agents 0.17.4 → 0.19.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 (48) hide show
  1. package/dist/{agent-tool-types-OhWqAbCp.d.ts → agent-tool-types-BNUGGBzQ.d.ts} +30 -11
  2. package/dist/agent-tool-types.d.ts +1 -1
  3. package/dist/{agent-tools-LdNKGZT9.d.ts → agent-tools-BFbzVLFc.d.ts} +2 -2
  4. package/dist/agent-tools.d.ts +1 -1
  5. package/dist/browser/tanstack-ai.js +3 -2
  6. package/dist/browser/tanstack-ai.js.map +1 -1
  7. package/dist/chat/index.d.ts +29 -9
  8. package/dist/chat/index.js +32 -42
  9. package/dist/chat/index.js.map +1 -1
  10. package/dist/chat/react.d.ts +25 -1
  11. package/dist/chat/react.js +249 -93
  12. package/dist/chat/react.js.map +1 -1
  13. package/dist/chat-sdk/index.d.ts +1 -1
  14. package/dist/{client-C7F0MaVz.js → client-CcjiFpTf.js} +176 -42
  15. package/dist/client-CcjiFpTf.js.map +1 -0
  16. package/dist/client.d.ts +1 -1
  17. package/dist/cloudflare-BldFV0Pa.js +117 -0
  18. package/dist/cloudflare-BldFV0Pa.js.map +1 -0
  19. package/dist/index.d.ts +5 -3
  20. package/dist/index.js +118 -43
  21. package/dist/index.js.map +1 -1
  22. package/dist/mcp/client.d.ts +1 -1
  23. package/dist/mcp/client.js +1 -1
  24. package/dist/mcp/index.d.ts +1 -1
  25. package/dist/mcp/index.js +1 -1
  26. package/dist/observability/ai/index.d.ts +155 -0
  27. package/dist/observability/ai/index.js +1848 -0
  28. package/dist/observability/ai/index.js.map +1 -0
  29. package/dist/react.d.ts +1 -1
  30. package/dist/{retries-CvHJwSuh.d.ts → retries-CAvxtG9d.d.ts} +16 -7
  31. package/dist/retries.d.ts +8 -6
  32. package/dist/retries.js +20 -2
  33. package/dist/retries.js.map +1 -1
  34. package/dist/serializable.d.ts +1 -1
  35. package/dist/sub-routing.d.ts +1 -1
  36. package/dist/vite.d.ts +4 -4
  37. package/dist/vite.js +4 -2
  38. package/dist/vite.js.map +1 -1
  39. package/dist/{wire-types-nflOzNuU.js → wire-types-CU9rLoeS.js} +33 -2
  40. package/dist/wire-types-CU9rLoeS.js.map +1 -0
  41. package/dist/workflows.d.ts +1 -1
  42. package/docs/agent-class.md +9 -1
  43. package/docs/configuration.md +20 -0
  44. package/docs/mcp-client.md +13 -4
  45. package/docs/observability.md +282 -0
  46. package/package.json +11 -6
  47. package/dist/client-C7F0MaVz.js.map +0 -1
  48. package/dist/wire-types-nflOzNuU.js.map +0 -1
@@ -2,7 +2,7 @@ import {
2
2
  O as Agent,
3
3
  ct as SubAgentClass,
4
4
  lt as SubAgentStub
5
- } from "../agent-tool-types-OhWqAbCp.js";
5
+ } from "../agent-tool-types-BNUGGBzQ.js";
6
6
  import { Lock, QueueEntry, StateAdapter } from "chat";
7
7
 
8
8
  //#region src/chat-sdk/agent.d.ts
@@ -6,7 +6,7 @@ import { z } from "zod";
6
6
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
7
7
  import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/cfworker-provider.js";
8
8
  import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
9
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
9
+ import { StreamableHTTPClientTransport, StreamableHTTPError } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
10
10
  import { ElicitRequestSchema, JSONRPCMessageSchema, PromptListChangedNotificationSchema, ResourceListChangedNotificationSchema, ToolListChangedNotificationSchema, isJSONRPCErrorResponse, isJSONRPCResultResponse } from "@modelcontextprotocol/sdk/types.js";
11
11
  //#region src/core/events.ts
12
12
  function toDisposable(fn) {
@@ -550,6 +550,7 @@ var MCPClientConnection = class {
550
550
  });
