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.
- package/dist/{agent-tool-types-OhWqAbCp.d.ts → agent-tool-types-BNUGGBzQ.d.ts} +30 -11
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-LdNKGZT9.d.ts → agent-tools-BFbzVLFc.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/browser/tanstack-ai.js +3 -2
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/chat/index.d.ts +29 -9
- package/dist/chat/index.js +32 -42
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +25 -1
- package/dist/chat/react.js +249 -93
- package/dist/chat/react.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/{client-C7F0MaVz.js → client-CcjiFpTf.js} +176 -42
- package/dist/client-CcjiFpTf.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/cloudflare-BldFV0Pa.js +117 -0
- package/dist/cloudflare-BldFV0Pa.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +118 -43
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/observability/ai/index.d.ts +155 -0
- package/dist/observability/ai/index.js +1848 -0
- package/dist/observability/ai/index.js.map +1 -0
- package/dist/react.d.ts +1 -1
- package/dist/{retries-CvHJwSuh.d.ts → retries-CAvxtG9d.d.ts} +16 -7
- package/dist/retries.d.ts +8 -6
- package/dist/retries.js +20 -2
- package/dist/retries.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/sub-routing.d.ts +1 -1
- package/dist/vite.d.ts +4 -4
- package/dist/vite.js +4 -2
- package/dist/vite.js.map +1 -1
- package/dist/{wire-types-nflOzNuU.js → wire-types-CU9rLoeS.js} +33 -2
- package/dist/wire-types-CU9rLoeS.js.map +1 -0
- package/dist/workflows.d.ts +1 -1
- package/docs/agent-class.md +9 -1
- package/docs/configuration.md +20 -0
- package/docs/mcp-client.md +13 -4
- package/docs/observability.md +282 -0
- package/package.json +11 -6
- package/dist/client-C7F0MaVz.js.map +0 -1
- package/dist/wire-types-nflOzNuU.js.map +0 -1
package/dist/chat-sdk/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
1323
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
1811
|
-
|
|
1812
|
-
const
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
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
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
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-
|
|
2119
|
+
//# sourceMappingURL=client-CcjiFpTf.js.map
|