@t2000/engine 0.40.4 → 0.42.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/index.d.ts +229 -34
- package/dist/index.js +346 -33
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1121,12 +1121,15 @@ async function queryHistoryByDate(rpcUrl, address, targetDate, limit) {
|
|
|
1121
1121
|
}
|
|
1122
1122
|
return results.slice(0, limit);
|
|
1123
1123
|
}
|
|
1124
|
+
var HISTORY_ACTIONS = ["send", "lending", "swap", "transaction"];
|
|
1125
|
+
var DEFAULT_LOOKBACK_DAYS = 30;
|
|
1124
1126
|
var transactionHistoryTool = buildTool({
|
|
1125
1127
|
name: "transaction_history",
|
|
1126
|
-
description: "Retrieve transaction history:
|
|
1128
|
+
description: "Retrieve recent transaction history (last 30 days by default): sends, saves, withdrawals, borrows, repayments, and rewards claims. Pass `date` (YYYY-MM-DD) for a specific day, `action` to filter by category (send/lending/swap), or both.",
|
|
1127
1129
|
inputSchema: z.object({
|
|
1128
1130
|
limit: z.number().int().min(1).max(50).optional(),
|
|
1129
|
-
date: z.string().optional().describe("Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day.")
|
|
1131
|
+
date: z.string().optional().describe("Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day."),
|
|
1132
|
+
action: z.enum(HISTORY_ACTIONS).optional().describe("Filter by action: send, lending, swap, or transaction.")
|
|
1130
1133
|
}),
|
|
1131
1134
|
jsonSchema: {
|
|
1132
1135
|
type: "object",
|
|
@@ -1138,6 +1141,11 @@ var transactionHistoryTool = buildTool({
|
|
|
1138
1141
|
date: {
|
|
1139
1142
|
type: "string",
|
|
1140
1143
|
description: "Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day."
|
|
1144
|
+
},
|
|
1145
|
+
action: {
|
|
1146
|
+
type: "string",
|
|
1147
|
+
enum: [...HISTORY_ACTIONS],
|
|
1148
|
+
description: "Filter results by action category: send, lending, swap, or transaction."
|
|
1141
1149
|
}
|
|
1142
1150
|
}
|
|
1143
1151
|
},
|
|
@@ -1145,29 +1153,55 @@ var transactionHistoryTool = buildTool({
|
|
|
1145
1153
|
maxResultSizeChars: 8e3,
|
|
1146
1154
|
async call(input, context) {
|
|
1147
1155
|
const limit = input.limit ?? 10;
|
|
1156
|
+
const action = input.action;
|
|
1157
|
+
const finalize = (records2) => {
|
|
1158
|
+
let scoped = records2;
|
|
1159
|
+
if (action) scoped = scoped.filter((r) => r.action === action);
|
|
1160
|
+
return scoped.slice(0, limit);
|
|
1161
|
+
};
|
|
1148
1162
|
if (context.agent) {
|
|
1149
1163
|
const agent = requireAgent(context);
|
|
1150
|
-
const records2 = await agent.history({ limit });
|
|
1164
|
+
const records2 = await agent.history({ limit: input.date ? limit : Math.max(limit * 4, 50) });
|
|
1165
|
+
const filtered2 = finalize(records2);
|
|
1151
1166
|
return {
|
|
1152
|
-
data: { transactions:
|
|
1153
|
-
displayText: `${
|
|
1167
|
+
data: { transactions: filtered2, count: filtered2.length, date: input.date ?? null, action: action ?? null },
|
|
1168
|
+
displayText: `${filtered2.length} recent transaction(s)`
|
|
1154
1169
|
};
|
|
1155
1170
|
}
|
|
1156
1171
|
if (!context.walletAddress || !context.suiRpcUrl) {
|
|
1157
1172
|
throw new Error("Transaction history requires a wallet address");
|
|
1158
1173
|
}
|
|
1159
1174
|
if (input.date) {
|
|
1160
|
-
const records2 = await queryHistoryByDate(
|
|
1175
|
+
const records2 = await queryHistoryByDate(
|
|
1176
|
+
context.suiRpcUrl,
|
|
1177
|
+
context.walletAddress,
|
|
1178
|
+
input.date,
|
|
1179
|
+
Math.max(limit * 4, 50)
|
|
1180
|
+
);
|
|
1181
|
+
const filtered2 = finalize(records2);
|
|
1161
1182
|
const dateLabel = new Date(input.date).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
|
|
1162
1183
|
return {
|
|
1163
|
-
data: { transactions:
|
|
1164
|
-
displayText:
|
|
1184
|
+
data: { transactions: filtered2, count: filtered2.length, date: input.date, action: action ?? null },
|
|
1185
|
+
displayText: filtered2.length > 0 ? `${filtered2.length} transaction(s) on ${dateLabel}` : `No transactions found on ${dateLabel}`
|
|
1165
1186
|
};
|
|
1166
1187
|
}
|
|
1167
|
-
const
|
|
1188
|
+
const cutoffMs = Date.now() - DEFAULT_LOOKBACK_DAYS * 864e5;
|
|
1189
|
+
const records = await queryHistoryRpc(
|
|
1190
|
+
context.suiRpcUrl,
|
|
1191
|
+
context.walletAddress,
|
|
1192
|
+
Math.max(limit * 4, 50)
|
|
1193
|
+
);
|
|
1194
|
+
const recent = records.filter((r) => r.timestamp >= cutoffMs);
|
|
1195
|
+
const filtered = finalize(recent);
|
|
1168
1196
|
return {
|
|
1169
|
-
data: {
|
|
1170
|
-
|
|
1197
|
+
data: {
|
|
1198
|
+
transactions: filtered,
|
|
1199
|
+
count: filtered.length,
|
|
1200
|
+
date: null,
|
|
1201
|
+
action: action ?? null,
|
|
1202
|
+
lookbackDays: DEFAULT_LOOKBACK_DAYS
|
|
1203
|
+
},
|
|
1204
|
+
displayText: `${filtered.length} transaction(s) in the last ${DEFAULT_LOOKBACK_DAYS} days`
|
|
1171
1205
|
};
|
|
1172
1206
|
}
|
|
1173
1207
|
});
|
|
@@ -1547,16 +1581,21 @@ function matchesQuery(service, q) {
|
|
|
1547
1581
|
}
|
|
1548
1582
|
var mppServicesTool = buildTool({
|
|
1549
1583
|
name: "mpp_services",
|
|
1550
|
-
description: "Discover available MPP gateway services. Returns service names, descriptions, endpoints with required parameters, and pricing.
|
|
1584
|
+
description: "Discover available MPP gateway services. Returns service names, descriptions, endpoints with required parameters, and pricing. Pass `query` for keyword search or `category` to filter by category. Calling with NO filters returns a category summary (not the full catalog) \u2014 narrow first, then fetch endpoints. Use this BEFORE calling pay_api.",
|
|
1551
1585
|
inputSchema: z.object({
|
|
1552
|
-
query: z.string().optional().describe('Filter by keyword (e.g. "postcard", "translate", "weather").
|
|
1586
|
+
query: z.string().optional().describe('Filter by keyword (e.g. "postcard", "translate", "weather").'),
|
|
1587
|
+
category: z.string().optional().describe('Filter by category exactly (e.g. "weather", "image"). See category summary returned when called without filters.')
|
|
1553
1588
|
}),
|
|
1554
1589
|
jsonSchema: {
|
|
1555
1590
|
type: "object",
|
|
1556
1591
|
properties: {
|
|
1557
1592
|
query: {
|
|
1558
1593
|
type: "string",
|
|
1559
|
-
description: 'Filter by keyword (e.g. "postcard", "translate", "weather").
|
|
1594
|
+
description: 'Filter by keyword (e.g. "postcard", "translate", "weather").'
|
|
1595
|
+
},
|
|
1596
|
+
category: {
|
|
1597
|
+
type: "string",
|
|
1598
|
+
description: 'Filter by category exactly (e.g. "weather", "image").'
|
|
1560
1599
|
}
|
|
1561
1600
|
},
|
|
1562
1601
|
required: []
|
|
@@ -1565,7 +1604,34 @@ var mppServicesTool = buildTool({
|
|
|
1565
1604
|
maxResultSizeChars: 5e3,
|
|
1566
1605
|
async call(input) {
|
|
1567
1606
|
const catalog = await fetchCatalog();
|
|
1568
|
-
|
|
1607
|
+
if (!input.query && !input.category) {
|
|
1608
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1609
|
+
for (const svc of catalog) {
|
|
1610
|
+
for (const cat of svc.categories) {
|
|
1611
|
+
counts.set(cat, (counts.get(cat) ?? 0) + 1);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
const categories = [...counts.entries()].sort((a, b) => b[1] - a[1]).map(([category, services2]) => ({ category, services: services2 }));
|
|
1615
|
+
return {
|
|
1616
|
+
data: {
|
|
1617
|
+
_refine: {
|
|
1618
|
+
reason: "MPP catalog has many services \u2014 pick a category or supply a query first.",
|
|
1619
|
+
suggestedParams: { category: categories[0]?.category ?? "weather" }
|
|
1620
|
+
},
|
|
1621
|
+
categories,
|
|
1622
|
+
totalServices: catalog.length
|
|
1623
|
+
},
|
|
1624
|
+
displayText: `${catalog.length} services across ${categories.length} categories. Re-call with a category or query.`
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
let filtered = catalog;
|
|
1628
|
+
if (input.category) {
|
|
1629
|
+
const cat = input.category.toLowerCase();
|
|
1630
|
+
filtered = filtered.filter((s) => s.categories.some((c) => c.toLowerCase() === cat));
|
|
1631
|
+
}
|
|
1632
|
+
if (input.query) {
|
|
1633
|
+
filtered = filtered.filter((s) => matchesQuery(s, input.query));
|
|
1634
|
+
}
|
|
1569
1635
|
const services = filtered.map((s) => ({
|
|
1570
1636
|
id: s.id,
|
|
1571
1637
|
name: s.name,
|
|
@@ -1578,7 +1644,11 @@ var mppServicesTool = buildTool({
|
|
|
1578
1644
|
price: `$${e.price}`
|
|
1579
1645
|
}))
|
|
1580
1646
|
}));
|
|
1581
|
-
const
|
|
1647
|
+
const filterDesc = [
|
|
1648
|
+
input.query ? `query "${input.query}"` : null,
|
|
1649
|
+
input.category ? `category "${input.category}"` : null
|
|
1650
|
+
].filter(Boolean).join(" + ");
|
|
1651
|
+
const summary = `Found ${services.length} service(s) matching ${filterDesc}`;
|
|
1582
1652
|
return {
|
|
1583
1653
|
data: { services, total: services.length },
|
|
1584
1654
|
displayText: summary
|
|
@@ -2830,6 +2900,10 @@ async function cachedFetch(url) {
|
|
|
2830
2900
|
apiCache.set(url, { data, ts: Date.now() });
|
|
2831
2901
|
return data;
|
|
2832
2902
|
}
|
|
2903
|
+
async function fetchDefillamaYieldPools() {
|
|
2904
|
+
const data = await cachedFetch(`${YIELDS_API2}/pools`);
|
|
2905
|
+
return data.data ?? [];
|
|
2906
|
+
}
|
|
2833
2907
|
function fmtToolTvl(tvl) {
|
|
2834
2908
|
if (tvl >= 1e9) return `$${(tvl / 1e9).toFixed(1)}B`;
|
|
2835
2909
|
if (tvl >= 1e6) return `$${(tvl / 1e6).toFixed(1)}M`;
|
|
@@ -2858,8 +2932,25 @@ var defillamaYieldPoolsTool = buildTool({
|
|
|
2858
2932
|
isReadOnly: true,
|
|
2859
2933
|
maxResultSizeChars: 6e3,
|
|
2860
2934
|
async call(input) {
|
|
2861
|
-
|
|
2862
|
-
|
|
2935
|
+
if (!input.chain && !input.project) {
|
|
2936
|
+
const all = await fetchDefillamaYieldPools();
|
|
2937
|
+
const chainCounts = /* @__PURE__ */ new Map();
|
|
2938
|
+
for (const p of all) {
|
|
2939
|
+
chainCounts.set(p.chain, (chainCounts.get(p.chain) ?? 0) + 1);
|
|
2940
|
+
}
|
|
2941
|
+
const topChains = [...chainCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 8).map(([chain, count]) => ({ chain, pools: count }));
|
|
2942
|
+
return {
|
|
2943
|
+
data: {
|
|
2944
|
+
_refine: {
|
|
2945
|
+
reason: "Cross-chain yield search is too broad; pick a chain.",
|
|
2946
|
+
suggestedParams: { chain: "Sui" },
|
|
2947
|
+
availableChains: topChains
|
|
2948
|
+
}
|
|
2949
|
+
},
|
|
2950
|
+
displayText: "Yield query needs a chain filter. Common chains: " + topChains.map((c) => c.chain).join(", ")
|
|
2951
|
+
};
|
|
2952
|
+
}
|
|
2953
|
+
let pools = await fetchDefillamaYieldPools();
|
|
2863
2954
|
if (input.chain) {
|
|
2864
2955
|
const chain = input.chain.toLowerCase();
|
|
2865
2956
|
pools = pools.filter((p) => p.chain.toLowerCase() === chain);
|
|
@@ -3149,6 +3240,40 @@ function getDefaultTools() {
|
|
|
3149
3240
|
return applyToolFlags([...READ_TOOLS, ...WRITE_TOOLS]);
|
|
3150
3241
|
}
|
|
3151
3242
|
|
|
3243
|
+
// src/tools/tool-modifiable-fields.ts
|
|
3244
|
+
var TOOL_MODIFIABLE_FIELDS = {
|
|
3245
|
+
save_deposit: [
|
|
3246
|
+
{ name: "amount", kind: "amount", asset: "USDC" }
|
|
3247
|
+
],
|
|
3248
|
+
withdraw: [
|
|
3249
|
+
{ name: "amount", kind: "amount", asset: "USDC" }
|
|
3250
|
+
],
|
|
3251
|
+
send_transfer: [
|
|
3252
|
+
// `amount` first so the UI surfaces it prominently; the recipient
|
|
3253
|
+
// address field is also editable in case the user typed the wrong one.
|
|
3254
|
+
{ name: "amount", kind: "amount" },
|
|
3255
|
+
{ name: "to", kind: "address" }
|
|
3256
|
+
],
|
|
3257
|
+
swap_execute: [
|
|
3258
|
+
{ name: "amount", kind: "amount" }
|
|
3259
|
+
],
|
|
3260
|
+
borrow: [
|
|
3261
|
+
{ name: "amount", kind: "amount", asset: "USDC" }
|
|
3262
|
+
],
|
|
3263
|
+
repay_debt: [
|
|
3264
|
+
{ name: "amount", kind: "amount", asset: "USDC" }
|
|
3265
|
+
],
|
|
3266
|
+
volo_stake: [
|
|
3267
|
+
{ name: "amount", kind: "amount", asset: "SUI" }
|
|
3268
|
+
],
|
|
3269
|
+
volo_unstake: [
|
|
3270
|
+
{ name: "amount", kind: "amount", asset: "vSUI" }
|
|
3271
|
+
]
|
|
3272
|
+
};
|
|
3273
|
+
function getModifiableFields(toolName) {
|
|
3274
|
+
return TOOL_MODIFIABLE_FIELDS[toolName];
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3152
3277
|
// src/prompt.ts
|
|
3153
3278
|
var DEFAULT_SYSTEM_PROMPT = `You are Audric \u2014 a financial agent on Sui. Audric is exactly five products: Audric Passport (the trust layer \u2014 Google sign-in, non-custodial wallet, tap-to-confirm consent, sponsored gas \u2014 wraps every other product), Audric Intelligence (you \u2014 the 5-system brain: Agent Harness with 40 tools, Reasoning Engine with 9 guards and 7 skill recipes, Silent Profile, Chain Memory, AdviceLog), Audric Finance (manage money on Sui \u2014 Save via NAVI lending at 3-8% APY USDC, Credit via NAVI borrowing with health factor, Swap via Cetus aggregator across 20+ DEXs at 0.1% fee, Charts for yield/health/portfolio viz), Audric Pay (move money \u2014 send USDC, receive via payment links / invoices / QR; free, global, instant on Sui), and Audric Store (creator marketplace, ships Phase 5 \u2014 say "coming soon" if asked). Save, swap, borrow, repay, withdraw, charts \u2192 Audric Finance. Send, receive, payment-link, invoice, QR \u2192 Audric Pay. Your silent context (profile, memory, chain facts, advice log) shapes your replies but never surfaces as a notification \u2014 you act only when the user asks, and every write waits on their tap-to-confirm via Passport. You can also call 41 paid APIs (music, image, research, translation, weather, fulfilment) via MPP micropayments using the pay_api tool \u2014 this is an internal capability, not a promoted product, so only mention it when the user asks for something that needs it.
|
|
3154
3279
|
|
|
@@ -3248,6 +3373,11 @@ var CostTracker = class {
|
|
|
3248
3373
|
};
|
|
3249
3374
|
|
|
3250
3375
|
// src/guards.ts
|
|
3376
|
+
function guardVerdictToAction(verdict) {
|
|
3377
|
+
if (verdict === "pass" || verdict === "hint") return "allow";
|
|
3378
|
+
if (verdict === "warn") return "warn";
|
|
3379
|
+
return "block";
|
|
3380
|
+
}
|
|
3251
3381
|
var DEFAULT_GUARD_CONFIG = {
|
|
3252
3382
|
balanceValidation: true,
|
|
3253
3383
|
healthFactor: { warnBelow: 2, blockBelow: 1.5 },
|
|
@@ -3464,9 +3594,22 @@ function createGuardRunnerState() {
|
|
|
3464
3594
|
lastHealthFactor: null
|
|
3465
3595
|
};
|
|
3466
3596
|
}
|
|
3467
|
-
function runGuards(tool, call, state, config, conversationContext) {
|
|
3597
|
+
function runGuards(tool, call, state, config, conversationContext, onGuardFired) {
|
|
3468
3598
|
const results = [];
|
|
3469
3599
|
const now = Date.now();
|
|
3600
|
+
const fire = (verdict, tier, gate, hadInjection) => {
|
|
3601
|
+
if (!onGuardFired) return;
|
|
3602
|
+
try {
|
|
3603
|
+
onGuardFired({
|
|
3604
|
+
name: gate,
|
|
3605
|
+
tier,
|
|
3606
|
+
action: guardVerdictToAction(verdict),
|
|
3607
|
+
injectionAdded: hadInjection
|
|
3608
|
+
});
|
|
3609
|
+
} catch (err) {
|
|
3610
|
+
console.warn("[guards] onGuardFired threw (ignored):", err);
|
|
3611
|
+
}
|
|
3612
|
+
};
|
|
3470
3613
|
if (config.inputValidation !== false && tool.preflight) {
|
|
3471
3614
|
const check = tool.preflight(call.input);
|
|
3472
3615
|
if (!check.valid) {
|
|
@@ -3479,6 +3622,7 @@ function runGuards(tool, call, state, config, conversationContext) {
|
|
|
3479
3622
|
tier: "safety",
|
|
3480
3623
|
message: check.error
|
|
3481
3624
|
};
|
|
3625
|
+
fire("block", "safety", "input_validation", false);
|
|
3482
3626
|
return {
|
|
3483
3627
|
blocked: true,
|
|
3484
3628
|
blockReason: check.error,
|
|
@@ -3520,6 +3664,10 @@ function runGuards(tool, call, state, config, conversationContext) {
|
|
|
3520
3664
|
}));
|
|
3521
3665
|
const block = results.find((r) => r.verdict === "block");
|
|
3522
3666
|
if (block) {
|
|
3667
|
+
for (const r of results) {
|
|
3668
|
+
if (r.verdict === "pass") continue;
|
|
3669
|
+
fire(r.verdict, r.tier, r.gate, false);
|
|
3670
|
+
}
|
|
3523
3671
|
return {
|
|
3524
3672
|
blocked: true,
|
|
3525
3673
|
blockReason: block.message ?? `Blocked by ${block.gate}`,
|
|
@@ -3532,6 +3680,10 @@ function runGuards(tool, call, state, config, conversationContext) {
|
|
|
3532
3680
|
_gate: r.gate,
|
|
3533
3681
|
...r.verdict === "hint" ? { _hint: r.message } : { _warning: r.message }
|
|
3534
3682
|
}));
|
|
3683
|
+
for (const r of results) {
|
|
3684
|
+
if (r.verdict === "pass") continue;
|
|
3685
|
+
fire(r.verdict, r.tier, r.gate, r.verdict === "hint" || r.verdict === "warn");
|
|
3686
|
+
}
|
|
3535
3687
|
return { blocked: false, injections, events };
|
|
3536
3688
|
}
|
|
3537
3689
|
function updateGuardStateAfterToolResult(toolName, tool, input, result, isError, state) {
|
|
@@ -3576,6 +3728,7 @@ function microcompact(messages) {
|
|
|
3576
3728
|
const seen = /* @__PURE__ */ new Map();
|
|
3577
3729
|
let toolUseIndex = 0;
|
|
3578
3730
|
const toolUseInputs = /* @__PURE__ */ new Map();
|
|
3731
|
+
const dedupedToolUseIds = /* @__PURE__ */ new Set();
|
|
3579
3732
|
for (const msg of messages) {
|
|
3580
3733
|
for (const block of msg.content) {
|
|
3581
3734
|
if (block.type === "tool_use") {
|
|
@@ -3583,7 +3736,7 @@ function microcompact(messages) {
|
|
|
3583
3736
|
}
|
|
3584
3737
|
}
|
|
3585
3738
|
}
|
|
3586
|
-
|
|
3739
|
+
const out = messages.map((msg) => {
|
|
3587
3740
|
if (msg.role !== "user") return { role: msg.role, content: [...msg.content] };
|
|
3588
3741
|
const hasToolResults = msg.content.some((b) => b.type === "tool_result");
|
|
3589
3742
|
if (!hasToolResults) return { role: msg.role, content: [...msg.content] };
|
|
@@ -3594,6 +3747,7 @@ function microcompact(messages) {
|
|
|
3594
3747
|
toolUseIndex++;
|
|
3595
3748
|
const prior = seen.get(key);
|
|
3596
3749
|
if (prior && !block.isError) {
|
|
3750
|
+
dedupedToolUseIds.add(block.toolUseId);
|
|
3597
3751
|
return {
|
|
3598
3752
|
...block,
|
|
3599
3753
|
content: `[Same result as call #${prior.turnIndex} \u2014 ${key.split(":")[0]} with identical inputs. Result unchanged.]`
|
|
@@ -3606,6 +3760,13 @@ function microcompact(messages) {
|
|
|
3606
3760
|
});
|
|
3607
3761
|
return { role: msg.role, content: newContent };
|
|
3608
3762
|
});
|
|
3763
|
+
Object.defineProperty(out, "dedupedToolUseIds", {
|
|
3764
|
+
value: dedupedToolUseIds,
|
|
3765
|
+
enumerable: false,
|
|
3766
|
+
writable: false,
|
|
3767
|
+
configurable: false
|
|
3768
|
+
});
|
|
3769
|
+
return out;
|
|
3609
3770
|
}
|
|
3610
3771
|
function stableStringify(value) {
|
|
3611
3772
|
if (value === null || value === void 0) return "";
|
|
@@ -3845,13 +4006,18 @@ var PERMISSION_PRESETS = {
|
|
|
3845
4006
|
]
|
|
3846
4007
|
}
|
|
3847
4008
|
};
|
|
3848
|
-
function resolvePermissionTier(operation, amountUsd, config) {
|
|
4009
|
+
function resolvePermissionTier(operation, amountUsd, config, sessionSpendUsd) {
|
|
3849
4010
|
const rule = config.rules.find((r) => r.operation === operation);
|
|
3850
4011
|
const autoBelow = rule?.autoBelow ?? config.globalAutoBelow;
|
|
3851
4012
|
const confirmBetween = rule?.confirmBetween ?? 1e3;
|
|
3852
|
-
|
|
3853
|
-
if (amountUsd <
|
|
3854
|
-
|
|
4013
|
+
let tier;
|
|
4014
|
+
if (amountUsd < autoBelow) tier = "auto";
|
|
4015
|
+
else if (amountUsd < confirmBetween) tier = "confirm";
|
|
4016
|
+
else tier = "explicit";
|
|
4017
|
+
if (tier === "auto" && typeof sessionSpendUsd === "number" && sessionSpendUsd + amountUsd > config.autonomousDailyLimit) {
|
|
4018
|
+
return "confirm";
|
|
4019
|
+
}
|
|
4020
|
+
return tier;
|
|
3855
4021
|
}
|
|
3856
4022
|
var TOOL_TO_OPERATION = {
|
|
3857
4023
|
save_deposit: "save",
|
|
@@ -3945,7 +4111,8 @@ var EarlyToolDispatcher = class {
|
|
|
3945
4111
|
toolName: entry.call.name,
|
|
3946
4112
|
toolUseId: entry.call.id,
|
|
3947
4113
|
result: budgeted,
|
|
3948
|
-
isError: result.isError
|
|
4114
|
+
isError: result.isError,
|
|
4115
|
+
wasEarlyDispatched: true
|
|
3949
4116
|
};
|
|
3950
4117
|
} catch (err) {
|
|
3951
4118
|
yield {
|
|
@@ -3953,7 +4120,8 @@ var EarlyToolDispatcher = class {
|
|
|
3953
4120
|
toolName: entry.call.name,
|
|
3954
4121
|
toolUseId: entry.call.id,
|
|
3955
4122
|
result: { error: err instanceof Error ? err.message : "Tool execution failed" },
|
|
3956
|
-
isError: true
|
|
4123
|
+
isError: true,
|
|
4124
|
+
wasEarlyDispatched: true
|
|
3957
4125
|
};
|
|
3958
4126
|
}
|
|
3959
4127
|
}
|
|
@@ -4005,6 +4173,13 @@ var QueryEngine = class {
|
|
|
4005
4173
|
contextSummarizer;
|
|
4006
4174
|
priceCache;
|
|
4007
4175
|
permissionConfig;
|
|
4176
|
+
// [v1.4] Session-scoped autonomous spend tracking.
|
|
4177
|
+
sessionSpendUsd;
|
|
4178
|
+
onAutoExecuted;
|
|
4179
|
+
onGuardFired;
|
|
4180
|
+
// [v1.5] See `EngineConfig.postWriteRefresh` — drives the post-write
|
|
4181
|
+
// synthetic read injection in `resumeWithToolResult`.
|
|
4182
|
+
postWriteRefresh;
|
|
4008
4183
|
matchedRecipe = null;
|
|
4009
4184
|
messages = [];
|
|
4010
4185
|
abortController = null;
|
|
@@ -4034,6 +4209,10 @@ var QueryEngine = class {
|
|
|
4034
4209
|
this.contextSummarizer = config.contextSummarizer;
|
|
4035
4210
|
this.priceCache = config.priceCache;
|
|
4036
4211
|
this.permissionConfig = config.permissionConfig;
|
|
4212
|
+
this.sessionSpendUsd = config.sessionSpendUsd;
|
|
4213
|
+
this.onAutoExecuted = config.onAutoExecuted;
|
|
4214
|
+
this.onGuardFired = config.onGuardFired;
|
|
4215
|
+
this.postWriteRefresh = config.postWriteRefresh;
|
|
4037
4216
|
this.tools = config.tools ?? (config.agent ? getDefaultTools() : []);
|
|
4038
4217
|
}
|
|
4039
4218
|
/**
|
|
@@ -4102,8 +4281,96 @@ var QueryEngine = class {
|
|
|
4102
4281
|
yield { type: "turn_complete", stopReason: "end_turn" };
|
|
4103
4282
|
return;
|
|
4104
4283
|
}
|
|
4284
|
+
yield* this.runPostWriteRefresh(action, response, signal);
|
|
4105
4285
|
yield* this.agentLoop(null, signal, false);
|
|
4106
4286
|
}
|
|
4287
|
+
/**
|
|
4288
|
+
* [v1.5] Auto-run configured read tools after a successful write,
|
|
4289
|
+
* push their results into the conversation, and yield `tool_result`
|
|
4290
|
+
* events so hosts/UI render them in the timeline. See
|
|
4291
|
+
* `EngineConfig.postWriteRefresh`.
|
|
4292
|
+
*
|
|
4293
|
+
* Pure injection — no LLM call here. The next `agentLoop` turn sees
|
|
4294
|
+
* the fresh tool results and narrates from them.
|
|
4295
|
+
*/
|
|
4296
|
+
async *runPostWriteRefresh(action, response, signal) {
|
|
4297
|
+
const refreshList = this.postWriteRefresh?.[action.toolName];
|
|
4298
|
+
if (!refreshList || refreshList.length === 0) return;
|
|
4299
|
+
const exec = response.executionResult;
|
|
4300
|
+
const writeFailed = exec != null && typeof exec === "object" && "success" in exec && exec.success === false;
|
|
4301
|
+
if (writeFailed) return;
|
|
4302
|
+
const refreshTools = refreshList.map((name) => findTool(this.tools, name)).filter(
|
|
4303
|
+
(t) => t !== void 0 && t.isReadOnly && t.isConcurrencySafe
|
|
4304
|
+
);
|
|
4305
|
+
if (refreshTools.length === 0) return;
|
|
4306
|
+
const context = {
|
|
4307
|
+
agent: this.agent,
|
|
4308
|
+
mcpManager: this.mcpManager,
|
|
4309
|
+
walletAddress: this.walletAddress,
|
|
4310
|
+
suiRpcUrl: this.suiRpcUrl,
|
|
4311
|
+
serverPositions: this.serverPositions,
|
|
4312
|
+
positionFetcher: this.positionFetcher,
|
|
4313
|
+
env: this.env,
|
|
4314
|
+
signal,
|
|
4315
|
+
priceCache: this.priceCache,
|
|
4316
|
+
permissionConfig: this.permissionConfig,
|
|
4317
|
+
sessionSpendUsd: this.sessionSpendUsd
|
|
4318
|
+
};
|
|
4319
|
+
const idStem = `pwr_${action.toolUseId.slice(-6)}`;
|
|
4320
|
+
const refreshes = await Promise.all(
|
|
4321
|
+
refreshTools.map(async (tool, idx) => {
|
|
4322
|
+
const id = `${idStem}_${idx}_${tool.name}`;
|
|
4323
|
+
try {
|
|
4324
|
+
const parsed = tool.inputSchema.safeParse({});
|
|
4325
|
+
if (!parsed.success) {
|
|
4326
|
+
return {
|
|
4327
|
+
tool,
|
|
4328
|
+
id,
|
|
4329
|
+
isError: true,
|
|
4330
|
+
data: {
|
|
4331
|
+
error: `Post-write refresh: invalid input for ${tool.name}`
|
|
4332
|
+
}
|
|
4333
|
+
};
|
|
4334
|
+
}
|
|
4335
|
+
const result = await tool.call(parsed.data, context);
|
|
4336
|
+
return { tool, id, isError: false, data: result.data };
|
|
4337
|
+
} catch (err) {
|
|
4338
|
+
return {
|
|
4339
|
+
tool,
|
|
4340
|
+
id,
|
|
4341
|
+
isError: true,
|
|
4342
|
+
data: {
|
|
4343
|
+
error: err instanceof Error ? err.message : "Post-write refresh failed"
|
|
4344
|
+
}
|
|
4345
|
+
};
|
|
4346
|
+
}
|
|
4347
|
+
})
|
|
4348
|
+
);
|
|
4349
|
+
const refreshUses = refreshes.map((r) => ({
|
|
4350
|
+
type: "tool_use",
|
|
4351
|
+
id: r.id,
|
|
4352
|
+
name: r.tool.name,
|
|
4353
|
+
input: {}
|
|
4354
|
+
}));
|
|
4355
|
+
this.messages.push({ role: "assistant", content: refreshUses });
|
|
4356
|
+
const refreshResults = refreshes.map((r) => ({
|
|
4357
|
+
type: "tool_result",
|
|
4358
|
+
toolUseId: r.id,
|
|
4359
|
+
content: typeof r.data === "string" ? r.data : JSON.stringify(r.data),
|
|
4360
|
+
isError: r.isError
|
|
4361
|
+
}));
|
|
4362
|
+
this.messages.push({ role: "user", content: refreshResults });
|
|
4363
|
+
for (const r of refreshes) {
|
|
4364
|
+
yield {
|
|
4365
|
+
type: "tool_result",
|
|
4366
|
+
toolName: r.tool.name,
|
|
4367
|
+
toolUseId: r.id,
|
|
4368
|
+
result: r.data,
|
|
4369
|
+
isError: r.isError,
|
|
4370
|
+
wasPostWriteRefresh: true
|
|
4371
|
+
};
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4107
4374
|
interrupt() {
|
|
4108
4375
|
this.abortController?.abort();
|
|
4109
4376
|
}
|
|
@@ -4155,7 +4422,8 @@ var QueryEngine = class {
|
|
|
4155
4422
|
env: this.env,
|
|
4156
4423
|
signal,
|
|
4157
4424
|
priceCache: this.priceCache,
|
|
4158
|
-
permissionConfig: this.permissionConfig
|
|
4425
|
+
permissionConfig: this.permissionConfig,
|
|
4426
|
+
sessionSpendUsd: this.sessionSpendUsd
|
|
4159
4427
|
};
|
|
4160
4428
|
let turns = 0;
|
|
4161
4429
|
let hasRetriedWithCleanHistory = false;
|
|
@@ -4174,13 +4442,25 @@ var QueryEngine = class {
|
|
|
4174
4442
|
};
|
|
4175
4443
|
const dispatcher = new EarlyToolDispatcher(this.tools, context);
|
|
4176
4444
|
try {
|
|
4177
|
-
|
|
4445
|
+
const microcompacted = microcompact(this.messages);
|
|
4446
|
+
this.messages = microcompacted;
|
|
4447
|
+
for (const dedupedId of microcompacted.dedupedToolUseIds) {
|
|
4448
|
+
yield {
|
|
4449
|
+
type: "tool_result",
|
|
4450
|
+
toolName: "__deduped__",
|
|
4451
|
+
toolUseId: dedupedId,
|
|
4452
|
+
result: null,
|
|
4453
|
+
isError: false,
|
|
4454
|
+
resultDeduped: true
|
|
4455
|
+
};
|
|
4456
|
+
}
|
|
4178
4457
|
if (this.contextBudget.shouldCompact()) {
|
|
4179
4458
|
this.messages = await compactMessages(this.messages, {
|
|
4180
4459
|
maxTokens: 1e5,
|
|
4181
4460
|
keepRecentCount: 8,
|
|
4182
4461
|
summarizer: this.contextSummarizer
|
|
4183
4462
|
});
|
|
4463
|
+
yield { type: "compaction" };
|
|
4184
4464
|
}
|
|
4185
4465
|
this.messages = validateHistory(this.messages);
|
|
4186
4466
|
if (process.env.NODE_ENV !== "test") {
|
|
@@ -4340,7 +4620,12 @@ ${recipeCtx}`;
|
|
|
4340
4620
|
const operation = toolNameToOperation(call.name);
|
|
4341
4621
|
if (operation) {
|
|
4342
4622
|
const usdValue = resolveUsdValue(call.name, call.input, context.priceCache);
|
|
4343
|
-
const tier = resolvePermissionTier(
|
|
4623
|
+
const tier = resolvePermissionTier(
|
|
4624
|
+
operation,
|
|
4625
|
+
usdValue,
|
|
4626
|
+
context.permissionConfig,
|
|
4627
|
+
context.sessionSpendUsd
|
|
4628
|
+
);
|
|
4344
4629
|
return tier !== "auto";
|
|
4345
4630
|
}
|
|
4346
4631
|
}
|
|
@@ -4363,7 +4648,14 @@ ${recipeCtx}`;
|
|
|
4363
4648
|
guardedApproved.push(call);
|
|
4364
4649
|
continue;
|
|
4365
4650
|
}
|
|
4366
|
-
const check = runGuards(
|
|
4651
|
+
const check = runGuards(
|
|
4652
|
+
tool,
|
|
4653
|
+
call,
|
|
4654
|
+
this.guardState,
|
|
4655
|
+
this.guardConfig,
|
|
4656
|
+
convCtx,
|
|
4657
|
+
this.onGuardFired
|
|
4658
|
+
);
|
|
4367
4659
|
this.guardEvents.push(...check.events);
|
|
4368
4660
|
if (check.blocked) {
|
|
4369
4661
|
yield {
|
|
@@ -4445,6 +4737,22 @@ ${recipeCtx}`;
|
|
|
4445
4737
|
toolUseId: finalEvent.toolUseId
|
|
4446
4738
|
};
|
|
4447
4739
|
}
|
|
4740
|
+
if (tool && !tool.isReadOnly && this.onAutoExecuted && this.permissionConfig && this.priceCache) {
|
|
4741
|
+
const operation = toolNameToOperation(toolEvent.toolName);
|
|
4742
|
+
if (operation && originalCall) {
|
|
4743
|
+
const usdValue = resolveUsdValue(
|
|
4744
|
+
toolEvent.toolName,
|
|
4745
|
+
originalCall.input,
|
|
4746
|
+
this.priceCache
|
|
4747
|
+
);
|
|
4748
|
+
Promise.resolve().then(() => this.onAutoExecuted({
|
|
4749
|
+
toolName: toolEvent.toolName,
|
|
4750
|
+
usdValue
|
|
4751
|
+
})).catch((err) => {
|
|
4752
|
+
console.warn("[engine] onAutoExecuted callback failed:", err);
|
|
4753
|
+
});
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
4448
4756
|
}
|
|
4449
4757
|
toolResultBlocks.push({
|
|
4450
4758
|
type: "tool_result",
|
|
@@ -4463,7 +4771,8 @@ ${recipeCtx}`;
|
|
|
4463
4771
|
pendingWrite.call,
|
|
4464
4772
|
this.guardState,
|
|
4465
4773
|
this.guardConfig,
|
|
4466
|
-
convCtx
|
|
4774
|
+
convCtx,
|
|
4775
|
+
this.onGuardFired
|
|
4467
4776
|
);
|
|
4468
4777
|
this.guardEvents.push(...check.events);
|
|
4469
4778
|
if (check.blocked) {
|
|
@@ -4490,6 +4799,8 @@ ${recipeCtx}`;
|
|
|
4490
4799
|
}
|
|
4491
4800
|
if (pendingWrite) {
|
|
4492
4801
|
const writeGuardInjections = pendingWrite.call._guardInjections;
|
|
4802
|
+
const modifiableFields = getModifiableFields(pendingWrite.call.name);
|
|
4803
|
+
const turnIndex = this.messages.filter((m) => m.role === "assistant").length;
|
|
4493
4804
|
yield {
|
|
4494
4805
|
type: "pending_action",
|
|
4495
4806
|
action: {
|
|
@@ -4503,7 +4814,9 @@ ${recipeCtx}`;
|
|
|
4503
4814
|
content: b.content,
|
|
4504
4815
|
isError: b.isError ?? false
|
|
4505
4816
|
})),
|
|
4506
|
-
...writeGuardInjections?.length ? { guardInjections: writeGuardInjections } : {}
|
|
4817
|
+
...writeGuardInjections?.length ? { guardInjections: writeGuardInjections } : {},
|
|
4818
|
+
...modifiableFields?.length ? { modifiableFields } : {},
|
|
4819
|
+
turnIndex
|
|
4507
4820
|
}
|
|
4508
4821
|
};
|
|
4509
4822
|
return;
|
|
@@ -5670,6 +5983,6 @@ function sanitizeAnthropicMessages(messages) {
|
|
|
5670
5983
|
return merged;
|
|
5671
5984
|
}
|
|
5672
5985
|
|
|
5673
|
-
export { AnthropicProvider, BalanceTracker, CANVAS_TEMPLATES, ContextBudget, CostTracker, DEFAULT_GUARD_CONFIG, DEFAULT_PERMISSION_CONFIG, DEFAULT_SYSTEM_PROMPT, EarlyToolDispatcher, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_SERVER_NAME, NaviTools, PERMISSION_PRESETS, QueryEngine, READ_TOOLS, RecipeRegistry, RetryTracker, TOOL_FLAGS, TxMutex, WRITE_TOOLS, activitySummaryTool, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, applyToolFlags, balanceCheckTool, borrowTool, budgetToolResult, buildCachedSystemPrompt, buildMcpTools, buildProactivenessInstructions, buildProfileContext, buildSelfEvaluationInstruction, buildStateContext, buildTool, claimRewardsTool, classifyEffort, clearPriceCache, compactMessages, createGuardRunnerState, defillamaChainTvlTool, defillamaPriceChangeTool, defillamaProtocolFeesTool, defillamaProtocolInfoTool, defillamaSuiProtocolsTool, defillamaTokenPricesTool, defillamaYieldPoolsTool, engineToSSE, estimateTokens, explainTxTool, extractConversationText, extractMcpText, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchTokenPrices, fetchWalletCoins, findTool, getDefaultTools, getMcpManager, getToolFlags, getWalletAddress, guardArtifactPreview, guardStaleData, hasNaviMcp, healthCheckTool, loadRecipes, microcompact, mppServicesTool, parseMcpJson, parseRecipe, parseSSE, payApiTool, portfolioAnalysisTool, protocolDeepDiveTool, ratesInfoTool, registerEngineTools, renderCanvasTool, repayDebtTool, requireAgent, resolvePermissionTier, resolveUsdValue, runGuards, runTools, saveContactTool, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, spendingAnalyticsTool, swapExecuteTool, swapQuoteTool, toolNameToOperation, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, updateGuardStateAfterToolResult, validateHistory, voloStakeTool, voloStatsTool, voloUnstakeTool, webSearchTool, withdrawTool, yieldSummaryTool };
|
|
5986
|
+
export { AnthropicProvider, BalanceTracker, CANVAS_TEMPLATES, ContextBudget, CostTracker, DEFAULT_GUARD_CONFIG, DEFAULT_PERMISSION_CONFIG, DEFAULT_SYSTEM_PROMPT, EarlyToolDispatcher, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_SERVER_NAME, NaviTools, PERMISSION_PRESETS, QueryEngine, READ_TOOLS, RecipeRegistry, RetryTracker, TOOL_FLAGS, TOOL_MODIFIABLE_FIELDS, TxMutex, WRITE_TOOLS, activitySummaryTool, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, applyToolFlags, balanceCheckTool, borrowTool, budgetToolResult, buildCachedSystemPrompt, buildMcpTools, buildProactivenessInstructions, buildProfileContext, buildSelfEvaluationInstruction, buildStateContext, buildTool, claimRewardsTool, classifyEffort, clearPriceCache, compactMessages, createGuardRunnerState, defillamaChainTvlTool, defillamaPriceChangeTool, defillamaProtocolFeesTool, defillamaProtocolInfoTool, defillamaSuiProtocolsTool, defillamaTokenPricesTool, defillamaYieldPoolsTool, engineToSSE, estimateTokens, explainTxTool, extractConversationText, extractMcpText, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchTokenPrices, fetchWalletCoins, findTool, getDefaultTools, getMcpManager, getModifiableFields, getToolFlags, getWalletAddress, guardArtifactPreview, guardStaleData, hasNaviMcp, healthCheckTool, loadRecipes, microcompact, mppServicesTool, parseMcpJson, parseRecipe, parseSSE, payApiTool, portfolioAnalysisTool, protocolDeepDiveTool, ratesInfoTool, registerEngineTools, renderCanvasTool, repayDebtTool, requireAgent, resolvePermissionTier, resolveUsdValue, runGuards, runTools, saveContactTool, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, spendingAnalyticsTool, swapExecuteTool, swapQuoteTool, toolNameToOperation, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, updateGuardStateAfterToolResult, validateHistory, voloStakeTool, voloStatsTool, voloUnstakeTool, webSearchTool, withdrawTool, yieldSummaryTool };
|
|
5674
5987
|
//# sourceMappingURL=index.js.map
|
|
5675
5988
|
//# sourceMappingURL=index.js.map
|