@t2000/engine 0.46.4 → 0.46.6
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.d.ts +18 -1
- package/dist/index.js +277 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1598,13 +1598,17 @@ interface AnthropicProviderConfig {
|
|
|
1598
1598
|
apiKey: string;
|
|
1599
1599
|
defaultModel?: string;
|
|
1600
1600
|
defaultMaxTokens?: number;
|
|
1601
|
+
/** Max retry attempts for retriable errors (overloaded, rate-limited, network). Default 3. */
|
|
1602
|
+
maxRetries?: number;
|
|
1601
1603
|
}
|
|
1602
1604
|
declare class AnthropicProvider implements LLMProvider {
|
|
1603
1605
|
private client;
|
|
1604
1606
|
private defaultModel;
|
|
1605
1607
|
private defaultMaxTokens;
|
|
1608
|
+
private maxRetries;
|
|
1606
1609
|
constructor(config: AnthropicProviderConfig);
|
|
1607
1610
|
chat(params: ChatParams): AsyncGenerator<ProviderEvent>;
|
|
1611
|
+
private streamOnce;
|
|
1608
1612
|
}
|
|
1609
1613
|
|
|
1610
1614
|
declare const CANVAS_TEMPLATES: readonly ["activity_heatmap", "portfolio_timeline", "yield_projector", "health_simulator", "dca_planner", "spending_breakdown", "watch_address", "full_portfolio"];
|
|
@@ -1640,12 +1644,23 @@ declare const healthCheckTool: Tool<{}, {
|
|
|
1640
1644
|
status: string;
|
|
1641
1645
|
}>;
|
|
1642
1646
|
|
|
1643
|
-
|
|
1647
|
+
type RateMap = Record<string, {
|
|
1648
|
+
saveApy: number;
|
|
1649
|
+
borrowApy: number;
|
|
1650
|
+
}>;
|
|
1651
|
+
declare const ratesInfoTool: Tool<{
|
|
1652
|
+
assets?: string[] | undefined;
|
|
1653
|
+
stableOnly?: boolean | undefined;
|
|
1654
|
+
topN?: number | undefined;
|
|
1655
|
+
}, RateMap>;
|
|
1644
1656
|
|
|
1645
1657
|
declare const transactionHistoryTool: Tool<{
|
|
1646
1658
|
action?: "send" | "swap" | "transaction" | "lending" | undefined;
|
|
1647
1659
|
date?: string | undefined;
|
|
1660
|
+
direction?: "out" | "in" | undefined;
|
|
1648
1661
|
limit?: number | undefined;
|
|
1662
|
+
minUsd?: number | undefined;
|
|
1663
|
+
assetSymbol?: string | undefined;
|
|
1649
1664
|
}, Record<string, unknown>>;
|
|
1650
1665
|
|
|
1651
1666
|
declare const saveDepositTool: Tool<{
|
|
@@ -1739,6 +1754,7 @@ declare const payApiTool: Tool<{
|
|
|
1739
1754
|
declare const mppServicesTool: Tool<{
|
|
1740
1755
|
query?: string | undefined;
|
|
1741
1756
|
category?: string | undefined;
|
|
1757
|
+
mode?: "summary" | "full" | undefined;
|
|
1742
1758
|
}, Record<string, unknown>>;
|
|
1743
1759
|
|
|
1744
1760
|
declare const swapExecuteTool: Tool<{
|
|
@@ -1926,6 +1942,7 @@ declare const activitySummaryTool: Tool<{
|
|
|
1926
1942
|
}, ActivitySummary>;
|
|
1927
1943
|
|
|
1928
1944
|
declare const defillamaYieldPoolsTool: Tool<{
|
|
1945
|
+
stableOnly?: boolean | undefined;
|
|
1929
1946
|
limit?: number | undefined;
|
|
1930
1947
|
chain?: string | undefined;
|
|
1931
1948
|
project?: string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -977,6 +977,36 @@ var healthCheckTool = buildTool({
|
|
|
977
977
|
}
|
|
978
978
|
});
|
|
979
979
|
var YIELDS_API = "https://yields.llama.fi";
|
|
980
|
+
var STABLECOIN_SYMBOLS2 = /* @__PURE__ */ new Set([
|
|
981
|
+
"usdc",
|
|
982
|
+
"wusdc",
|
|
983
|
+
"usdt",
|
|
984
|
+
"wusdt",
|
|
985
|
+
"suiusdt",
|
|
986
|
+
"usdy",
|
|
987
|
+
"usdsui",
|
|
988
|
+
"usde",
|
|
989
|
+
"ausd",
|
|
990
|
+
"fdusd",
|
|
991
|
+
"buck"
|
|
992
|
+
]);
|
|
993
|
+
function isStable(symbol) {
|
|
994
|
+
return STABLECOIN_SYMBOLS2.has(symbol.toLowerCase());
|
|
995
|
+
}
|
|
996
|
+
function applyFilters(rates, opts) {
|
|
997
|
+
let entries = Object.entries(rates);
|
|
998
|
+
if (opts.assets && opts.assets.length) {
|
|
999
|
+
const wanted = new Set(opts.assets.map((a) => a.toLowerCase()));
|
|
1000
|
+
entries = entries.filter(([sym]) => wanted.has(sym.toLowerCase()));
|
|
1001
|
+
} else if (opts.stableOnly) {
|
|
1002
|
+
entries = entries.filter(([sym]) => isStable(sym));
|
|
1003
|
+
}
|
|
1004
|
+
entries.sort(([, a], [, b]) => b.saveApy - a.saveApy);
|
|
1005
|
+
if (opts.topN && opts.topN > 0) {
|
|
1006
|
+
entries = entries.slice(0, opts.topN);
|
|
1007
|
+
}
|
|
1008
|
+
return Object.fromEntries(entries);
|
|
1009
|
+
}
|
|
980
1010
|
function formatRatesSummary(rates) {
|
|
981
1011
|
return Object.entries(rates).map(([asset, r]) => `${asset}: Save ${(r.saveApy * 100).toFixed(2)}% / Borrow ${(r.borrowApy * 100).toFixed(2)}%`).join(", ");
|
|
982
1012
|
}
|
|
@@ -997,22 +1027,52 @@ async function fetchRatesFromDefiLlama() {
|
|
|
997
1027
|
}
|
|
998
1028
|
var ratesInfoTool = buildTool({
|
|
999
1029
|
name: "rates_info",
|
|
1000
|
-
description:
|
|
1001
|
-
inputSchema: z.object({
|
|
1002
|
-
|
|
1030
|
+
description: 'NAVI Protocol lending markets ONLY (single-sided save/borrow, no impermanent-loss risk). Use this for stablecoin and bluechip lending yields. Renders a rich rates card. Filter args: `assets` (specific symbols like ["USDC"]), `stableOnly` (true to show only USD-pegged assets), `topN` (max rows in card, default 8, max 50). Do NOT call defillama_yield_pools in the same turn \u2014 that tool is for LP/farming pools with IL risk, not lending.',
|
|
1031
|
+
inputSchema: z.object({
|
|
1032
|
+
assets: z.array(z.string()).optional().describe('Filter to specific asset symbols (e.g. ["USDC"], ["USDC","USDT","USDSUI"]). Case-insensitive.'),
|
|
1033
|
+
stableOnly: z.boolean().optional().describe("When true, return only stablecoin markets (USDC, USDT, USDSUI, USDY, suiUSDT, etc.). Ignored when `assets` is supplied."),
|
|
1034
|
+
topN: z.number().int().min(1).max(50).optional().describe("Cap the number of rows in the card (default 8). Use 50 to render the full NAVI catalog.")
|
|
1035
|
+
}),
|
|
1036
|
+
jsonSchema: {
|
|
1037
|
+
type: "object",
|
|
1038
|
+
properties: {
|
|
1039
|
+
assets: {
|
|
1040
|
+
type: "array",
|
|
1041
|
+
items: { type: "string" },
|
|
1042
|
+
description: "Filter to specific asset symbols (case-insensitive)."
|
|
1043
|
+
},
|
|
1044
|
+
stableOnly: {
|
|
1045
|
+
type: "boolean",
|
|
1046
|
+
description: "When true, return only stablecoin markets. Ignored when `assets` is supplied."
|
|
1047
|
+
},
|
|
1048
|
+
topN: {
|
|
1049
|
+
type: "number",
|
|
1050
|
+
description: "Cap the number of rows in the card (default 8, max 50)."
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1053
|
+
required: []
|
|
1054
|
+
},
|
|
1003
1055
|
isReadOnly: true,
|
|
1004
|
-
async call(
|
|
1056
|
+
async call(input, context) {
|
|
1057
|
+
const opts = {
|
|
1058
|
+
assets: input.assets,
|
|
1059
|
+
stableOnly: input.stableOnly,
|
|
1060
|
+
topN: input.topN ?? 8
|
|
1061
|
+
};
|
|
1005
1062
|
if (hasNaviMcpGlobal(context)) {
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1063
|
+
const all2 = await fetchRates(getMcpManager(context));
|
|
1064
|
+
const filtered2 = applyFilters(all2, opts);
|
|
1065
|
+
return { data: filtered2, displayText: formatRatesSummary(filtered2) };
|
|
1008
1066
|
}
|
|
1009
1067
|
if (hasAgent(context)) {
|
|
1010
1068
|
const agent = requireAgent(context);
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1069
|
+
const all2 = await agent.rates();
|
|
1070
|
+
const filtered2 = applyFilters(all2, opts);
|
|
1071
|
+
return { data: filtered2, displayText: formatRatesSummary(filtered2) };
|
|
1013
1072
|
}
|
|
1014
|
-
const
|
|
1015
|
-
|
|
1073
|
+
const all = await fetchRatesFromDefiLlama();
|
|
1074
|
+
const filtered = applyFilters(all, opts);
|
|
1075
|
+
return { data: filtered, displayText: formatRatesSummary(filtered) };
|
|
1016
1076
|
}
|
|
1017
1077
|
});
|
|
1018
1078
|
function parseRpcTx(tx, address) {
|
|
@@ -1114,11 +1174,14 @@ var HISTORY_ACTIONS = ["send", "lending", "swap", "transaction"];
|
|
|
1114
1174
|
var DEFAULT_LOOKBACK_DAYS = 30;
|
|
1115
1175
|
var transactionHistoryTool = buildTool({
|
|
1116
1176
|
name: "transaction_history",
|
|
1117
|
-
description:
|
|
1177
|
+
description: 'Retrieve recent transaction history (last 30 days by default): sends, saves, withdrawals, borrows, repayments, swaps, and rewards claims. Renders a rich transaction card. Filter args: `date` (YYYY-MM-DD), `action` (send/lending/swap), `minUsd` (minimum amount in USD \u2014 use this for "transactions over $X" instead of post-filtering), `assetSymbol` (e.g. "USDC", "SUI"), `direction` ("in" or "out"). The card itself respects all filters \u2014 never re-list the rows in narration.',
|
|
1118
1178
|
inputSchema: z.object({
|
|
1119
1179
|
limit: z.number().int().min(1).max(50).optional(),
|
|
1120
1180
|
date: z.string().optional().describe("Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day."),
|
|
1121
|
-
action: z.enum(HISTORY_ACTIONS).optional().describe("Filter by action: send, lending, swap, or transaction.")
|
|
1181
|
+
action: z.enum(HISTORY_ACTIONS).optional().describe("Filter by action: send, lending, swap, or transaction."),
|
|
1182
|
+
minUsd: z.number().min(0).optional().describe('Minimum transaction amount in USD. Use this for "transactions over $X" \u2014 the amount is converted to USD using the asset price snapshot.'),
|
|
1183
|
+
assetSymbol: z.string().optional().describe('Filter to a single asset symbol (case-insensitive, e.g. "USDC", "SUI", "LOFI"). Matches `tx.asset` exactly.'),
|
|
1184
|
+
direction: z.enum(["in", "out"]).optional().describe('Filter by user-side balance flow: "in" = received, "out" = spent.')
|
|
1122
1185
|
}),
|
|
1123
1186
|
jsonSchema: {
|
|
1124
1187
|
type: "object",
|
|
@@ -1135,6 +1198,19 @@ var transactionHistoryTool = buildTool({
|
|
|
1135
1198
|
type: "string",
|
|
1136
1199
|
enum: [...HISTORY_ACTIONS],
|
|
1137
1200
|
description: "Filter results by action category: send, lending, swap, or transaction."
|
|
1201
|
+
},
|
|
1202
|
+
minUsd: {
|
|
1203
|
+
type: "number",
|
|
1204
|
+
description: 'Minimum transaction amount in USD. Use this for "transactions over $X" queries.'
|
|
1205
|
+
},
|
|
1206
|
+
assetSymbol: {
|
|
1207
|
+
type: "string",
|
|
1208
|
+
description: 'Filter to a single asset symbol (case-insensitive, e.g. "USDC", "SUI").'
|
|
1209
|
+
},
|
|
1210
|
+
direction: {
|
|
1211
|
+
type: "string",
|
|
1212
|
+
enum: ["in", "out"],
|
|
1213
|
+
description: 'Filter by direction of user balance change: "in" = received, "out" = spent.'
|
|
1138
1214
|
}
|
|
1139
1215
|
}
|
|
1140
1216
|
},
|
|
@@ -1183,17 +1259,48 @@ var transactionHistoryTool = buildTool({
|
|
|
1183
1259
|
async call(input, context) {
|
|
1184
1260
|
const limit = input.limit ?? 10;
|
|
1185
1261
|
const action = input.action;
|
|
1262
|
+
const assetSymbol = input.assetSymbol?.toLowerCase();
|
|
1263
|
+
const direction = input.direction;
|
|
1264
|
+
const minUsd = input.minUsd;
|
|
1265
|
+
const prices = context.tokenPrices;
|
|
1266
|
+
const priceFor = (sym) => {
|
|
1267
|
+
if (!sym || !prices) return void 0;
|
|
1268
|
+
return prices[sym.toUpperCase()] ?? prices[sym.toLowerCase()] ?? prices[sym];
|
|
1269
|
+
};
|
|
1186
1270
|
const finalize = (records2) => {
|
|
1187
1271
|
let scoped = records2;
|
|
1188
1272
|
if (action) scoped = scoped.filter((r) => r.action === action);
|
|
1273
|
+
if (assetSymbol) {
|
|
1274
|
+
scoped = scoped.filter((r) => r.asset?.toLowerCase() === assetSymbol);
|
|
1275
|
+
}
|
|
1276
|
+
if (direction) {
|
|
1277
|
+
scoped = scoped.filter((r) => r.direction === direction);
|
|
1278
|
+
}
|
|
1279
|
+
if (minUsd != null && minUsd > 0) {
|
|
1280
|
+
scoped = scoped.filter((r) => {
|
|
1281
|
+
if (r.amount == null) return false;
|
|
1282
|
+
const sym = r.asset?.toUpperCase() ?? "";
|
|
1283
|
+
const isStableLike = sym === "USDC" || sym === "USDT" || sym === "WUSDC" || sym === "WUSDT" || sym === "SUIUSDT" || sym === "USDY" || sym === "USDSUI" || sym === "USDE" || sym === "AUSD" || sym === "FDUSD" || sym === "BUCK";
|
|
1284
|
+
const usd = isStableLike ? r.amount : (priceFor(sym) ?? 0) * r.amount;
|
|
1285
|
+
if (!isStableLike && priceFor(sym) == null) return true;
|
|
1286
|
+
return usd >= minUsd;
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1189
1289
|
return scoped.slice(0, limit);
|
|
1190
1290
|
};
|
|
1291
|
+
const filterMeta = {
|
|
1292
|
+
date: input.date ?? null,
|
|
1293
|
+
action: action ?? null,
|
|
1294
|
+
minUsd: minUsd ?? null,
|
|
1295
|
+
assetSymbol: input.assetSymbol ?? null,
|
|
1296
|
+
direction: direction ?? null
|
|
1297
|
+
};
|
|
1191
1298
|
if (context.agent) {
|
|
1192
1299
|
const agent = requireAgent(context);
|
|
1193
1300
|
const records2 = await agent.history({ limit: input.date ? limit : Math.max(limit * 4, 50) });
|
|
1194
1301
|
const filtered2 = finalize(records2);
|
|
1195
1302
|
return {
|
|
1196
|
-
data: { transactions: filtered2, count: filtered2.length,
|
|
1303
|
+
data: { transactions: filtered2, count: filtered2.length, ...filterMeta },
|
|
1197
1304
|
displayText: `${filtered2.length} recent transaction(s)`
|
|
1198
1305
|
};
|
|
1199
1306
|
}
|
|
@@ -1210,7 +1317,7 @@ var transactionHistoryTool = buildTool({
|
|
|
1210
1317
|
const filtered2 = finalize(records2);
|
|
1211
1318
|
const dateLabel = new Date(input.date).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
|
|
1212
1319
|
return {
|
|
1213
|
-
data: { transactions: filtered2, count: filtered2.length,
|
|
1320
|
+
data: { transactions: filtered2, count: filtered2.length, ...filterMeta },
|
|
1214
1321
|
displayText: filtered2.length > 0 ? `${filtered2.length} transaction(s) on ${dateLabel}` : `No transactions found on ${dateLabel}`
|
|
1215
1322
|
};
|
|
1216
1323
|
}
|
|
@@ -1226,8 +1333,7 @@ var transactionHistoryTool = buildTool({
|
|
|
1226
1333
|
data: {
|
|
1227
1334
|
transactions: filtered,
|
|
1228
1335
|
count: filtered.length,
|
|
1229
|
-
|
|
1230
|
-
action: action ?? null,
|
|
1336
|
+
...filterMeta,
|
|
1231
1337
|
lookbackDays: DEFAULT_LOOKBACK_DAYS
|
|
1232
1338
|
},
|
|
1233
1339
|
displayText: `${filtered.length} transaction(s) in the last ${DEFAULT_LOOKBACK_DAYS} days`
|
|
@@ -1610,10 +1716,11 @@ function matchesQuery(service, q) {
|
|
|
1610
1716
|
}
|
|
1611
1717
|
var mppServicesTool = buildTool({
|
|
1612
1718
|
name: "mpp_services",
|
|
1613
|
-
description:
|
|
1719
|
+
description: 'Discover available MPP gateway services. Returns service names, descriptions, endpoints with required parameters, and pricing. Use BEFORE calling pay_api. Modes: pass `query` for keyword search, `category` to filter by category, or `mode: "full"` to fetch the ENTIRE catalog in one card (for "show me all MPP services" / "full catalog" requests \u2014 never enumerate per category in a loop). Calling with no args returns a category summary so you can narrow.',
|
|
1614
1720
|
inputSchema: z.object({
|
|
1615
1721
|
query: z.string().optional().describe('Filter by keyword (e.g. "postcard", "translate", "weather").'),
|
|
1616
|
-
category: z.string().optional().describe('Filter by category exactly (e.g. "weather", "image"). See category summary returned when called without filters.')
|
|
1722
|
+
category: z.string().optional().describe('Filter by category exactly (e.g. "weather", "image"). See category summary returned when called without filters.'),
|
|
1723
|
+
mode: z.enum(["summary", "full"]).optional().describe('"full" returns the entire catalog in a single card \u2014 use this for "show me all MPP services" / "full catalog" requests instead of looping per category. Default is "summary" (category counts only when no filter is supplied).')
|
|
1617
1724
|
}),
|
|
1618
1725
|
jsonSchema: {
|
|
1619
1726
|
type: "object",
|
|
@@ -1625,14 +1732,40 @@ var mppServicesTool = buildTool({
|
|
|
1625
1732
|
category: {
|
|
1626
1733
|
type: "string",
|
|
1627
1734
|
description: 'Filter by category exactly (e.g. "weather", "image").'
|
|
1735
|
+
},
|
|
1736
|
+
mode: {
|
|
1737
|
+
type: "string",
|
|
1738
|
+
enum: ["summary", "full"],
|
|
1739
|
+
description: '"full" returns the entire catalog in one card. Use for "show me all" requests.'
|
|
1628
1740
|
}
|
|
1629
1741
|
},
|
|
1630
1742
|
required: []
|
|
1631
1743
|
},
|
|
1632
1744
|
isReadOnly: true,
|
|
1633
|
-
|
|
1745
|
+
// [v0.46.6] Bumped to fit the full catalog (~40 services) in one
|
|
1746
|
+
// shot when `mode: 'full'` is used. The summarizeOnTruncate path
|
|
1747
|
+
// still applies if the catalog ever exceeds the budget.
|
|
1748
|
+
maxResultSizeChars: 12e3,
|
|
1634
1749
|
async call(input) {
|
|
1635
1750
|
const catalog = await fetchCatalog();
|
|
1751
|
+
if (input.mode === "full") {
|
|
1752
|
+
const services2 = catalog.map((s) => ({
|
|
1753
|
+
id: s.id,
|
|
1754
|
+
name: s.name,
|
|
1755
|
+
description: s.description,
|
|
1756
|
+
categories: s.categories,
|
|
1757
|
+
endpoints: s.endpoints.map((e) => ({
|
|
1758
|
+
url: `${MPP_GATEWAY2}/${s.id}${e.path}`,
|
|
1759
|
+
method: e.method,
|
|
1760
|
+
description: e.description,
|
|
1761
|
+
price: `$${e.price}`
|
|
1762
|
+
}))
|
|
1763
|
+
}));
|
|
1764
|
+
return {
|
|
1765
|
+
data: { services: services2, total: services2.length, mode: "full" },
|
|
1766
|
+
displayText: `Full MPP catalog: ${services2.length} services.`
|
|
1767
|
+
};
|
|
1768
|
+
}
|
|
1636
1769
|
if (!input.query && !input.category) {
|
|
1637
1770
|
const counts = /* @__PURE__ */ new Map();
|
|
1638
1771
|
for (const svc of catalog) {
|
|
@@ -1644,13 +1777,14 @@ var mppServicesTool = buildTool({
|
|
|
1644
1777
|
return {
|
|
1645
1778
|
data: {
|
|
1646
1779
|
_refine: {
|
|
1647
|
-
reason:
|
|
1648
|
-
suggestedParams: { category: categories[0]?.category ?? "weather" }
|
|
1780
|
+
reason: 'MPP catalog has many services \u2014 pick a category, supply a query, or pass mode:"full" to fetch everything.',
|
|
1781
|
+
suggestedParams: { category: categories[0]?.category ?? "weather" },
|
|
1782
|
+
allModes: ["summary", "full"]
|
|
1649
1783
|
},
|
|
1650
1784
|
categories,
|
|
1651
1785
|
totalServices: catalog.length
|
|
1652
1786
|
},
|
|
1653
|
-
displayText: `${catalog.length} services across ${categories.length} categories. Re-call with a category or
|
|
1787
|
+
displayText: `${catalog.length} services across ${categories.length} categories. Re-call with a category, query, or mode:"full".`
|
|
1654
1788
|
};
|
|
1655
1789
|
}
|
|
1656
1790
|
let filtered = catalog;
|
|
@@ -2933,22 +3067,44 @@ function fmtToolTvl(tvl) {
|
|
|
2933
3067
|
if (tvl >= 1e3) return `$${(tvl / 1e3).toFixed(0)}K`;
|
|
2934
3068
|
return `$${tvl}`;
|
|
2935
3069
|
}
|
|
3070
|
+
var POOL_STABLE_LEGS = /* @__PURE__ */ new Set([
|
|
3071
|
+
"USDC",
|
|
3072
|
+
"WUSDC",
|
|
3073
|
+
"USDT",
|
|
3074
|
+
"WUSDT",
|
|
3075
|
+
"SUIUSDT",
|
|
3076
|
+
"USDY",
|
|
3077
|
+
"USDSUI",
|
|
3078
|
+
"USDE",
|
|
3079
|
+
"AUSD",
|
|
3080
|
+
"FDUSD",
|
|
3081
|
+
"BUCK",
|
|
3082
|
+
"DAI",
|
|
3083
|
+
"LUSD",
|
|
3084
|
+
"FRAX",
|
|
3085
|
+
"GUSD",
|
|
3086
|
+
"PYUSD",
|
|
3087
|
+
"USDS",
|
|
3088
|
+
"CRVUSD"
|
|
3089
|
+
]);
|
|
2936
3090
|
var defillamaYieldPoolsTool = buildTool({
|
|
2937
3091
|
name: "defillama_yield_pools",
|
|
2938
|
-
description: '
|
|
3092
|
+
description: 'Cross-protocol LP / vault yields with IMPERMANENT-LOSS RISK (Cetus, Bluefin, Full Sail, etc.). ONLY call when the user explicitly asks about LP pools, DeFi farming, or "higher yield with more risk". For safe single-sided lending yields (USDC save, NAVI, etc.) use rates_info instead \u2014 NEVER both in the same turn. Filter by chain (e.g. "Sui"), project, and minimum TVL.',
|
|
2939
3093
|
inputSchema: z.object({
|
|
2940
3094
|
chain: z.string().optional().describe('Filter by chain name (e.g. "Sui", "Ethereum")'),
|
|
2941
|
-
project: z.string().optional().describe('Filter by protocol project name (e.g. "
|
|
3095
|
+
project: z.string().optional().describe('Filter by protocol project name (e.g. "cetus-clmm", "bluefin-spot")'),
|
|
2942
3096
|
limit: z.number().min(1).max(20).optional().describe("Max results (default 5)"),
|
|
2943
|
-
minTvl: z.number().optional().describe("Minimum TVL in USD to filter out small/risky pools (default 100000)")
|
|
3097
|
+
minTvl: z.number().optional().describe("Minimum TVL in USD to filter out small/risky pools (default 100000)"),
|
|
3098
|
+
stableOnly: z.boolean().optional().describe('When true, only return pools where every leg is a stablecoin (USDC, USDT, USDSUI, etc.). Use this for "show stablecoin yield options" \u2014 keeps volatile-pair LPs (WAL-SUI, DEEP-SUI) out.')
|
|
2944
3099
|
}),
|
|
2945
3100
|
jsonSchema: {
|
|
2946
3101
|
type: "object",
|
|
2947
3102
|
properties: {
|
|
2948
3103
|
chain: { type: "string", description: "Filter by chain name" },
|
|
2949
|
-
project: { type: "string", description: 'Filter by protocol project name (e.g. "
|
|
3104
|
+
project: { type: "string", description: 'Filter by protocol project name (e.g. "cetus-clmm")' },
|
|
2950
3105
|
limit: { type: "number", description: "Max results (default 5)" },
|
|
2951
|
-
minTvl: { type: "number", description: "Minimum TVL in USD (default 100000)" }
|
|
3106
|
+
minTvl: { type: "number", description: "Minimum TVL in USD (default 100000)" },
|
|
3107
|
+
stableOnly: { type: "boolean", description: "When true, only return all-stablecoin pools." }
|
|
2952
3108
|
},
|
|
2953
3109
|
required: []
|
|
2954
3110
|
},
|
|
@@ -2984,6 +3140,12 @@ var defillamaYieldPoolsTool = buildTool({
|
|
|
2984
3140
|
}
|
|
2985
3141
|
const minTvl = input.minTvl ?? 1e5;
|
|
2986
3142
|
pools = pools.filter((p) => p.tvlUsd >= minTvl);
|
|
3143
|
+
if (input.stableOnly) {
|
|
3144
|
+
pools = pools.filter((p) => {
|
|
3145
|
+
const legs = p.symbol.split("-");
|
|
3146
|
+
return legs.every((leg) => POOL_STABLE_LEGS.has(leg.trim().toUpperCase()));
|
|
3147
|
+
});
|
|
3148
|
+
}
|
|
2987
3149
|
pools.sort((a, b) => b.apy - a.apy);
|
|
2988
3150
|
const limit = input.limit ?? 5;
|
|
2989
3151
|
const top = pools.slice(0, limit);
|
|
@@ -5729,16 +5891,51 @@ function adaptAllServerTools(manager, serverConfigs) {
|
|
|
5729
5891
|
}
|
|
5730
5892
|
var DEFAULT_MODEL = "claude-sonnet-4-20250514";
|
|
5731
5893
|
var DEFAULT_MAX_TOKENS2 = 4096;
|
|
5894
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
5895
|
+
var RETRY_BASE_DELAY_MS = 1e3;
|
|
5896
|
+
var RETRY_MAX_DELAY_MS = 8e3;
|
|
5732
5897
|
var AnthropicProvider = class {
|
|
5733
5898
|
client;
|
|
5734
5899
|
defaultModel;
|
|
5735
5900
|
defaultMaxTokens;
|
|
5901
|
+
maxRetries;
|
|
5736
5902
|
constructor(config) {
|
|
5737
5903
|
this.client = new Anthropic({ apiKey: config.apiKey });
|
|
5738
5904
|
this.defaultModel = config.defaultModel ?? DEFAULT_MODEL;
|
|
5739
5905
|
this.defaultMaxTokens = config.defaultMaxTokens ?? DEFAULT_MAX_TOKENS2;
|
|
5906
|
+
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
5740
5907
|
}
|
|
5741
5908
|
async *chat(params) {
|
|
5909
|
+
let attempt = 0;
|
|
5910
|
+
while (true) {
|
|
5911
|
+
let yieldedAnything = false;
|
|
5912
|
+
const inner = this.streamOnce(params);
|
|
5913
|
+
try {
|
|
5914
|
+
for (; ; ) {
|
|
5915
|
+
const next = await inner.next();
|
|
5916
|
+
if (next.done) return;
|
|
5917
|
+
yieldedAnything = true;
|
|
5918
|
+
yield next.value;
|
|
5919
|
+
}
|
|
5920
|
+
} catch (err) {
|
|
5921
|
+
try {
|
|
5922
|
+
await inner.return?.(void 0);
|
|
5923
|
+
} catch {
|
|
5924
|
+
}
|
|
5925
|
+
if (!yieldedAnything && isRetriableError(err) && attempt < this.maxRetries) {
|
|
5926
|
+
attempt++;
|
|
5927
|
+
const delayMs = computeBackoffMs(attempt);
|
|
5928
|
+
console.warn(
|
|
5929
|
+
`[anthropic] retriable error (attempt ${attempt}/${this.maxRetries}, retrying in ${delayMs}ms): ${rawErrorMessage(err)}`
|
|
5930
|
+
);
|
|
5931
|
+
await sleep(delayMs);
|
|
5932
|
+
continue;
|
|
5933
|
+
}
|
|
5934
|
+
throw new Error(friendlyErrorMessage(err));
|
|
5935
|
+
}
|
|
5936
|
+
}
|
|
5937
|
+
}
|
|
5938
|
+
async *streamOnce(params) {
|
|
5742
5939
|
const messages = sanitizeAnthropicMessages(
|
|
5743
5940
|
params.messages.map(toAnthropicMessage)
|
|
5744
5941
|
);
|
|
@@ -5895,6 +6092,59 @@ var AnthropicProvider = class {
|
|
|
5895
6092
|
}
|
|
5896
6093
|
}
|
|
5897
6094
|
};
|
|
6095
|
+
function isRetriableError(err) {
|
|
6096
|
+
if (!err) return false;
|
|
6097
|
+
if (err instanceof Anthropic.APIError) {
|
|
6098
|
+
if (err.status === 529 || err.status === 408) return true;
|
|
6099
|
+
if (err.status === 502 || err.status === 503 || err.status === 504) return true;
|
|
6100
|
+
if (err.status === 429) return true;
|
|
6101
|
+
return false;
|
|
6102
|
+
}
|
|
6103
|
+
const msg = rawErrorMessage(err).toLowerCase();
|
|
6104
|
+
if (msg.includes("overloaded_error") || msg.includes('"overloaded"') || msg.includes("rate_limit_error") || msg.includes("econnreset") || msg.includes("etimedout") || msg.includes("socket hang up") || msg.includes("fetch failed") || msg.includes("network error")) {
|
|
6105
|
+
return true;
|
|
6106
|
+
}
|
|
6107
|
+
return false;
|
|
6108
|
+
}
|
|
6109
|
+
function rawErrorMessage(err) {
|
|
6110
|
+
if (err instanceof Error) return err.message;
|
|
6111
|
+
if (typeof err === "string") return err;
|
|
6112
|
+
try {
|
|
6113
|
+
return JSON.stringify(err);
|
|
6114
|
+
} catch {
|
|
6115
|
+
return String(err);
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6118
|
+
function friendlyErrorMessage(err) {
|
|
6119
|
+
const msg = rawErrorMessage(err).toLowerCase();
|
|
6120
|
+
if (msg.includes("overloaded_error") || msg.includes('"overloaded"') || err instanceof Anthropic.APIError && err.status === 529) {
|
|
6121
|
+
return "Anthropic's servers are over capacity right now. Please try again in 30 seconds.";
|
|
6122
|
+
}
|
|
6123
|
+
if (msg.includes("rate_limit_error") || err instanceof Anthropic.APIError && err.status === 429) {
|
|
6124
|
+
return "Too many requests in a short window. Please wait a moment and try again.";
|
|
6125
|
+
}
|
|
6126
|
+
if (msg.includes("econnreset") || msg.includes("etimedout") || msg.includes("socket hang up") || msg.includes("fetch failed") || msg.includes("network error")) {
|
|
6127
|
+
return "Couldn't reach Anthropic. Check your connection and try again.";
|
|
6128
|
+
}
|
|
6129
|
+
if (err instanceof Anthropic.APIError && err.status === 401) {
|
|
6130
|
+
return "Authentication failed. Please check the Anthropic API key configuration.";
|
|
6131
|
+
}
|
|
6132
|
+
if (err instanceof Anthropic.APIError && err.status === 400) {
|
|
6133
|
+
return "The request was rejected by Anthropic. This is likely a bug \u2014 please retry, and if it persists, contact support.";
|
|
6134
|
+
}
|
|
6135
|
+
if (err instanceof Anthropic.APIError && err.status >= 500) {
|
|
6136
|
+
return "Anthropic returned a server error. Please try again in a moment.";
|
|
6137
|
+
}
|
|
6138
|
+
return "Something went wrong. Please try again.";
|
|
6139
|
+
}
|
|
6140
|
+
function computeBackoffMs(attempt) {
|
|
6141
|
+
const base = Math.min(RETRY_BASE_DELAY_MS * 2 ** (attempt - 1), RETRY_MAX_DELAY_MS);
|
|
6142
|
+
const jitter = Math.floor(Math.random() * 250);
|
|
6143
|
+
return base + jitter;
|
|
6144
|
+
}
|
|
6145
|
+
function sleep(ms) {
|
|
6146
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6147
|
+
}
|
|
5898
6148
|
function toAnthropicSystem(prompt) {
|
|
5899
6149
|
if (typeof prompt === "string") return prompt;
|
|
5900
6150
|
return prompt.map((block) => ({
|