@t2000/engine 0.46.11 → 0.46.12
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 +10 -0
- package/dist/index.js +58 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -228,6 +228,14 @@ interface GuardConfig {
|
|
|
228
228
|
* upstream guard (e.g. an off-process verifier).
|
|
229
229
|
*/
|
|
230
230
|
addressSource?: boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Companion to `addressSource`: blocks send_transfer that defaults to
|
|
233
|
+
* USDC when the user's recent messages clearly named a non-USDC token
|
|
234
|
+
* (SUI, USDT, WAL, etc.). Without this, the LLM would call
|
|
235
|
+
* `send_transfer({ amount, to })` for a "send my SUI" request and the
|
|
236
|
+
* tool would silently ship USDC. Default on.
|
|
237
|
+
*/
|
|
238
|
+
assetIntent?: boolean;
|
|
231
239
|
}
|
|
232
240
|
declare const DEFAULT_GUARD_CONFIG: GuardConfig;
|
|
233
241
|
declare class BalanceTracker {
|
|
@@ -1862,11 +1870,13 @@ declare const withdrawTool: Tool<{
|
|
|
1862
1870
|
declare const sendTransferTool: Tool<{
|
|
1863
1871
|
to: string;
|
|
1864
1872
|
amount: number;
|
|
1873
|
+
asset?: string | undefined;
|
|
1865
1874
|
memo?: string | undefined;
|
|
1866
1875
|
}, {
|
|
1867
1876
|
success: boolean;
|
|
1868
1877
|
tx: string;
|
|
1869
1878
|
amount: number;
|
|
1879
|
+
asset: "USDC" | "USDT" | "SUI" | "USDe" | "USDsui" | "WAL" | "ETH" | "NAVX" | "GOLD";
|
|
1870
1880
|
to: string;
|
|
1871
1881
|
contactName: string | undefined;
|
|
1872
1882
|
gasCost: number;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { resolveSymbol, getDecimalsForCoinType, assertAllowedAsset, getSwapQuote, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
|
|
2
|
+
import { ALL_NAVI_ASSETS, resolveSymbol, getDecimalsForCoinType, assertAllowedAsset, SUPPORTED_ASSETS, getSwapQuote, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
|
|
3
3
|
import { readdirSync, readFileSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import yaml from 'js-yaml';
|
|
@@ -1447,12 +1447,14 @@ var withdrawTool = buildTool({
|
|
|
1447
1447
|
};
|
|
1448
1448
|
}
|
|
1449
1449
|
});
|
|
1450
|
+
var ASSET_LIST = ALL_NAVI_ASSETS.map((a) => String(a)).join(", ");
|
|
1450
1451
|
var sendTransferTool = buildTool({
|
|
1451
1452
|
name: "send_transfer",
|
|
1452
|
-
description:
|
|
1453
|
+
description: `Send ANY supported token (${ASSET_LIST}) to another Sui address or contact name. Validates the address, checks balance, and executes the on-chain transfer. MUST set the \`asset\` field to the token symbol you want to send (case-insensitive). If \`asset\` is omitted, USDC is assumed \u2014 only do this when the user explicitly asks for USDC. When the user asks to send a token by name (SUI, USDT, etc.) or to send the proceeds of a just-completed swap, you MUST pass \`asset\` matching that token. Returns tx hash, gas cost, and updated balance.`,
|
|
1453
1454
|
inputSchema: z.object({
|
|
1454
1455
|
to: z.string().min(1),
|
|
1455
1456
|
amount: z.number().positive(),
|
|
1457
|
+
asset: z.string().optional(),
|
|
1456
1458
|
memo: z.string().optional()
|
|
1457
1459
|
}),
|
|
1458
1460
|
jsonSchema: {
|
|
@@ -1464,7 +1466,11 @@ var sendTransferTool = buildTool({
|
|
|
1464
1466
|
},
|
|
1465
1467
|
amount: {
|
|
1466
1468
|
type: "number",
|
|
1467
|
-
description: "Amount in USD
|
|
1469
|
+
description: "Amount of the asset to send (denominated in the asset\u2019s own units, NOT USD). For USDC this is the USDC count; for SUI this is the SUI count."
|
|
1470
|
+
},
|
|
1471
|
+
asset: {
|
|
1472
|
+
type: "string",
|
|
1473
|
+
description: `Token symbol to send. One of: ${ASSET_LIST}. Defaults to USDC if omitted. REQUIRED whenever the user names a non-USDC token or you are forwarding the proceeds of a swap.`
|
|
1468
1474
|
},
|
|
1469
1475
|
memo: {
|
|
1470
1476
|
type: "string",
|
|
@@ -1487,16 +1493,27 @@ var sendTransferTool = buildTool({
|
|
|
1487
1493
|
if (input.amount <= 0) {
|
|
1488
1494
|
return { valid: false, error: "Amount must be positive." };
|
|
1489
1495
|
}
|
|
1496
|
+
if (input.asset !== void 0) {
|
|
1497
|
+
const normalized = String(input.asset).toUpperCase();
|
|
1498
|
+
if (!(normalized in SUPPORTED_ASSETS)) {
|
|
1499
|
+
return {
|
|
1500
|
+
valid: false,
|
|
1501
|
+
error: `Unsupported asset "${input.asset}". send_transfer accepts: ${ASSET_LIST}.`
|
|
1502
|
+
};
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1490
1505
|
return { valid: true };
|
|
1491
1506
|
},
|
|
1492
1507
|
async call(input, context) {
|
|
1493
1508
|
const agent = requireAgent(context);
|
|
1494
|
-
const
|
|
1509
|
+
const asset = input.asset ? String(input.asset).toUpperCase() : "USDC";
|
|
1510
|
+
const result = await agent.send({ to: input.to, amount: input.amount, asset });
|
|
1495
1511
|
return {
|
|
1496
1512
|
data: {
|
|
1497
1513
|
success: result.success,
|
|
1498
1514
|
tx: result.tx,
|
|
1499
1515
|
amount: result.amount,
|
|
1516
|
+
asset,
|
|
1500
1517
|
to: result.to,
|
|
1501
1518
|
contactName: result.contactName,
|
|
1502
1519
|
gasCost: result.gasCost,
|
|
@@ -1504,7 +1521,7 @@ var sendTransferTool = buildTool({
|
|
|
1504
1521
|
balance: result.balance,
|
|
1505
1522
|
memo: input.memo ?? null
|
|
1506
1523
|
},
|
|
1507
|
-
displayText: `Sent
|
|
1524
|
+
displayText: `Sent ${result.amount} ${asset} to ${result.contactName ?? `${result.to.slice(0, 10)}\u2026`} (tx: ${result.tx.slice(0, 8)}\u2026)`
|
|
1508
1525
|
};
|
|
1509
1526
|
}
|
|
1510
1527
|
});
|
|
@@ -3610,7 +3627,8 @@ var DEFAULT_GUARD_CONFIG = {
|
|
|
3610
3627
|
costWarning: true,
|
|
3611
3628
|
retryProtection: true,
|
|
3612
3629
|
inputValidation: true,
|
|
3613
|
-
addressSource: true
|
|
3630
|
+
addressSource: true,
|
|
3631
|
+
assetIntent: true
|
|
3614
3632
|
};
|
|
3615
3633
|
var BalanceTracker = class {
|
|
3616
3634
|
lastBalanceAt = 0;
|
|
@@ -3793,6 +3811,37 @@ var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{64}$/;
|
|
|
3793
3811
|
function normalizeAddress(addr) {
|
|
3794
3812
|
return addr.trim().toLowerCase();
|
|
3795
3813
|
}
|
|
3814
|
+
var NON_USDC_TOKEN_WORDS = [
|
|
3815
|
+
// Patterns are anchored with \b on both sides. Case-insensitive.
|
|
3816
|
+
{ symbol: "SUI", pattern: /\bSUI\b/i },
|
|
3817
|
+
{ symbol: "USDT", pattern: /\bUSDT\b/i },
|
|
3818
|
+
{ symbol: "USDe", pattern: /\bUSDe\b/i },
|
|
3819
|
+
{ symbol: "USDsui", pattern: /\bUSDsui\b/i },
|
|
3820
|
+
{ symbol: "WAL", pattern: /\bWAL\b/i },
|
|
3821
|
+
{ symbol: "ETH", pattern: /\bETH\b/i },
|
|
3822
|
+
{ symbol: "NAVX", pattern: /\bNAVX\b/i },
|
|
3823
|
+
{ symbol: "GOLD", pattern: /\bGOLD\b/i }
|
|
3824
|
+
];
|
|
3825
|
+
function guardAssetIntent(tool, call, userText) {
|
|
3826
|
+
if (tool.name !== "send_transfer") {
|
|
3827
|
+
return { verdict: "pass", gate: "asset_intent", tier: "safety" };
|
|
3828
|
+
}
|
|
3829
|
+
const input = call.input;
|
|
3830
|
+
const assetWasSet = !(input.asset === void 0 || input.asset === null || input.asset === "");
|
|
3831
|
+
if (assetWasSet) {
|
|
3832
|
+
return { verdict: "pass", gate: "asset_intent", tier: "safety" };
|
|
3833
|
+
}
|
|
3834
|
+
const mentioned = NON_USDC_TOKEN_WORDS.find((t) => t.pattern.test(userText));
|
|
3835
|
+
if (!mentioned) {
|
|
3836
|
+
return { verdict: "pass", gate: "asset_intent", tier: "safety" };
|
|
3837
|
+
}
|
|
3838
|
+
return {
|
|
3839
|
+
verdict: "block",
|
|
3840
|
+
gate: "asset_intent",
|
|
3841
|
+
tier: "safety",
|
|
3842
|
+
message: `Asset mismatch: the user's recent messages mention "${mentioned.symbol}" but send_transfer was called without an \`asset\` field (defaults to USDC). If the user asked you to send ${mentioned.symbol}, re-issue send_transfer with \`asset: "${mentioned.symbol}"\`. If the user really meant USDC, set \`asset: "USDC"\` explicitly to confirm intent. Never default to USDC when the user named a different token.`
|
|
3843
|
+
};
|
|
3844
|
+
}
|
|
3796
3845
|
function guardAddressSource(tool, call, userText, contacts, walletAddress) {
|
|
3797
3846
|
if (tool.name !== "send_transfer") {
|
|
3798
3847
|
return { verdict: "pass", gate: "address_source", tier: "safety" };
|
|
@@ -3903,6 +3952,9 @@ function runGuards(tool, call, state, config, conversationContext, onGuardFired,
|
|
|
3903
3952
|
)
|
|
3904
3953
|
);
|
|
3905
3954
|
}
|
|
3955
|
+
if (config.assetIntent !== false) {
|
|
3956
|
+
results.push(guardAssetIntent(tool, call, conversationContext.recentUserText));
|
|
3957
|
+
}
|
|
3906
3958
|
if (config.irreversibility !== false) {
|
|
3907
3959
|
results.push(guardIrreversibility(tool, call, conversationContext.fullText));
|
|
3908
3960
|
}
|