551
551
  return {
552
552
  success: false,
553
+ reason: "error",
553
554
  error: `Discovery skipped - connection in ${this.connectionState} state`
554
555
  };
555
556
  }
@@ -587,9 +588,11 @@ var MCPClientConnection = class {
587
588
  } catch (e) {
588
589
  if (timeoutId !== void 0) clearTimeout(timeoutId);
589
590
  this.connectionState = MCPConnectionState.CONNECTED;
591
+ const error = e instanceof Error ? e.message : String(e);
590
592
  return {
591
593
  success: false,
592
- error: e instanceof Error ? e.message : String(e)
594
+ reason: this._probingCapabilities && e instanceof StreamableHTTPError && e.code === 404 ? "stale-session" : "error",
595
+ error
593
596
  };
594
597
  } finally {
595
598
  this._discoveryAbortController = void 0;
@@ -695,6 +698,10 @@ var MCPClientConnection = class {
695
698
  get sessionId() {
696
699
  if (this._transport instanceof StreamableHTTPClientTransport) return this._transport.sessionId;
697
700
  }
701
+ /** @internal Clear a restored session before reconnecting. */
702
+ clearResumedSession() {
703
+ if ("sessionId" in this.options.transport) delete this.options.transport.sessionId;
704
+ }
698
705
  getTransportName(transport) {
699
706
  if (transport instanceof StreamableHTTPClientTransport) return "streamable-http";
700
707
  if (transport instanceof SSEClientTransport) return "sse";
@@ -935,6 +942,13 @@ function isBlockedUrl(url) {
935
942
  }
936
943
  return false;
937
944
  }
945
+ /** Converts a resolved connection failure into a retry signal. */
946
+ var ConnectRetryError = class extends Error {
947
+ constructor(result) {
948
+ super("MCP connection attempt failed");
949
+ this.result = result;
950
+ }
951
+ };
938
952
  /**
939
953
  * Utility class that aggregates multiple MCP clients into one
940
954
  */
@@ -948,6 +962,7 @@ var MCPClientManager = class {
948
962
  this._name = _name;
949
963
  this._version = _version;
950
964
  this.mcpConnections = {};
965
+ this._aiToolSchemas = /* @__PURE__ */ new WeakMap();
951
966
  this._didWarnAboutUnstableGetAITools = false;
952
967
  this._connectionDisposables = /* @__PURE__ */ new Map();
953
968
  this._isRestored = false;
@@ -1007,6 +1022,11 @@ var MCPClientManager = class {
1007
1022
  */
1008
1023
  async migrateServerId(oldId, newId, clientName) {
1009
1024
  if (oldId === newId) return;
1025
+ while (true) {
1026
+ const pending = this._pendingConnections.get(oldId);
1027
+ if (!pending) break;
1028
+ await pending.catch(() => {});
1029
+ }
1010
1030
  if (this.sql("SELECT id FROM cf_agents_mcp_servers WHERE id = ?", oldId).length === 0) {
1011
1031
  this._renameInMemoryConnection(oldId, newId);
1012
1032
  return;
@@ -1153,6 +1173,22 @@ var MCPClientManager = class {
1153
1173
  if (authProvider.runWithCodeVerifierState) return authProvider.runWithCodeVerifierState(state, callback);
1154
1174
  return callback();
1155
1175
  }
1176
+ async hasRedeemableOAuthState(serverId, authProvider, state) {
1177
+ authProvider.serverId = serverId;
1178
+ try {
1179
+ return (await authProvider.checkState(state)).valid;
1180
+ } catch {
1181
+ return false;
1182
+ }
1183
+ }
1184
+ ignoreUnverifiedCallback(serverId, error) {
1185
+ console.warn(`[MCPClientManager] Ignoring OAuth callback with unverified state for server "${serverId}": ${error}`);
1186
+ return {
1187
+ serverId,
1188
+ authSuccess: false,
1189
+ authError: error
1190
+ };
1191
+ }
1156
1192
  async consumeStaleOAuthState(serverId, authProvider, state) {
1157
1193
  try {
1158
1194
  const stateValidation = await authProvider.checkState(state);
@@ -1315,16 +1351,30 @@ var MCPClientManager = class {
1315
1351
  clearTimeout(timerId);
1316
1352
  } else await settled;
1317
1353
  }
1354
+ async _connectWithRetry(serverId, retry) {
1355
+ const maxAttempts = retry?.maxAttempts ?? 3;
1356
+ const baseDelayMs = retry?.baseDelayMs ?? 500;
1357
+ const maxDelayMs = retry?.maxDelayMs ?? 5e3;
1358
+ try {
1359
+ return await tryN(maxAttempts, async () => {
1360
+ const result = await this.connectToServer(serverId);
1361
+ if (result.state === MCPConnectionState.FAILED) throw new ConnectRetryError(result);
1362
+ return result;
1363
+ }, {
1364
+ baseDelayMs,
1365
+ maxDelayMs
1366
+ });
1367
+ } catch (error) {
1368
+ if (error instanceof ConnectRetryError) return error.result;
1369
+ throw error;
1370
+ }
1371
+ }
1318
1372
  /**
1319
1373
  * Internal method to restore a single server connection and discovery
1320
1374
  */
1321
1375
  async _restoreServer(serverId, retry) {
1322
- const maxAttempts = retry?.maxAttempts ?? 3;
1323
- if ((await tryN(maxAttempts, async () => this.connectToServer(serverId), {
1324
- baseDelayMs: retry?.baseDelayMs ?? 500,
1325
- maxDelayMs: retry?.maxDelayMs ?? 5e3
1326
- }).catch((error) => {
1327
- console.error(`Error connecting to ${serverId} after ${maxAttempts} attempts:`, error);
1376
+ if ((await this._connectWithRetry(serverId, retry).catch((error) => {
1377
+ console.error(`Error connecting to ${serverId}:`, error);
1328
1378
  return null;
1329
1379
  }))?.state === MCPConnectionState.CONNECTED) {
1330
1380
  const discoverResult = await this.discoverIfConnected(serverId);
@@ -1349,7 +1399,12 @@ var MCPClientManager = class {
1349
1399
  }
1350
1400
  if (isBlockedUrl(url)) throw new Error(`Blocked URL: ${url} — MCP client connections to private/internal addresses are not allowed`);
1351
1401
  if (!options.reconnect?.oauthCode || !this.mcpConnections[id]) {
1352
- delete this.mcpConnections[id];
1402
+ const replaced = this.mcpConnections[id];
1403
+ if (replaced) {
1404
+ delete this.mcpConnections[id];
1405
+ await replaced.close().catch(() => {});
1406
+ this.updateStoredSessionId(id, void 0);
1407
+ }
1353
1408
  this.createConnection(id, url, {
1354
1409
  client: options.client,
1355
1410
  transport: options.transport ?? {}
@@ -1613,6 +1668,8 @@ var MCPClientManager = class {
1613
1668
  }
1614
1669
  return this.oauthCallbackSuccess(validation.serverId, conn);
1615
1670
  }
1671
+ const authProvider = conn.options.transport.authProvider;
1672
+ if (validation.state && authProvider && !await this.hasRedeemableOAuthState(validation.serverId, authProvider, validation.state)) return this.ignoreUnverifiedCallback(validation.serverId, validation.error);
1616
1673
  return this.failConnection(validation.serverId, validation.error);
1617
1674
  }
1618
1675
  return {
@@ -1633,13 +1690,13 @@ var MCPClientManager = class {
1633
1690
  await this.consumeStaleOAuthState(serverId, authProvider, state);
1634
1691
  return this.oauthCallbackSuccess(serverId, conn);
1635
1692
  }
1636
- throw new Error(stateValidation.error || "Invalid state");
1693
+ return this.ignoreUnverifiedCallback(serverId, stateValidation.error || "Invalid state");
1637
1694
  }
1638
1695
  if (this.isAuthAcceptedConnection(conn)) {
1639
1696
  await this.consumeStaleOAuthState(serverId, authProvider, state);
1640
1697
  return this.oauthCallbackSuccess(serverId, conn);
1641
1698
  }
1642
- if (conn.connectionState !== MCPConnectionState.AUTHENTICATING) throw new Error(`Failed to authenticate: the client is in "${conn.connectionState}" state, expected "authenticating"`);
1699
+ if (conn.connectionState !== MCPConnectionState.AUTHENTICATING && conn.connectionState !== MCPConnectionState.FAILED) throw new Error(`Failed to authenticate from "${conn.connectionState}" state`);
1643
1700
  conn.connectionState = MCPConnectionState.CONNECTING;
1644
1701
  await authProvider.consumeState(state);
1645
1702
  await this.completeAuthorizationAndCleanupVerifier(serverId, conn, authProvider, state, code);
@@ -1676,11 +1733,41 @@ var MCPClientManager = class {
1676
1733
  return;
1677
1734
  }
1678
1735
  const result = await conn.discover(options);
1736
+ if (!result.success && result.reason === "stale-session") return this._recoverStaleSession(conn, serverId, options);
1679
1737
  this._onServerStateChanged.fire();
1680
- return {
1681
- ...result,
1738
+ return this._toDiscoverResult(conn, result);
1739
+ }
1740
+ _toDiscoverResult(conn, result) {
1741
+ return result.success ? {
1742
+ success: true,
1743
+ state: conn.connectionState
1744
+ } : {
1745
+ success: false,
1746
+ error: result.error,
1747
+ state: conn.connectionState
1748
+ };
1749
+ }
1750
+ async _recoverStaleSession(conn, serverId, options) {
1751
+ conn.clearResumedSession();
1752
+ this.updateStoredSessionId(serverId, void 0);
1753
+ let connectResult;
1754
+ try {
1755
+ connectResult = await this.connectToServer(serverId);
1756
+ } catch (error) {
1757
+ return {
1758
+ success: false,
1759
+ error: toErrorMessage(error),
1760
+ state: conn.connectionState
1761
+ };
1762
+ }
1763
+ if (connectResult.state !== MCPConnectionState.CONNECTED) return {
1764
+ success: false,
1765
+ error: connectResult.state === MCPConnectionState.FAILED ? connectResult.error : `Connection in ${connectResult.state} state after session re-initialization`,
1682
1766
  state: conn.connectionState
1683
1767
  };
1768
+ const result = await conn.discover(options);
1769
+ this._onServerStateChanged.fire();
1770
+ return this._toDiscoverResult(conn, result);
1684
1771
  }
1685
1772
  /**
1686
1773
  * Establish connection in the background after OAuth completion.
@@ -1717,10 +1804,7 @@ var MCPClientManager = class {
1717
1804
  return;
1718
1805
  }
1719
1806
  const retry = this.getServerRetryOptions(serverId);
1720
- const connectResult = await tryN(retry?.maxAttempts ?? 3, async () => this.connectToServer(serverId), {
1721
- baseDelayMs: retry?.baseDelayMs ?? 500,
1722
- maxDelayMs: retry?.maxDelayMs ?? 5e3
1723
- });
1807
+ const connectResult = await this._connectWithRetry(serverId, retry);
1724
1808
  this._onServerStateChanged.fire();
1725
1809
  if (connectResult.state === MCPConnectionState.CONNECTED) await this.discoverIfConnected(serverId);
1726
1810
  this._onObservabilityEvent.fire({
@@ -1800,37 +1884,87 @@ var MCPClientManager = class {
1800
1884
  return getNamespacedData(this.filterConnections(filter), "tools");
1801
1885
  }
1802
1886
  /**
1887
+ * Convert connected MCP tools for the AI SDK. Converted schemas are reused
1888
+ * while a live connection retains the same catalog array and schema-source
1889
+ * identities; tool records and execute closures are rebuilt on every call.
1890
+ *
1803
1891
  * @param filter - Optional filter to scope results to specific servers
1804
1892
  * @returns a set of tools that you can use with the AI SDK
1805
1893
  */
1806
1894
  getAITools(filter) {
1807
1895
  const connections = this.filterConnections(filter);
1808
- 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.`);
1809
1896
  const entries = [];
1810
- for (const tool of getNamespacedData(connections, "tools")) try {
1811
- const toolKey = `tool_${tool.serverId.replace(/-/g, "")}_${tool.name}`;
1812
- const title = tool.title ?? tool.annotations?.title;
1813
- entries.push([toolKey, {
1814
- description: tool.description,
1815
- title,
1816
- execute: async (args) => {
1817
- const result = await this.callTool({
1818
- arguments: args,
1819
- name: tool.name,
1820
- serverId: tool.serverId
1821
- });
1822
- if (result.isError) {
1823
- const textContent = result.content?.[0];
1824
- const message = textContent?.type === "text" && textContent.text ? textContent.text : "Tool call failed";
1825
- throw new Error(message);
1897
+ for (const [serverId, conn] of Object.entries(connections)) {
1898
+ if (conn.connectionState !== MCPConnectionState.READY && conn.connectionState !== MCPConnectionState.AUTHENTICATING) console.warn(`[getAITools] WARNING: Reading tools from connection ${serverId} in state "${conn.connectionState}". Tools may not be loaded yet.`);
1899
+ const catalog = conn.tools;
1900
+ let cache = this._aiToolSchemas.get(conn);
1901
+ if (!cache || cache.catalog !== catalog) {
1902
+ cache = {
1903
+ catalog,
1904
+ converted: []
1905
+ };
1906
+ this._aiToolSchemas.set(conn, cache);
1907
+ }
1908
+ for (const [index, tool] of catalog.entries()) {
1909
+ const toolName = tool.name;
1910
+ try {
1911
+ const sourceInputSchema = tool.inputSchema;
1912
+ const sourceOutputSchema = tool.outputSchema;
1913
+ let slot = cache.converted[index];
1914
+ if (!slot || slot.tool !== tool || slot.inputSchema !== sourceInputSchema || slot.outputSchema !== sourceOutputSchema) {
1915
+ try {
1916
+ slot = {
1917
+ status: "converted",
1918
+ tool,
1919
+ inputSchema: sourceInputSchema,
1920
+ outputSchema: sourceOutputSchema,
1921
+ converted: {
1922
+ inputSchema: sourceInputSchema ? z.fromJSONSchema(sourceInputSchema) : z.fromJSONSchema({ type: "object" }),
1923
+ outputSchema: sourceOutputSchema ? z.fromJSONSchema(sourceOutputSchema) : void 0
1924
+ }
1925
+ };
1926
+ } catch (error) {
1927
+ const errorText = String(error);
1928
+ cache.converted[index] = {
1929
+ status: "failed",
1930
+ tool,
1931
+ inputSchema: sourceInputSchema,
1932
+ outputSchema: sourceOutputSchema,
1933
+ error: errorText
1934
+ };
1935
+ console.warn(`[getAITools] Skipping tool "${toolName}" from "${serverId}": ${errorText}`);
1936
+ continue;
1937
+ }
1938
+ cache.converted[index] = slot;
1826
1939
  }
1827
- return result;
1828
- },
1829
- inputSchema: tool.inputSchema ? z.fromJSONSchema(tool.inputSchema) : z.fromJSONSchema({ type: "object" }),
1830
- outputSchema: tool.outputSchema ? z.fromJSONSchema(tool.outputSchema) : void 0
1831
- }]);
1832
- } catch (e) {
1833
- console.warn(`[getAITools] Skipping tool "${tool.name}" from "${tool.serverId}": ${e}`);
1940
+ if (slot.status === "failed") continue;
1941
+ const toolKey = `tool_${serverId.replace(/-/g, "")}_${toolName}`;
1942
+ const title = tool.title ?? tool.annotations?.title;
1943
+ const description = tool.description;
1944
+ entries.push([toolKey, {
1945
+ description,
1946
+ title,
1947
+ execute: async (args) => {
1948
+ const result = await this.callTool({
1949
+ arguments: args,
1950
+ name: toolName,
1951
+ serverId
1952
+ });
1953
+ if (result.isError) {
1954
+ const textContent = result.content?.[0];
1955
+ const message = textContent?.type === "text" && textContent.text ? textContent.text : "Tool call failed";
1956
+ throw new Error(message);
1957
+ }
1958
+ return result;
1959
+ },
1960
+ inputSchema: slot.converted.inputSchema,
1961
+ outputSchema: slot.converted.outputSchema
1962
+ }]);
1963
+ } catch (error) {
1964
+ console.warn(`[getAITools] Skipping tool "${toolName}" from "${serverId}": ${error}`);
1965
+ }
1966
+ }
1967
+ cache.converted.length = catalog.length;
1834
1968
  }
1835
1969
  return Object.fromEntries(entries);
1836
1970
  }
@@ -1982,4 +2116,4 @@ function getNamespacedData(mcpClients, type) {
1982
2116
  //#endregion
1983
2117
  export { MCPConnectionState as a, RPC_DO_PREFIX as c, normalizeServerId as i, DisposableStore as l, MCP_SERVER_ID_MAX_LENGTH as n, RPCClientTransport as o, getNamespacedData as r, RPCServerTransport as s, MCPClientManager as t };
1984
2118
 
1985
- //# sourceMappingURL=client-C7F0MaVz.js.map
2119
+ //# sourceMappingURL=client-CcjiFpTf.js.map