@t2000/engine 1.6.0 → 1.8.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tool.ts","../src/orchestration.ts","../src/tool-flags.ts","../src/navi-config.ts","../src/tools/utils.ts","../src/navi-transforms.ts","../src/sui-rpc.ts","../src/defi-cache.ts","../src/wallet-cache.ts","../src/cross-instance-lock.ts","../src/telemetry.ts","../src/blockvision-prices.ts","../src/audric-api.ts","../src/sui-address.ts","../src/tools/balance.ts","../src/navi-cache.ts","../src/navi-reads.ts","../src/tools/savings.ts","../src/tools/health.ts","../src/tools/rates.ts","../src/tools/history.ts","../src/tools/save.ts","../src/tools/withdraw.ts","../src/tools/transfer.ts","../src/tools/borrow.ts","../src/tools/repay.ts","../src/tools/claim.ts","../src/tools/pay.ts","../src/tools/mpp-services.ts","../src/tools/swap.ts","../src/tools/swap-quote.ts","../src/tools/volo-stake.ts","../src/tools/volo-unstake.ts","../src/tools/volo-stats.ts","../src/tools/contacts.ts","../src/tools/web-search.ts","../src/tools/explain-tx.ts","../src/tools/portfolio-analysis.ts","../src/tools/protocol-deep-dive.ts","../src/tools/receive.ts","../src/tools/canvas.ts","../src/tools/spending.ts","../src/tools/yield-summary.ts","../src/tools/activity-summary.ts","../src/tools/resolve-suins.ts","../src/tools/update-todo.ts","../src/tools/token-prices.ts","../src/tools/index.ts","../src/tools/tool-modifiable-fields.ts","../src/prompt.ts","../src/cost.ts","../src/thinking-budget.ts","../src/guards.ts","../src/compact/microcompact.ts","../src/context.ts","../src/permission-rules.ts","../src/turn-read-cache.ts","../src/early-dispatcher.ts","../src/engine.ts","../src/types.ts","../src/streaming.ts","../src/session.ts","../src/recipes/loader.ts","../src/recipes/registry.ts","../src/classify-effort.ts","../src/eval-summary.ts","../src/prompt-cache.ts","../src/intelligence.ts","../src/state/conversation-state.ts","../src/mcp.ts","../src/mcp-client.ts","../src/mcp-tool-adapter.ts","../src/providers/anthropic.ts"],"names":["getDecimalsForCoinType","activeStore","sleep","resolveSymbol","n","SUI_MAINNET_URL","GAS_RESERVE_SUI","gasReserveUsd","balance","usdcHolding","usdsuiHolding","defi","callNavi","z","result","stamped","borrowed","status","transportHf","hf","STABLECOIN_SYMBOLS","priceFor","records","filtered","cutoffMs","recent","assertAllowedAsset","MPP_GATEWAY","services","inputSchema","SUI_ADDRESS_REGEX","stableStringify","DEFAULT_MAX_TOKENS"],"mappings":"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","file":"index.js","sourcesContent":["import type { z } from 'zod';\nimport type {\n PermissionLevel,\n PreflightResult,\n Tool,\n ToolContext,\n ToolFlags,\n ToolJsonSchema,\n ToolResult,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// buildTool — factory for creating typed, permission-aware tools\n// ---------------------------------------------------------------------------\n\nexport interface BuildToolOptions<TInput, TOutput> {\n name: string;\n description: string;\n inputSchema: z.ZodType<TInput>;\n jsonSchema: ToolJsonSchema;\n call: (input: TInput, context: ToolContext) => Promise<ToolResult<TOutput>>;\n isReadOnly?: boolean;\n permissionLevel?: PermissionLevel;\n flags?: ToolFlags;\n preflight?: (input: TInput) => PreflightResult;\n maxResultSizeChars?: number;\n summarizeOnTruncate?: (result: string, maxChars: number) => string;\n /**\n * [v1.5.1] See `Tool.cacheable`. Default `true`. Set `false` for\n * tools whose results depend on mutable on-chain state.\n */\n cacheable?: boolean;\n}\n\ntype AnyPreflight = (input: unknown) => PreflightResult;\n\nexport function buildTool<TInput, TOutput>(\n opts: BuildToolOptions<TInput, TOutput>,\n): Tool<TInput, TOutput> {\n const isReadOnly = opts.isReadOnly ?? true;\n return {\n name: opts.name,\n description: opts.description,\n inputSchema: opts.inputSchema,\n jsonSchema: opts.jsonSchema,\n call: opts.call,\n isReadOnly,\n isConcurrencySafe: isReadOnly,\n permissionLevel: opts.permissionLevel ?? (isReadOnly ? 'auto' : 'confirm'),\n flags: opts.flags ?? {},\n preflight: opts.preflight as AnyPreflight | undefined,\n maxResultSizeChars: opts.maxResultSizeChars,\n summarizeOnTruncate: opts.summarizeOnTruncate,\n cacheable: opts.cacheable,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tool helpers\n// ---------------------------------------------------------------------------\n\nexport function toolsToDefinitions(tools: Tool[]): {\n name: string;\n description: string;\n input_schema: ToolJsonSchema;\n}[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.jsonSchema,\n }));\n}\n\nexport function findTool(tools: Tool[], name: string): Tool | undefined {\n return tools.find((t) => t.name === name);\n}\n","import type { EngineEvent, Tool, ToolContext } from './types.js';\nimport { findTool } from './tool.js';\n\n// ---------------------------------------------------------------------------\n// Pending tool call — accumulated from provider events\n// ---------------------------------------------------------------------------\n\nexport interface PendingToolCall {\n id: string;\n name: string;\n input: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// TxMutex — serialises write operations to prevent race conditions\n// ---------------------------------------------------------------------------\n\nexport class TxMutex {\n private queue: (() => void)[] = [];\n private locked = false;\n\n async acquire(): Promise<void> {\n if (!this.locked) {\n this.locked = true;\n return;\n }\n return new Promise<void>((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n release(): void {\n const next = this.queue.shift();\n if (next) {\n next();\n } else {\n this.locked = false;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// [SPEC 8 v0.5.1 B3.2] withRetryStats — per-tool retry attempt counter\n//\n// Engine dispatchers wrap each tool invocation with a fresh\n// `retryStats: { attemptCount: 1 }` so every tool gets an isolated counter.\n// The BlockVision retry wrapper (`fetchBlockVisionWithRetry`) deep in the\n// call stack increments `retryStats.attemptCount` on every retry beyond\n// the first attempt; the dispatcher reads it back via `readAttemptCount()`\n// and surfaces the value (when > 1) on the `tool_result` event.\n//\n// Tools that don't use a retry wrapper never observe a non-default value,\n// so `attemptCount` stays undefined on `tool_result` for them — matching\n// the spec's \"kept undefined to avoid header noise on the common path.\"\n// ---------------------------------------------------------------------------\n\nexport function withRetryStats(context: ToolContext): {\n context: ToolContext;\n readAttemptCount: () => number | undefined;\n} {\n const retryStats = { attemptCount: 1 };\n return {\n context: { ...context, retryStats },\n readAttemptCount: () =>\n retryStats.attemptCount > 1 ? retryStats.attemptCount : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// runTools — executes tool calls with parallel reads, serial writes\n// ---------------------------------------------------------------------------\n\nexport async function* runTools(\n pending: PendingToolCall[],\n tools: Tool[],\n context: ToolContext,\n txMutex: TxMutex,\n): AsyncGenerator<EngineEvent> {\n const { reads, writes } = partitionToolCalls(pending, tools);\n\n // Phase 1: execute all read-only tools in parallel\n if (reads.length > 0) {\n const readResults = await Promise.allSettled(\n reads.map(async (call) => {\n const tool = findTool(tools, call.name);\n if (!tool) {\n return {\n call,\n result: { data: { error: `Unknown tool: ${call.name}` } },\n isError: true,\n attemptCount: undefined as number | undefined,\n };\n }\n const { context: toolCtx, readAttemptCount } = withRetryStats(context);\n const execResult = await executeSingleTool(tool, call, toolCtx);\n if (!execResult.isError) {\n execResult.data = budgetToolResult(execResult.data, tool);\n }\n return {\n call,\n result: execResult,\n isError: execResult.isError,\n attemptCount: readAttemptCount(),\n };\n }),\n );\n\n for (const settled of readResults) {\n if (settled.status === 'fulfilled') {\n const { call, result, isError, attemptCount } = settled.value;\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: result.data,\n isError,\n ...(attemptCount !== undefined ? { attemptCount } : {}),\n };\n } else {\n const idx = readResults.indexOf(settled);\n const call = reads[idx];\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: settled.reason?.message ?? 'Tool execution failed' },\n isError: true,\n };\n }\n }\n }\n\n // Phase 2: execute write tools sequentially under mutex\n for (const call of writes) {\n const tool = findTool(tools, call.name);\n if (!tool) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: `Unknown tool: ${call.name}` },\n isError: true,\n };\n continue;\n }\n await txMutex.acquire();\n try {\n const { context: toolCtx, readAttemptCount } = withRetryStats(context);\n const result = await executeSingleTool(tool, call, toolCtx);\n if (!result.isError) {\n result.data = budgetToolResult(result.data, tool);\n }\n const attemptCount = readAttemptCount();\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: result.data,\n isError: result.isError,\n ...(attemptCount !== undefined ? { attemptCount } : {}),\n };\n } catch (err) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: err instanceof Error ? err.message : 'Tool execution failed' },\n isError: true,\n };\n } finally {\n txMutex.release();\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction partitionToolCalls(\n pending: PendingToolCall[],\n tools: Tool[],\n): { reads: PendingToolCall[]; writes: PendingToolCall[] } {\n const reads: PendingToolCall[] = [];\n const writes: PendingToolCall[] = [];\n\n for (const call of pending) {\n const tool = findTool(tools, call.name);\n if (!tool) {\n reads.push(call); // unknown tools treated as reads — will fail safely\n continue;\n }\n if (tool.isReadOnly && tool.isConcurrencySafe) {\n reads.push(call);\n } else {\n writes.push(call);\n }\n }\n\n return { reads, writes };\n}\n\nasync function executeSingleTool(\n tool: Tool,\n call: PendingToolCall,\n context: ToolContext,\n): Promise<{ data: unknown; isError: boolean }> {\n const parsed = tool.inputSchema.safeParse(call.input);\n if (!parsed.success) {\n return {\n data: {\n error: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(', ')}`,\n },\n isError: true,\n };\n }\n\n const result = await tool.call(parsed.data, context);\n return { data: result.data, isError: false };\n}\n\n/**\n * Enforce per-tool result size limits. When a serialized result exceeds\n * `maxResultSizeChars`, truncate it with a hint to re-call with narrower\n * parameters. Uses the tool's custom `summarizeOnTruncate` when available.\n */\nexport function budgetToolResult(\n data: unknown,\n tool: Tool,\n): unknown {\n if (!tool.maxResultSizeChars) return data;\n\n const serialized = typeof data === 'string' ? data : JSON.stringify(data);\n if (serialized.length <= tool.maxResultSizeChars) return data;\n\n if (tool.summarizeOnTruncate) {\n const summarized = tool.summarizeOnTruncate(serialized, tool.maxResultSizeChars);\n try { return JSON.parse(summarized); } catch { return summarized; }\n }\n\n const preview = serialized.slice(0, tool.maxResultSizeChars);\n const linesOmitted = serialized.split('\\n').length - preview.split('\\n').length;\n const note = `[Truncated — ${linesOmitted} lines omitted. Call ${tool.name} with narrower parameters (e.g. smaller date range or limit) to see more.]`;\n /**\n * [v1.5.2] If the original payload was a JSON object, *don't* return a\n * raw sliced string — the slice is invalid JSON, JSON.parse fails, and\n * downstream consumers (frontend card renderers, history-replay logic,\n * etc.) get a string they cannot destructure. Instead, wrap the\n * preview in a structured `_truncated` envelope so the result stays\n * object-shaped. Tools that genuinely return a string (rare) fall\n * through to the legacy concat behavior.\n */\n if (typeof data === 'object' && data !== null) {\n return { _truncated: true, _preview: preview, _note: note };\n }\n return `${preview}\\n\\n${note}`;\n}\n","import type { Tool, ToolFlags } from './types.js';\n\n/**\n * Central registry of tool flags for the guard runner (RE-2.2).\n *\n * Flags are declarative metadata that guards read to decide what checks to run.\n * Read-only tools have no flags by default (empty object).\n *\n * Flag meanings:\n * mutating — changes on-chain state (deposit, swap, send, borrow)\n * requiresBalance — needs sufficient funds to execute\n * affectsHealth — can change borrow health factor\n * irreversible — physical mail, external transfers — can't undo\n * producesArtifact — returns images, documents, generated content\n * costAware — has a monetary cost the user should know about\n * maxRetries — max calls with same input (default: unlimited for reads, 1 for writes)\n */\nexport const TOOL_FLAGS: Record<string, ToolFlags> = {\n // Write tools — financial\n save_deposit: { mutating: true, requiresBalance: true },\n withdraw: { mutating: true, affectsHealth: true },\n send_transfer: { mutating: true, requiresBalance: true, irreversible: true },\n swap_execute: { mutating: true, requiresBalance: true },\n borrow: { mutating: true, affectsHealth: true },\n repay_debt: { mutating: true, requiresBalance: true },\n claim_rewards: { mutating: true },\n volo_stake: { mutating: true, requiresBalance: true },\n volo_unstake: { mutating: true },\n\n // Write tools — pay / services\n pay_api: { mutating: true, requiresBalance: true, costAware: true, producesArtifact: true, maxRetries: 1 },\n\n // Write tools — lightweight (no financial guards)\n save_contact: {},\n\n // [SIMPLIFICATION DAY 7] Removed flag entries for deleted tools:\n // create_schedule, cancel_schedule (DCA schedules retired)\n // toggle_allowance, update_daily_limit, update_permissions (allowance dormant)\n\n // Receive tools — create/cancel mutate server state\n create_payment_link: { mutating: true },\n cancel_payment_link: { mutating: true },\n create_invoice: { mutating: true },\n cancel_invoice: { mutating: true },\n};\n\n/**\n * Apply flags from the central registry to a tool array.\n * Tools not in the registry get empty flags (read-only tools).\n */\nexport function applyToolFlags<T extends Tool>(tools: T[]): T[] {\n return tools.map((tool) => {\n const flags = TOOL_FLAGS[tool.name];\n if (!flags) return tool;\n return { ...tool, flags: { ...tool.flags, ...flags } };\n });\n}\n\n/**\n * Get flags for a tool by name. Returns empty flags if not registered.\n */\nexport function getToolFlags(name: string): ToolFlags {\n return TOOL_FLAGS[name] ?? {};\n}\n","import type { McpServerConfig } from './mcp-client.js';\n\n// ---------------------------------------------------------------------------\n// NAVI MCP server configuration\n// ---------------------------------------------------------------------------\n\nexport const NAVI_SERVER_NAME = 'navi';\nexport const NAVI_MCP_URL = 'https://open-api.naviprotocol.io/api/mcp';\n\nexport const NAVI_MCP_CONFIG: McpServerConfig = {\n name: NAVI_SERVER_NAME,\n url: NAVI_MCP_URL,\n transport: 'streamable-http',\n cacheTtlMs: 30_000,\n readOnly: true,\n};\n\n// ---------------------------------------------------------------------------\n// NAVI MCP tool name constants (as observed from live discovery)\n// ---------------------------------------------------------------------------\n\nexport const NaviTools = {\n GET_POOLS: 'navi_get_pools',\n GET_POOL: 'navi_get_pool',\n GET_PROTOCOL_STATS: 'navi_get_protocol_stats',\n GET_HEALTH_FACTOR: 'navi_get_health_factor',\n GET_BORROW_FEE: 'navi_get_borrow_fee',\n GET_FEES: 'navi_get_fees',\n GET_FLASH_LOAN_ASSETS: 'navi_get_flash_loan_assets',\n GET_FLASH_LOAN_ASSET: 'navi_get_flash_loan_asset',\n GET_LENDING_REWARDS: 'navi_get_lending_rewards',\n GET_AVAILABLE_REWARDS: 'navi_get_available_rewards',\n GET_PRICE_FEEDS: 'navi_get_price_feeds',\n GET_SWAP_QUOTE: 'navi_get_swap_quote',\n GET_BRIDGE_CHAINS: 'navi_get_bridge_chains',\n SEARCH_BRIDGE_TOKENS: 'navi_search_bridge_tokens',\n GET_BRIDGE_QUOTE: 'navi_get_bridge_quote',\n GET_BRIDGE_TX_STATUS: 'navi_get_bridge_tx_status',\n GET_BRIDGE_HISTORY: 'navi_get_bridge_history',\n GET_DCA_ORDERS: 'navi_get_dca_orders',\n GET_DCA_ORDER_DETAILS: 'navi_get_dca_order_details',\n LIST_DCA_ORDERS: 'navi_list_dca_orders',\n GET_COINS: 'navi_get_coins',\n GET_MARKET_CONFIG: 'navi_get_market_config',\n GET_POSITIONS: 'get_positions',\n GET_TRANSACTION: 'sui_get_transaction',\n EXPLAIN_TRANSACTION: 'sui_explain_transaction',\n SEARCH_TOKENS: 'navi_search_tokens',\n} as const;\n","import type { T2000 } from '@t2000/sdk';\nimport type { McpClientManager } from '../mcp-client.js';\nimport { NAVI_SERVER_NAME } from '../navi-config.js';\nimport type { ToolContext } from '../types.js';\n\nexport function hasAgent(context: ToolContext): boolean {\n return !!context.agent;\n}\n\nexport function requireAgent(context: ToolContext): T2000 {\n if (!context.agent) {\n throw new Error(\n 'Tool requires a T2000 agent instance — pass `agent` in EngineConfig',\n );\n }\n return context.agent as T2000;\n}\n\n/**\n * Check if context has an MCP manager with a connected NAVI server\n * and a wallet address for address-dependent reads.\n */\nexport function hasNaviMcp(context: ToolContext): boolean {\n if (!context.mcpManager || !context.walletAddress) return false;\n const mgr = context.mcpManager as McpClientManager;\n return mgr.isConnected(NAVI_SERVER_NAME);\n}\n\n/**\n * Check if context has a connected NAVI MCP (no wallet required).\n * Use for global reads like rates/pools that don't depend on a user address.\n */\nexport function hasNaviMcpGlobal(context: ToolContext): boolean {\n if (!context.mcpManager) return false;\n const mgr = context.mcpManager as McpClientManager;\n return mgr.isConnected(NAVI_SERVER_NAME);\n}\n\n/**\n * Get the MCP client manager from context (assumes hasNaviMcp() is true).\n */\nexport function getMcpManager(context: ToolContext): McpClientManager {\n return context.mcpManager as McpClientManager;\n}\n\n/**\n * Get the wallet address from context (assumes hasNaviMcp() is true).\n */\nexport function getWalletAddress(context: ToolContext): string {\n return context.walletAddress!;\n}\n","import { getDecimalsForCoinType } from '@t2000/sdk';\n\n// ---------------------------------------------------------------------------\n// Raw NAVI MCP response types (as returned by the live NAVI MCP server)\n// ---------------------------------------------------------------------------\n\nexport interface NaviRawPool {\n id: number;\n symbol: string;\n coinType: string;\n price: string;\n market: string;\n ltv: number;\n liquidation: {\n bonus: string;\n ratio: string;\n threshold: string;\n };\n supply: string;\n borrow: string;\n supplyApy: string;\n borrowApy: string;\n}\n\nexport interface NaviRawPosition {\n id: string;\n protocol: string;\n type: string;\n market: string;\n tokenASymbol: string;\n tokenAPrice: number;\n amountA: string;\n tokenBSymbol?: string | null;\n tokenBPrice?: number | null;\n amountB?: string | null;\n valueUSD: string;\n apr: string;\n liquidationThreshold: string;\n lowerPrice?: string | null;\n upperPrice?: string | null;\n currentPrice?: string | null;\n claimableRewards?: string | null;\n isActive?: boolean;\n}\n\nexport interface NaviRawPositionsResponse {\n address: string;\n positions: NaviRawPosition[];\n}\n\nexport interface NaviRawHealthFactor {\n address: string;\n healthFactor: number | null;\n}\n\nexport interface NaviRawCoin {\n coinType: string;\n totalBalance: string;\n coinObjectCount: number;\n symbol?: string;\n decimals?: number;\n}\n\nexport interface NaviRawRewardsResponse {\n address: string;\n rewards: Array<{\n pool?: string;\n rewardType?: string;\n amount?: string;\n symbol?: string;\n valueUsd?: number;\n }>;\n summary: Array<{\n symbol: string;\n totalAmount: string;\n valueUSD?: string;\n }>;\n}\n\nexport interface NaviRawProtocolStats {\n tvl: number;\n totalBorrowUsd: number;\n averageUtilization: number;\n maxApy: number;\n userAmount: number;\n interactionUserAmount: number;\n borrowFee: number;\n}\n\n// ---------------------------------------------------------------------------\n// Transformed engine-friendly types\n// ---------------------------------------------------------------------------\n\nexport interface RatesResult {\n [symbol: string]: {\n saveApy: number;\n borrowApy: number;\n ltv: number;\n price: number;\n };\n}\n\nexport interface HealthFactorResult {\n healthFactor: number;\n supplied: number;\n borrowed: number;\n maxBorrow: number;\n liquidationThreshold: number;\n}\n\nexport interface BalanceResult {\n available: number;\n savings: number;\n debt: number;\n pendingRewards: number;\n gasReserve: number;\n total: number;\n stables: number;\n}\n\nexport interface PositionEntry {\n protocol: string;\n type: 'supply' | 'borrow';\n symbol: string;\n amount: number;\n valueUsd: number;\n apy: number;\n liquidationThreshold: number;\n}\n\nexport interface SavingsResult {\n positions: PositionEntry[];\n earnings: {\n totalYieldEarned: number;\n currentApy: number;\n dailyEarning: number;\n supplied: number;\n };\n fundStatus: {\n supplied: number;\n apy: number;\n earnedToday: number;\n earnedAllTime: number;\n projectedMonthly: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Safe number parser — handles strings, numbers, null, undefined\n// ---------------------------------------------------------------------------\n\nfunction toNum(v: unknown): number {\n if (v == null) return 0;\n const n = typeof v === 'number' ? v : Number(v);\n return Number.isFinite(n) ? n : 0;\n}\n\n// ---------------------------------------------------------------------------\n// Transform: pools → rates\n// ---------------------------------------------------------------------------\n\nexport function transformRates(raw: unknown): RatesResult {\n const pools = Array.isArray(raw) ? (raw as NaviRawPool[]) : [];\n const result: RatesResult = {};\n\n for (const pool of pools) {\n if (!pool.symbol) continue;\n result[pool.symbol] = {\n saveApy: toNum(pool.supplyApy) / 100,\n borrowApy: toNum(pool.borrowApy) / 100,\n ltv: toNum(pool.ltv),\n price: toNum(pool.price),\n };\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Transform: positions → typed PositionEntry[]\n// ---------------------------------------------------------------------------\n\n// NAVI MCP divides ALL position amounts by 10^9 (original storage precision),\n// but newer pools (id > 10) store at the token's native decimals. For 6-decimal\n// stablecoins in newer pools, this makes amounts 1000x too small.\n// Correction factor: 10^(9 - 6) = 1000.\n// Remove this map if/when the NAVI MCP fixes pool-aware decimal handling.\nconst NAVI_NEWER_POOL_SYMBOLS = new Set([\n 'USDSUI', 'USDsui',\n 'SUI_USDE', 'suiUSDe', 'USDe',\n 'suiUSDT',\n]);\nconst NEWER_POOL_FACTOR = 1000;\n\nfunction naviDecimalFactor(symbol: string): number {\n return NAVI_NEWER_POOL_SYMBOLS.has(symbol) ? NEWER_POOL_FACTOR : 1;\n}\n\nexport function transformPositions(raw: unknown): PositionEntry[] {\n const data = raw as NaviRawPositionsResponse | undefined;\n const positions = data?.positions ?? (Array.isArray(raw) ? (raw as NaviRawPosition[]) : []);\n\n return positions.map((p) => {\n const symbol = p.tokenASymbol ?? 'UNKNOWN';\n const factor = naviDecimalFactor(symbol);\n return {\n protocol: p.protocol ?? 'navi',\n type: p.type?.includes('borrow') ? ('borrow' as const) : ('supply' as const),\n symbol,\n amount: toNum(p.amountA) * factor,\n valueUsd: toNum(p.valueUSD) * factor,\n apy: toNum(p.apr) / 100,\n liquidationThreshold: toNum(p.liquidationThreshold),\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Transform: health factor (+ optional positions for enrichment)\n// ---------------------------------------------------------------------------\n\nexport function transformHealthFactor(\n rawHf: unknown,\n rawPositions?: unknown,\n): HealthFactorResult {\n const hf = rawHf as NaviRawHealthFactor | undefined;\n const positions = transformPositions(rawPositions);\n\n const supplied = positions\n .filter((p) => p.type === 'supply')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n const borrowed = positions\n .filter((p) => p.type === 'borrow')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n\n const supplyPositions = positions.filter((p) => p.type === 'supply');\n const weightedLt =\n supplied > 0\n ? supplyPositions.reduce(\n (acc, p) => acc + p.liquidationThreshold * p.valueUsd,\n 0,\n ) / supplied\n : 0;\n\n const maxBorrow = supplied * weightedLt - borrowed;\n\n return {\n healthFactor: toNum(hf?.healthFactor) || (borrowed === 0 ? Infinity : 0),\n supplied,\n borrowed,\n maxBorrow: Math.max(0, maxBorrow),\n liquidationThreshold: weightedLt,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Transform: rewards → typed reward summaries\n// ---------------------------------------------------------------------------\n\nexport interface PendingReward {\n symbol: string;\n totalAmount: number;\n valueUsd: number;\n}\n\nexport function transformRewards(raw: unknown): PendingReward[] {\n const data = raw as NaviRawRewardsResponse | undefined;\n return (data?.summary ?? []).map((s) => ({\n symbol: s.symbol ?? 'UNKNOWN',\n totalAmount: toNum(s.totalAmount),\n valueUsd: toNum(s.valueUSD),\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Transform: coins + positions + rewards → balance breakdown\n// Requires `prices` map (symbol → USD price) for proper cross-currency totals.\n// ---------------------------------------------------------------------------\n\nconst STABLECOIN_SYMBOLS = new Set([\n 'USDC', 'USDT', 'USDe', 'USDsui', 'wUSDC', 'wUSDT', 'suiUSDe', 'USDSUI',\n]);\n\nconst GAS_RESERVE_SUI = 0.05;\n\nexport interface BalancePrices {\n [symbol: string]: number;\n}\n\nexport function transformBalance(\n rawCoins: unknown,\n rawPositions: unknown,\n rawRewards: unknown,\n prices?: BalancePrices,\n): BalanceResult {\n const coins = Array.isArray(rawCoins) ? (rawCoins as NaviRawCoin[]) : [];\n const positions = transformPositions(rawPositions);\n const rewards = transformRewards(rawRewards);\n\n let availableUsd = 0;\n let stablesUsd = 0;\n let gasReserveUsd = 0;\n\n for (const coin of coins) {\n const symbol = coin.symbol ?? '';\n const decimals = coin.decimals ?? getDecimalsForCoinType(coin.coinType ?? '');\n const balance = toNum(coin.totalBalance) / 10 ** decimals;\n const price = prices?.[symbol] ?? (STABLECOIN_SYMBOLS.has(symbol) ? 1 : 0);\n\n if (symbol === 'SUI' || coin.coinType === '0x2::sui::SUI') {\n const reserveAmount = Math.min(balance, GAS_RESERVE_SUI);\n gasReserveUsd = reserveAmount * price;\n availableUsd += (balance - reserveAmount) * price;\n } else {\n availableUsd += balance * price;\n if (STABLECOIN_SYMBOLS.has(symbol)) {\n stablesUsd += balance * price;\n }\n }\n }\n\n const savings = positions\n .filter((p) => p.type === 'supply')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n const debt = positions\n .filter((p) => p.type === 'borrow')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n\n const pendingRewardsUsd = rewards.reduce((sum, r) => sum + r.valueUsd, 0);\n\n return {\n available: availableUsd,\n savings,\n debt,\n pendingRewards: pendingRewardsUsd,\n gasReserve: gasReserveUsd,\n total: availableUsd + savings + gasReserveUsd + pendingRewardsUsd - debt,\n stables: stablesUsd,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Transform: positions + pools → savings info\n// ---------------------------------------------------------------------------\n\nexport function transformSavings(\n rawPositions: unknown,\n rawPools: unknown,\n): SavingsResult {\n const positions = transformPositions(rawPositions);\n const rates = transformRates(rawPools);\n\n const supplyPositions = positions.filter((p) => p.type === 'supply');\n const supplied = supplyPositions.reduce((sum, p) => sum + p.valueUsd, 0);\n\n const weightedApy =\n supplied > 0\n ? supplyPositions.reduce(\n (acc, p) => acc + (rates[p.symbol]?.saveApy ?? p.apy) * p.valueUsd,\n 0,\n ) / supplied\n : 0;\n\n const dailyEarning = (supplied * weightedApy) / 365;\n const projectedMonthly = dailyEarning * 30;\n\n return {\n positions,\n earnings: {\n totalYieldEarned: 0, // not available from MCP reads alone\n currentApy: weightedApy,\n dailyEarning,\n supplied,\n },\n fundStatus: {\n supplied,\n apy: weightedApy,\n earnedToday: dailyEarning,\n earnedAllTime: 0, // not available from MCP reads alone\n projectedMonthly,\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers: extract text content from MCP response\n// ---------------------------------------------------------------------------\n\nexport function extractMcpText(\n content: Array<{ type: string; text?: string; [key: string]: unknown }>,\n): string {\n return content\n .filter((c) => c.type === 'text' && c.text)\n .map((c) => c.text!)\n .join('\\n');\n}\n\nexport function parseMcpJson<T = unknown>(\n content: Array<{ type: string; text?: string; [key: string]: unknown }>,\n): T {\n const text = extractMcpText(content);\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n}\n","// ---------------------------------------------------------------------------\n// Direct Sui JSON-RPC coin fetcher — no SDK dependency required.\n// Uses suix_getAllBalances to get wallet coin balances.\n// ---------------------------------------------------------------------------\n\nimport { getDecimalsForCoinType, resolveSymbol } from '@t2000/sdk';\n\nconst SUI_MAINNET_URL = 'https://fullnode.mainnet.sui.io:443';\n\nexport interface SuiCoinBalance {\n coinType: string;\n totalBalance: string;\n coinObjectCount: number;\n}\n\n/** Supplementary coins not in the SDK registry (legacy/wrapped variants). */\nconst EXTRA_COINS: Record<string, { symbol: string; decimals: number }> = {\n '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN': { symbol: 'USDT', decimals: 6 },\n};\n\nexport interface WalletCoin {\n coinType: string;\n symbol: string;\n decimals: number;\n totalBalance: string;\n coinObjectCount: number;\n}\n\n/**\n * Fetch all coin balances for an address directly from the Sui JSON-RPC.\n * Returns enriched objects with known symbol/decimals where possible.\n */\nexport async function fetchWalletCoins(\n address: string,\n rpcUrl?: string,\n): Promise<WalletCoin[]> {\n const url = rpcUrl || SUI_MAINNET_URL;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_getAllBalances',\n params: [address],\n }),\n signal: AbortSignal.timeout(8_000),\n });\n\n if (!res.ok) {\n throw new Error(`Sui RPC error: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as {\n result?: SuiCoinBalance[];\n error?: { message: string };\n };\n\n if (json.error) {\n throw new Error(`Sui RPC error: ${json.error.message}`);\n }\n\n const balances = json.result ?? [];\n\n return balances.map((b) => {\n const extra = EXTRA_COINS[b.coinType];\n const symbol = extra?.symbol ?? resolveSymbol(b.coinType);\n const decimals = extra?.decimals ?? getDecimalsForCoinType(b.coinType);\n return {\n coinType: b.coinType,\n symbol,\n decimals,\n totalBalance: b.totalBalance,\n coinObjectCount: b.coinObjectCount,\n };\n });\n}\n","// ---------------------------------------------------------------------------\n// DefiCacheStore — pluggable cache backend for `fetchAddressDefiPortfolio`\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// Pre-v0.54 the DeFi cache was a process-local `Map<string, DefiCacheEntry>`\n// inside `blockvision-prices.ts`. That worked for the CLI and for\n// single-instance dev servers, but it broke the SSOT promise on Vercel\n// where every API route runs in its own serverless function with its own\n// process. Three readers (`balance_check` tool, `/api/portfolio` route,\n// `/api/analytics/portfolio-history` route) running on three Vercel\n// instances produced three independent cache states for the same address,\n// so during a BlockVision burst the user saw three different totals on the\n// same chat turn (e.g. $36,991 from balance_check, $36,992 from the\n// timeline canvas, $29,514 from the full-portfolio canvas). This is the\n// exact divergence the SSOT refactor was meant to eliminate.\n//\n// The fix\n// -------\n// `fetchAddressDefiPortfolio` now reads/writes through this `DefiCacheStore`\n// interface. The default `InMemoryDefiCacheStore` preserves the legacy\n// behavior for the CLI / tests / dev. Audric injects an Upstash-backed\n// implementation at engine init so all routes/instances share one cache.\n//\n// Sticky-positive write semantics live in the FETCHER (not the store) so\n// the store stays a dumb key-value with TTL. That keeps the contract small\n// and lets callers swap stores freely without re-implementing policy.\n//\n// Stale tolerance\n// ---------------\n// The store TTL is the **sticky window** (default 30 minutes), not the\n// fresh-data window. Freshness is computed by the fetcher from the entry's\n// `pricedAt` against source-specific thresholds:\n// - `blockvision` — fresh for 60s → fully successful, trust it\n// - `partial` — fresh for 15s → some protocols 429'd, retry sooner\n// - `partial-stale` — fresh for 0s → always re-fetch in the background\n// - `degraded` — never cached → no value to serve\n// If a fresh fetch returns degraded/partial-zero, the fetcher serves the\n// last positive cached value (up to 30 minutes old) marked as\n// `partial-stale` — \"this is the most recent real number we've seen, but\n// BlockVision is currently unreachable, so the canvas/UI can decide\n// whether to render it as-is or with a 'last refresh Nm ago' caveat.\"\n// ---------------------------------------------------------------------------\n\nimport type { DefiSummary } from './blockvision-prices.js';\n\n/** Cache entry stored under each address key. */\nexport interface DefiCacheEntry {\n data: DefiSummary;\n /** Wall-clock ms when this was written — used by the fetcher to compute freshness. */\n pricedAt: number;\n}\n\n/**\n * Pluggable cache backend.\n *\n * All methods are async because Redis-backed implementations are\n * inherently async; the in-memory impl wraps in resolved promises.\n *\n * Implementations MUST tolerate transport errors gracefully — `get`\n * should return `null` (not throw) on backend failure so the fetcher\n * falls through to a fresh BlockVision read instead of erroring the\n * whole `balance_check` call. `set` should swallow errors (logging is\n * fine) so a Redis hiccup doesn't break a successful read.\n */\nexport interface DefiCacheStore {\n /** Returns the cached entry, or `null` if not found / expired / backend error. */\n get(address: string): Promise<DefiCacheEntry | null>;\n\n /** Writes an entry with a TTL in seconds. Errors are swallowed (logged). */\n set(address: string, entry: DefiCacheEntry, ttlSec: number): Promise<void>;\n\n /** Removes the entry for an address. Errors are swallowed. */\n delete(address: string): Promise<void>;\n\n /** Removes all entries. Used by tests and `clearDefiCache()`. */\n clear(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\n/**\n * Process-local cache backed by a `Map`. Used as the default when no\n * other store has been injected via `setDefiCacheStore()`.\n *\n * NOT suitable for multi-instance deployments — each Vercel function\n * instance gets its own Map, which causes the SSOT divergence this\n * module exists to fix. Audric replaces this at engine init with an\n * Upstash-backed store; the CLI keeps it.\n */\nexport class InMemoryDefiCacheStore implements DefiCacheStore {\n private readonly store = new Map<string, { entry: DefiCacheEntry; expiresAt: number }>();\n\n async get(address: string): Promise<DefiCacheEntry | null> {\n const slot = this.store.get(address.toLowerCase());\n if (!slot) return null;\n if (Date.now() >= slot.expiresAt) {\n this.store.delete(address.toLowerCase());\n return null;\n }\n return slot.entry;\n }\n\n async set(address: string, entry: DefiCacheEntry, ttlSec: number): Promise<void> {\n this.store.set(address.toLowerCase(), {\n entry,\n expiresAt: Date.now() + ttlSec * 1000,\n });\n }\n\n async delete(address: string): Promise<void> {\n this.store.delete(address.toLowerCase());\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeStore: DefiCacheStore = new InMemoryDefiCacheStore();\n\n/**\n * Swap the active DeFi cache store. Call once at engine init from a\n * runtime that wants a non-default backend (e.g. Audric injecting\n * `RedisDefiCacheStore`). Idempotent — calling again replaces the\n * previous store, but does NOT migrate entries; warm cache is lost\n * on swap. Tests use this to inject a fake/spy store and `resetDefiCacheStore()`\n * to restore the in-memory default.\n */\nexport function setDefiCacheStore(store: DefiCacheStore): void {\n activeStore = store;\n}\n\n/** Returns the currently active store. Used by `fetchAddressDefiPortfolio`. */\nexport function getDefiCacheStore(): DefiCacheStore {\n return activeStore;\n}\n\n/** Restore the default in-memory store. Used by test teardowns. */\nexport function resetDefiCacheStore(): void {\n activeStore = new InMemoryDefiCacheStore();\n}\n","// ---------------------------------------------------------------------------\n// WalletCacheStore — pluggable cache backend for `fetchAddressPortfolio`\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// Pre-v0.55 the wallet portfolio cache was a process-local\n// `Map<string, PortfolioCacheEntry>` inside `blockvision-prices.ts`.\n// That mirrored the pre-v0.54 DeFi situation exactly: it worked for\n// the CLI and single-instance dev servers but broke the SSOT promise\n// on Vercel where every API route runs in its own serverless function\n// with its own process. `/api/portfolio` and `balance_check` could\n// observe different wallet states for the same address during a\n// BlockVision 429 burst — one route had a healthy cache hit, another\n// freshly degraded to `sui-rpc-degraded` (which can't price\n// non-stables), so the same chat turn rendered different totals on\n// different cards.\n//\n// PR 1+2 of the scaling spec closes the loop by mirroring the v0.54\n// DeFi cache pattern verbatim. The default `InMemoryWalletCacheStore`\n// preserves the legacy behavior for the CLI / tests / dev. Audric\n// injects an Upstash-backed implementation at engine init so all\n// routes/instances share one cache.\n//\n// Sticky-positive write semantics live in the FETCHER (not the store)\n// so the store stays a dumb key-value with TTL. That keeps the\n// contract small and lets callers swap stores freely without\n// re-implementing policy.\n//\n// Stale tolerance\n// ---------------\n// The store TTL is the **sticky window** (default 30 minutes), not\n// the fresh-data window. Freshness is computed by the fetcher from\n// the entry's `pricedAt` against source-specific thresholds:\n// - `blockvision` — fresh for 60s → fully successful, trust it\n// - `sui-rpc-degraded` — fresh for 15s → BV unavailable, retry sooner\n// If a fresh fetch returns `sui-rpc-degraded`, the fetcher serves the\n// last positive `blockvision` value (up to 30 minutes old) instead of\n// overwriting — same sticky-positive contract as DeFi. The cache\n// entry's `pricedAt` is preserved so a UI consumer can render\n// \"last refresh Nm ago\" if it wants to caveat the staleness.\n// ---------------------------------------------------------------------------\n\nimport type { AddressPortfolio } from './blockvision-prices.js';\n\n/** Cache entry stored under each address key. */\nexport interface WalletCacheEntry {\n data: AddressPortfolio;\n /**\n * Wall-clock ms when this entry was WRITTEN to the cache — used by\n * the fetcher to compute freshness.\n *\n * Distinct from `data.pricedAt` (the upstream-data timestamp from\n * BlockVision / Sui RPC). Mirrors `DefiCacheEntry.pricedAt` for\n * cross-pattern consistency.\n */\n pricedAt: number;\n}\n\n/**\n * Pluggable cache backend.\n *\n * All methods are async because Redis-backed implementations are\n * inherently async; the in-memory impl wraps in resolved promises.\n *\n * Implementations MUST tolerate transport errors gracefully — `get`\n * should return `null` (not throw) on backend failure so the fetcher\n * falls through to a fresh BlockVision read instead of erroring the\n * whole `balance_check` call. `set` should swallow errors (logging is\n * fine) so a Redis hiccup doesn't break a successful read.\n */\nexport interface WalletCacheStore {\n /** Returns the cached entry, or `null` if not found / expired / backend error. */\n get(address: string): Promise<WalletCacheEntry | null>;\n\n /** Writes an entry with a TTL in seconds. Errors are swallowed (logged). */\n set(address: string, entry: WalletCacheEntry, ttlSec: number): Promise<void>;\n\n /** Removes the entry for an address. Errors are swallowed. */\n delete(address: string): Promise<void>;\n\n /** Removes all entries. Used by tests and `clearPortfolioCache()`. */\n clear(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\n/**\n * Process-local cache backed by a `Map`. Used as the default when no\n * other store has been injected via `setWalletCacheStore()`.\n *\n * NOT suitable for multi-instance deployments — each Vercel function\n * instance gets its own Map, which causes the SSOT divergence this\n * module exists to fix. Audric replaces this at engine init with an\n * Upstash-backed store; the CLI and MCP server keep it.\n *\n * Address normalization: keys are lowercased to match the\n * `UpstashWalletCacheStore.key()` convention. Sui addresses are\n * case-insensitive after the `0x` prefix in practice; keying by\n * lowercase prevents accidental cache misses from `0xABC...` vs\n * `0xabc...` callers (e.g. one route normalizes, another doesn't).\n */\nexport class InMemoryWalletCacheStore implements WalletCacheStore {\n private readonly store = new Map<string, { entry: WalletCacheEntry; expiresAt: number }>();\n\n async get(address: string): Promise<WalletCacheEntry | null> {\n const slot = this.store.get(address.toLowerCase());\n if (!slot) return null;\n if (Date.now() >= slot.expiresAt) {\n this.store.delete(address.toLowerCase());\n return null;\n }\n return slot.entry;\n }\n\n async set(address: string, entry: WalletCacheEntry, ttlSec: number): Promise<void> {\n this.store.set(address.toLowerCase(), {\n entry,\n expiresAt: Date.now() + ttlSec * 1000,\n });\n }\n\n async delete(address: string): Promise<void> {\n this.store.delete(address.toLowerCase());\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeStore: WalletCacheStore = new InMemoryWalletCacheStore();\n\n/**\n * Swap the active wallet cache store. Call once at engine init from a\n * runtime that wants a non-default backend (e.g. Audric injecting\n * `UpstashWalletCacheStore`). Idempotent — calling again replaces the\n * previous store, but does NOT migrate entries; warm cache is lost on\n * swap. Tests use this to inject a fake/spy store and\n * `resetWalletCacheStore()` to restore the in-memory default.\n */\nexport function setWalletCacheStore(store: WalletCacheStore): void {\n activeStore = store;\n}\n\n/** Returns the currently active store. Used by `fetchAddressPortfolio`. */\nexport function getWalletCacheStore(): WalletCacheStore {\n return activeStore;\n}\n\n/** Restore the default in-memory store. Used by test teardowns. */\nexport function resetWalletCacheStore(): void {\n activeStore = new InMemoryWalletCacheStore();\n}\n","// ---------------------------------------------------------------------------\n// FetchLock — pluggable cross-instance request coalescing\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// Even with v0.54's shared DeFi cache and v0.55's shared wallet cache,\n// when N concurrent Vercel instances all miss the cache for the same\n// address at the same instant, all N independently fire the BlockVision\n// portfolio call AND the 9-protocol DeFi fan-out. At 200 concurrent\n// users with one popular shared address (e.g. a treasury everyone is\n// watching), a single cache-miss instant produces 200 × 10 = 2000 BV\n// calls in <1 second — self-inflicted DoS.\n//\n// `defiInflight` and `portfolioInflight` Maps coalesce WITHIN a process,\n// but every Vercel instance is its own process. We need a CROSS-process\n// coalescer.\n//\n// The contract\n// ------------\n// `awaitOrFetch(key, fetcher, opts)`:\n// 1. Try `lock.acquire(key, leaseSec)` — backed by Upstash `SET NX EX`\n// in production, in-memory Map in CLI/tests/dev.\n// 2. **Lock acquired** → run `fetcher()` (which writes the cache as\n// its last act), then `release()`. Cache write is the signal —\n// no separate pub/sub channel needed.\n// 3. **Lock NOT acquired** → another instance is fetching. Poll\n// `opts.pollCache()` every ~100ms (jittered) for up to\n// `pollBudgetMs`. If cache fills → return that. If timeout →\n// fall through to a direct `fetcher()` call (defensive degraded\n// path; never block forever on a phantom lock).\n//\n// Lease sizing\n// ------------\n// Default lease is **15 seconds**, sized for the worst-case\n// `fetchBlockVisionWithRetry` budget:\n// - 3 HTTP attempts × 4s timeout = 12s\n// - + backoff sleeps 250ms + 750ms = 1s\n// - Total ≈ 13s\n// A shorter lease (e.g. 5s) expires mid-fetch under load, the leader\n// loses the lock, a follower acquires it, and now 2 instances are\n// fetching the same address — exactly the amplification we exist to\n// prevent. We never extend; if a process dies, the lease expires and\n// the next caller takes over.\n//\n// Default poll budget is **4.5 seconds** — must be < the engine's\n// per-tool timeout (typically 5s for `balance_check` /\n// `portfolio_analysis`) so a dead leader doesn't cascade into a tool\n// timeout for every follower. 4.5s × 100ms poll = ≤45 cheap GETs per\n// follower per coalesced fan-out.\n//\n// Implementation note: store transport errors are swallowed and the\n// caller falls through to `fetcher()` (i.e. degrades to per-instance\n// fetching). A Redis outage should never break a successful read.\n// ---------------------------------------------------------------------------\n\n/**\n * Pluggable distributed mutex. Implementations MUST tolerate transport\n * errors gracefully — `acquire` returning `false` (not throwing) on\n * backend failure is fine; the caller will fall through to a direct\n * fetch. The Upstash impl uses `SET NX EX` which is the canonical\n * Redis distributed-lock primitive at this scale.\n */\nexport interface FetchLock {\n /**\n * Try to acquire the lock for `key`, with an automatic expiry of\n * `leaseSec` seconds.\n *\n * Returns `true` if acquired (caller is now the leader for that key,\n * MUST call `release` when done). Returns `false` if the lock is\n * already held by someone else (caller is a follower).\n *\n * Errors are swallowed (logged); on backend failure return `false`\n * so the caller falls through to its degraded direct-fetch path.\n */\n acquire(key: string, leaseSec: number): Promise<boolean>;\n\n /**\n * Release the lock for `key`. Idempotent — calling on a key the\n * caller doesn't hold is a no-op (we accept a small window of\n * potential ABA: if our lease expired and another caller took the\n * key, we'll harmlessly delete THEIR lock once. Production traffic\n * patterns make this exceedingly rare; the cost is one extra\n * fan-out, which is the same cost we'd pay anyway under contention.)\n *\n * Errors are swallowed (logged) — release failures are non-fatal\n * because the lease expires on its own.\n */\n release(key: string): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\n/**\n * Process-local mutex backed by a `Map<key, expiryMs>`. Used as the\n * default when no other lock has been injected via `setFetchLock()`.\n *\n * NOT suitable for multi-instance deployments — each Vercel function\n * instance gets its own Map, which means N concurrent instances all\n * acquire successfully and all fan out to BlockVision. Audric replaces\n * this at engine init with `UpstashFetchLock`; the CLI keeps it\n * (single-process, so process-local is correct).\n */\nexport class InMemoryFetchLock implements FetchLock {\n private readonly held = new Map<string, number>();\n\n async acquire(key: string, leaseSec: number): Promise<boolean> {\n const now = Date.now();\n const expiry = this.held.get(key);\n if (expiry !== undefined && expiry > now) return false;\n this.held.set(key, now + leaseSec * 1000);\n return true;\n }\n\n async release(key: string): Promise<void> {\n this.held.delete(key);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeLock: FetchLock = new InMemoryFetchLock();\n\n/**\n * Swap the active fetch lock backend. Call once at engine init from a\n * runtime that wants a non-default backend (e.g. Audric injecting\n * `UpstashFetchLock`). Idempotent — calling again replaces the previous\n * lock instance, but does NOT migrate held leases (which are stored in\n * the backend, not the lock object).\n */\nexport function setFetchLock(lock: FetchLock): void {\n activeLock = lock;\n}\n\n/** Returns the currently active lock. Used by `awaitOrFetch`. */\nexport function getFetchLock(): FetchLock {\n return activeLock;\n}\n\n/** Restore the default in-memory lock. Used by test teardowns. */\nexport function resetFetchLock(): void {\n activeLock = new InMemoryFetchLock();\n}\n\n// ---------------------------------------------------------------------------\n// awaitOrFetch — the high-level coalescing primitive\n// ---------------------------------------------------------------------------\n\n/** Default lease seconds — sized for worst-case BV retry budget. See header. */\nexport const DEFAULT_LEASE_SEC = 15;\n\n/** Default follower poll budget ms — must be < engine per-tool timeout. */\nexport const DEFAULT_POLL_BUDGET_MS = 4_500;\n\n/** Default poll interval ms (jittered ±20%) — ~45 GETs over 4.5s. */\nexport const DEFAULT_POLL_INTERVAL_MS = 100;\n\nexport interface AwaitOrFetchOpts<T> {\n /** Override the active lock instance (test seam). */\n lock?: FetchLock;\n /** Lease seconds for `lock.acquire`. Default 15. */\n leaseSec?: number;\n /** Total ms a follower will poll the cache before falling through. Default 4500. */\n pollBudgetMs?: number;\n /** Poll cadence ms (jittered ±20%). Default 100. */\n pollIntervalMs?: number;\n /**\n * Optional cache reader for followers. If provided, followers poll\n * this every `pollIntervalMs` (jittered) until it returns non-null\n * or the budget is exhausted. If omitted, followers fall through\n * immediately to a direct `fetcher()` call (no coalescing benefit).\n *\n * The follower's \"is this fresh enough?\" decision lives inside this\n * callback — it should return `null` when the cache entry exists but\n * is too stale to serve, so the poll keeps trying.\n */\n pollCache?: () => Promise<T | null>;\n /** Test seam — defaults to `Math.random()`. */\n rng?: () => number;\n /** Test seam — defaults to `setTimeout`-backed promise. */\n sleep?: (ms: number) => Promise<void>;\n /** Test seam — defaults to `Date.now()`. */\n now?: () => number;\n /** Optional abort signal — caller cancellation halts polling. */\n signal?: AbortSignal;\n}\n\n/**\n * Cross-instance request coalescer.\n *\n * `key` MUST be stable across instances for the same logical fetch —\n * e.g. `bv-lock:wallet:0xabc...` for the wallet portfolio of `0xabc...`.\n * Different operations on the same address (wallet vs DeFi) MUST use\n * different keys so they don't block each other.\n *\n * `fetcher` is the leader's work. It SHOULD write the cache as its\n * last act, otherwise followers will time out and fall through to\n * direct fetches (functionally correct, just no coalescing benefit).\n *\n * The leader is guaranteed to call `release()` even if `fetcher()`\n * throws — propagated to the caller after release completes.\n *\n * Followers degrade to direct `fetcher()` on:\n * - lock backend failure (`acquire` threw or returned `false` due to a\n * transport error rather than contention)\n * - poll budget exhausted (leader didn't write cache, or wrote with\n * an old enough `pricedAt` that `pollCache` keeps returning `null`)\n * - no `pollCache` callback provided\n */\nexport async function awaitOrFetch<T>(\n key: string,\n fetcher: () => Promise<T>,\n opts: AwaitOrFetchOpts<T> = {},\n): Promise<T> {\n const lock = opts.lock ?? getFetchLock();\n const leaseSec = opts.leaseSec ?? DEFAULT_LEASE_SEC;\n const pollBudgetMs = opts.pollBudgetMs ?? DEFAULT_POLL_BUDGET_MS;\n const pollIntervalMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const rng = opts.rng ?? Math.random;\n const now = opts.now ?? Date.now;\n const sleep =\n opts.sleep ??\n ((ms: number) =>\n new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, ms);\n if (opts.signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n if (opts.signal.aborted) onAbort();\n else opts.signal.addEventListener('abort', onAbort, { once: true });\n }\n }));\n\n let acquired = false;\n try {\n acquired = await lock.acquire(key, leaseSec);\n } catch (err) {\n // Backend failure — degrade to direct fetch (no coalescing).\n console.warn(`[fetch-lock] acquire(${key}) threw; falling through to direct fetch:`, err);\n return fetcher();\n }\n\n if (acquired) {\n try {\n return await fetcher();\n } finally {\n try {\n await lock.release(key);\n } catch (err) {\n // Release failure is non-fatal — lease expires on its own.\n console.warn(`[fetch-lock] release(${key}) failed (non-fatal):`, err);\n }\n }\n }\n\n // ---------------------------------------------------------------\n // Follower path\n // ---------------------------------------------------------------\n // Without a pollCache there's no benefit to waiting — a follower\n // can't know when the leader is done. Fall through immediately.\n if (!opts.pollCache) {\n return fetcher();\n }\n\n const deadline = now() + pollBudgetMs;\n while (now() < deadline) {\n // Symmetric jitter ±20% so concurrent followers don't hammer\n // Redis on synchronized 100ms boundaries.\n const jitterPx = (rng() * 0.4 - 0.2) * pollIntervalMs;\n const wait = Math.max(0, pollIntervalMs + jitterPx);\n try {\n await sleep(wait);\n } catch (err) {\n // Caller cancelled mid-poll — propagate.\n if ((err as { name?: string })?.name === 'AbortError') throw err;\n // Anything else is a sleep impl bug; bail to direct fetch.\n return fetcher();\n }\n let cached: T | null = null;\n try {\n cached = await opts.pollCache();\n } catch (err) {\n // pollCache transport failure — log and keep polling, not the\n // caller's problem. Eventually the budget runs out and we fall\n // through to a direct fetch.\n console.warn(`[fetch-lock] pollCache(${key}) threw; continuing to poll:`, err);\n }\n if (cached !== null) return cached;\n }\n\n // Defensive degraded path: leader didn't fill the cache within the\n // poll budget. Could be a dead leader, a too-slow leader, or a\n // misconfigured pollCache that always returns null. Fetching\n // directly preserves correctness at the cost of one fan-out.\n return fetcher();\n}\n","// ---------------------------------------------------------------------------\n// TelemetrySink — pluggable observability backend for hot-path counters\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// PR 5 of the scaling spec adds structured counters/gauges/histograms to\n// the engine's hot paths (BlockVision retry, NAVI MCP, Anthropic usage).\n// The engine package has no runtime dependency on any observability vendor —\n// it can't import @vercel/analytics because it ships to the CLI and MCP\n// server which have no Vercel runtime. The solution is the same pluggable\n// injection pattern used for the cache stores:\n//\n// - Default `NoopSink` does nothing (zero overhead for CLI/MCP/tests).\n// - Audric injects `VercelTelemetrySink` at engine init, which writes\n// structured `console.log` lines (ingested by Vercel Observability)\n// and calls `track()` for discrete events (Vercel Analytics).\n//\n// The interface is intentionally minimal. We don't need full OTel-style\n// spans or trace IDs at 1k DAU — counters + histograms on the 10 key\n// metrics listed in the spec are enough to answer every incident question\n// this stack will face at this scale.\n//\n// Tag shape\n// ---------\n// Tags are flat key-value string pairs. This matches what both Vercel\n// Observability (structured log fields) and @vercel/analytics `track()`\n// natively consume. No nested objects, no arrays — keep it serializable.\n//\n// Naming convention (mirrors the spec counters table)\n// ---------------------------------------------------\n// bv.requests — BlockVision fetch attempts\n// bv.cache_hit — wallet/defi cache reads\n// bv.cb_open — circuit breaker state (gauge 0|1)\n// navi.requests — NAVI MCP call attempts\n// navi.cache_hit — NAVI cache reads\n// navi.cb_open — NAVI CB state (gauge 0|1)\n// anthropic.tokens — input/output/cache tokens\n// anthropic.latency_ms — per-turn latency (histogram)\n// upstash.requests — store operations\n// cron.fin_ctx_shard_duration_ms — shard processing time (histogram)\n// cron.fin_ctx_users_processed — users processed per shard\n// ---------------------------------------------------------------------------\n\n/** A flat tag bag. Values are strings for universal serialization. */\nexport type TelemetryTags = Record<string, string | number>;\n\n/**\n * Pluggable telemetry backend.\n *\n * All methods are fire-and-forget — implementations MUST NOT throw.\n * Swallow errors internally and optionally log a warning; the hot path\n * should never fail because an observability call failed.\n */\nexport interface TelemetrySink {\n /**\n * Increment a named counter by 1 (or `value` if supplied).\n * Used for discrete countable events: requests, errors, cache hits.\n */\n counter(name: string, tags?: TelemetryTags, value?: number): void;\n\n /**\n * Record the current value of a gauge.\n * Used for point-in-time measurements: circuit-breaker open (0|1),\n * queue depths, active connections.\n */\n gauge(name: string, value: number, tags?: TelemetryTags): void;\n\n /**\n * Record a distribution sample (latency, sizes).\n * Implementations may bucket, percentile, or just counter/average.\n */\n histogram(name: string, value: number, tags?: TelemetryTags): void;\n}\n\n// ---------------------------------------------------------------------------\n// No-op implementation — default for CLI, MCP, tests\n// ---------------------------------------------------------------------------\n\nclass NoopTelemetrySink implements TelemetrySink {\n counter(_name: string, _tags?: TelemetryTags, _value?: number): void {}\n gauge(_name: string, _value: number, _tags?: TelemetryTags): void {}\n histogram(_name: string, _value: number, _tags?: TelemetryTags): void {}\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeSink: TelemetrySink = new NoopTelemetrySink();\n\n/**\n * Swap the active telemetry sink. Call once at engine init from a runtime\n * that wants to emit real metrics (e.g. Audric injecting `VercelTelemetrySink`).\n * Idempotent — calling again replaces the previous sink. Tests can inject\n * a spy sink and use `resetTelemetrySink()` to restore the noop default.\n */\nexport function setTelemetrySink(sink: TelemetrySink): void {\n activeSink = sink;\n}\n\n/** Returns the currently active sink. Used by hot-path instrumentation. */\nexport function getTelemetrySink(): TelemetrySink {\n return activeSink;\n}\n\n/** Restore the default noop sink. Used by test teardowns. */\nexport function resetTelemetrySink(): void {\n activeSink = new NoopTelemetrySink();\n}\n","// ---------------------------------------------------------------------------\n// BlockVision Indexer REST API — wallet portfolio + multi-token price feed.\n//\n// Replaces the DefiLlama public price endpoint (`coins.llama.fi`) for both\n// `balance_check` (full portfolio) and `portfolio_analysis` /\n// `engine-factory` prompt-time price seeding (multi-token quotes).\n//\n// Two endpoints are wrapped here:\n//\n// GET /v2/sui/account/coins — full wallet portfolio + USD prices\n// (paid Pro-tier endpoint; one call)\n// GET /v2/sui/coin/price/list — multi-token price list\n// (max 10 tokens per call; chunked\n// transparently if more are passed)\n//\n// Auth: `x-api-key` header. The shared API key is available as\n// `process.env.BLOCKVISION_API_KEY` in the audric web app and is threaded\n// into `ToolContext.blockvisionApiKey` via the engine factory.\n//\n// Failure mode: layered fallback. If BlockVision `/account/coins` returns\n// 5xx, 429, or the `apiKey` is missing/blank we drop to a Sui-RPC path\n// for the coin list, then [v0.50.3] still attempt the BlockVision\n// `/coin/price/list` endpoint to USD-price non-stable holdings. Only when\n// BOTH BV endpoints fail do we degrade to the hardcoded stable allow-list\n// (USDC/USDT/USDe/USDsui get $1.00, everything else `null`). The two\n// endpoints have separate rate limits and price-list responses are cached\n// in-process for `CACHE_TTL_MS`, so the second call is frequently a hot\n// hit. The `source` field on the returned portfolio surfaces the final\n// path so callers can decide whether to badge \"approximate\" totals.\n// ---------------------------------------------------------------------------\n\nimport { getDecimalsForCoinType, resolveSymbol, normalizeCoinType, isInRegistry } from '@t2000/sdk';\nimport { fetchWalletCoins } from './sui-rpc.js';\nimport { getDefiCacheStore, type DefiCacheEntry, type DefiCacheStore } from './defi-cache.js';\nimport { getWalletCacheStore, type WalletCacheEntry, type WalletCacheStore } from './wallet-cache.js';\nimport { awaitOrFetch } from './cross-instance-lock.js';\nimport { getTelemetrySink } from './telemetry.js';\n\nconst BLOCKVISION_BASE = 'https://api.blockvision.org/v2/sui';\nconst PORTFOLIO_TIMEOUT_MS = 4_000;\nconst PRICES_TIMEOUT_MS = 3_000;\nconst CACHE_TTL_MS = 60_000;\n\n// ---------------------------------------------------------------------------\n// Wallet portfolio cache TTLs (PR 1+2 — v0.55)\n//\n// Per-source freshness for `fetchAddressPortfolio`. Mirrors the DeFi\n// cache pattern (`DEFI_FRESH_TTL_MS_*`). The store TTL we pass to\n// `set(address, entry, ttlSec)` is the **sticky window** (30 min) —\n// we want the entry to STAY in Redis long enough that a sustained\n// BV outage can keep serving the last known-good positive value\n// stamped as such. Freshness is computed by the FETCHER from the\n// entry's own `pricedAt`, not by the store.\n//\n// Why split:\n// - 60s `blockvision` — fully successful BV reply; trust it.\n// - 15s `sui-rpc-degraded` — BV unavailable, retry sooner so the\n// next caller gets a chance to recover.\n//\n// Pre-PR-1 the degraded TTL was emulated with the\n// `ts: Date.now() - (CACHE_TTL_MS - DEGRADED_CACHE_TTL_MS)` aging\n// trick at the write site. That worked under the in-process Map (TTL\n// was client-checked at read time using `ts`) but silently broke\n// under Redis (`EX` is server-enforced and ignores client `ts`).\n// Now we pass per-source TTLs explicitly to `store.set`.\n// ---------------------------------------------------------------------------\nconst WALLET_FRESH_TTL_MS_BLOCKVISION = 60_000;\nconst WALLET_FRESH_TTL_MS_DEGRADED = 15_000;\n/** Sticky window — entries persist this long after their fresh window so\n * brief BV bursts can fall back to last known-good positive. */\nconst WALLET_STICKY_TTL_SEC = 30 * 60;\n/** Lock keyspace prefix for cross-instance fan-out coalescing. */\nconst WALLET_LOCK_KEY = (address: string) => `bv-lock:wallet:${address.toLowerCase()}`;\nconst DEFI_LOCK_KEY = (address: string) => `bv-lock:defi:${address.toLowerCase()}`;\n\n// ---------------------------------------------------------------------------\n// BlockVision retry policy\n//\n// BlockVision Pro periodically returns 429 (\"rate limited\") under burst\n// load — both the per-second key limit AND a global edge throttle that\n// can fire even when the key is well under quota. Without retry, a\n// single 429 cascades through the whole stack:\n// - balance_check's wallet read degrades to Sui-RPC ($0 for long-tail)\n// - DeFi read returns degraded → falls to sticky cache (or empty)\n// - portfolio_analysis trusts the partial+0 → no DeFi line\n//\n// Three attempts with jittered exponential backoff (250/750/2250ms ± 25%)\n// catches the typical 1–3s BV throttle window before any user-visible\n// degradation happens. If BlockVision sends a `Retry-After` header we\n// honor it (capped at 5s to stay inside the per-call timeout budget).\n//\n// Worst case: 250 + 750 = ~1s of waiting before the third (final)\n// attempt. Still well inside the 4s portfolio / 3s prices / 5s defi\n// per-call timeouts because each `fetch()` carries its own\n// `AbortSignal.timeout()` independent of the retry sleep.\n// ---------------------------------------------------------------------------\nconst BV_RETRY_MAX_ATTEMPTS = 3;\nconst BV_RETRY_BASE_DELAY_MS = 250;\nconst BV_RETRY_BACKOFF_FACTOR = 3;\nconst BV_RETRY_JITTER = 0.25;\nconst BV_RETRY_AFTER_CAP_MS = 5_000;\n\n// ---------------------------------------------------------------------------\n// Circuit breaker — scaling guard\n//\n// Naive retry amplifies BV load 3x during sustained outages. At 10k\n// users that's a self-inflicted DoS — every retry burst pushes BV\n// further into rate-limit territory and prolongs the outage. Solution:\n// a process-local circuit breaker. After CB_THRESHOLD 429s within a\n// CB_WINDOW_MS rolling window, open the circuit for CB_COOLDOWN_MS\n// and treat 429s as final (no retry). This isolates retry to the\n// burst case it's designed for and removes amplification during real\n// outages.\n//\n// Per-process state is intentional — global Redis-backed coordination\n// would add latency on the hot path, and each Vercel function having\n// its own breaker is acceptable: at 10k users we'd have ~10–50\n// concurrent function instances; each one independently learning the\n// circuit is open within ~5s of the outage starting is fast enough.\n//\n// Tunables chosen to detect a sustained outage in <5s without\n// false-positiving on momentary bursts that retry would absorb.\n// ---------------------------------------------------------------------------\nconst CB_WINDOW_MS = 5_000;\nconst CB_THRESHOLD = 10;\nconst CB_COOLDOWN_MS = 30_000;\n\nlet cb429Timestamps: number[] = [];\nlet cbOpenUntil = 0;\n\nfunction cbIsOpen(now: number): boolean {\n return now < cbOpenUntil;\n}\n\nfunction cbRecord429(now: number): void {\n cb429Timestamps.push(now);\n cb429Timestamps = cb429Timestamps.filter((t) => now - t < CB_WINDOW_MS);\n if (cb429Timestamps.length >= CB_THRESHOLD && !cbIsOpen(now)) {\n cbOpenUntil = now + CB_COOLDOWN_MS;\n getTelemetrySink().gauge('bv.cb_open', 1);\n console.warn(\n `[blockvision] circuit breaker OPEN — ${CB_THRESHOLD} 429s in ${CB_WINDOW_MS}ms, retries disabled for ${CB_COOLDOWN_MS / 1000}s`,\n );\n cb429Timestamps = [];\n }\n}\n\n/** Test seam — reset breaker state between tests. */\nexport function _resetBlockVisionCircuitBreaker(): void {\n cb429Timestamps = [];\n cbOpenUntil = 0;\n}\n\ninterface BvRetryOpts {\n signal?: AbortSignal;\n /** Test seam — defaults to `Math.random()`. Inject a fixed RNG for deterministic tests. */\n rng?: () => number;\n /** Test seam — defaults to `setTimeout`-backed promise. */\n sleep?: (ms: number) => Promise<void>;\n /** Test seam — defaults to `Date.now()`. Inject for deterministic CB tests. */\n now?: () => number;\n /**\n * [SPEC 8 v0.5.1 B3.2] Mutable counter the engine attaches to\n * `ToolContext.retryStats`. Bumped to `attempt + 1` on every retry\n * iteration past the first, so a 1st-try success leaves the value\n * at 1 and a 2nd-try success leaves it at 2. The dispatcher reads\n * the final value back and surfaces it on the `tool_result` event\n * (only when > 1) so the host renders \"TOOL · attempt N · 1.4s\".\n */\n retryStats?: { attemptCount: number };\n}\n\n/**\n * `fetch()` with bounded retry on transient failures.\n *\n * Retries on:\n * - HTTP 429 (rate limited) — honors `Retry-After` if present\n * - HTTP 5xx (transient server error)\n * - Network errors (DNS, ECONNRESET, etc.) — but NOT AbortError\n *\n * Does NOT retry on:\n * - HTTP 4xx other than 429 (client error — won't change on retry)\n * - AbortError from the caller's signal (caller cancelled — respect)\n *\n * Returns the final `Response` (success or last non-retryable error)\n * so existing `res.ok` / `res.status` checks at call sites continue\n * to work unchanged. Re-throws the original error only when every\n * attempt was a network error (no Response object to return).\n */\nexport async function fetchBlockVisionWithRetry(\n url: string,\n init: RequestInit,\n opts: BvRetryOpts = {},\n): Promise<Response> {\n const rng = opts.rng ?? Math.random;\n const sleep = opts.sleep ?? ((ms: number) =>\n new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, ms);\n // Wire the caller's signal into the sleep so cancelling the\n // overall request aborts the retry wait too — otherwise we'd\n // burn the full backoff before noticing the caller gave up.\n if (opts.signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n if (opts.signal.aborted) onAbort();\n else opts.signal.addEventListener('abort', onAbort, { once: true });\n }\n }));\n\n let lastError: unknown = null;\n let lastResponse: Response | null = null;\n\n for (let attempt = 0; attempt < BV_RETRY_MAX_ATTEMPTS; attempt++) {\n // [SPEC 8 v0.5.1 B3.2] Reflect the actual attempt count (1-indexed) into\n // the caller's mutable counter. Done at the top of every iteration so\n // even a network-error path (which `continue`s) still advances the\n // visible attempt count for the dispatcher's read-back.\n if (opts.retryStats) opts.retryStats.attemptCount = attempt + 1;\n if (attempt > 0) {\n // Base wait with exponential growth: 250, 750, 2250 ms.\n let waitMs = BV_RETRY_BASE_DELAY_MS * Math.pow(BV_RETRY_BACKOFF_FACTOR, attempt - 1);\n // Honor Retry-After when the server told us to wait — capped so\n // a misbehaving header (`Retry-After: 3600`) can't stall a\n // single tool call past its per-call timeout budget.\n const retryAfter = lastResponse?.headers.get('retry-after');\n if (retryAfter) {\n const secs = Number(retryAfter);\n if (Number.isFinite(secs) && secs > 0) {\n waitMs = Math.min(secs * 1000, BV_RETRY_AFTER_CAP_MS);\n }\n }\n // Symmetric jitter (±jitterFactor) to spread out caller bursts\n // — without it, every concurrent request retries at the same\n // moment and re-creates the burst we're trying to absorb.\n const jitterPx = (rng() * 2 - 1) * BV_RETRY_JITTER * waitMs;\n const delay = Math.max(0, waitMs + jitterPx);\n try {\n await sleep(delay);\n } catch (err) {\n // Caller aborted during backoff — bail with the last error/\n // response so the caller sees the same surface as if the\n // abort had fired during fetch itself.\n if (lastResponse) return lastResponse;\n throw err;\n }\n }\n\n try {\n lastResponse = await fetch(url, init);\n } catch (err) {\n lastError = err;\n // Don't retry if the caller cancelled — that's intentional.\n if ((err as { name?: string })?.name === 'AbortError') throw err;\n getTelemetrySink().counter('bv.requests', { status: 'network_err', attempt: String(attempt) });\n continue;\n }\n\n if (lastResponse.ok) {\n getTelemetrySink().counter('bv.requests', { status: '2xx', attempt: String(attempt) });\n return lastResponse;\n }\n // 4xx other than 429 are permanent client errors — no point retrying.\n if (lastResponse.status !== 429 && lastResponse.status < 500) {\n getTelemetrySink().counter('bv.requests', { status: String(lastResponse.status), attempt: String(attempt) });\n return lastResponse;\n }\n // Track 429s for the circuit breaker — if too many fire in a\n // short window we stop retrying and let the caller degrade\n // gracefully rather than amplifying load on an already-overloaded\n // upstream.\n if (lastResponse.status === 429) {\n getTelemetrySink().counter('bv.requests', { status: '429', attempt: String(attempt) });\n const now = (opts.now ?? Date.now)();\n cbRecord429(now);\n if (cbIsOpen(now)) {\n return lastResponse;\n }\n } else {\n getTelemetrySink().counter('bv.requests', { status: '5xx', attempt: String(attempt) });\n }\n }\n\n if (lastResponse) return lastResponse;\n throw lastError ?? new Error('fetch failed after retries');\n}\n// [PR 1 — v0.55] `DEGRADED_CACHE_TTL_MS` (the v0.53.3 constant for the\n// Sui-RPC fallback path's effective TTL) was removed alongside the\n// `portfolioCache` Map and its `ts: Date.now() - (CACHE_TTL_MS -\n// DEGRADED_CACHE_TTL_MS)` aging trick. The same effect — short retry\n// window for degraded reads — now lives in `WALLET_FRESH_TTL_MS_DEGRADED`\n// at the top of the file, applied as a per-source `EX` value at write\n// time so Redis enforces it server-side.\n//\n// BlockVision caps `tokenIds` at 10. Internal callers (engine-factory, the\n// future `token_prices` LLM tool) may request more — we chunk transparently.\nconst PRICE_LIST_CHUNK = 10;\n\n/**\n * Hardcoded $1.00 allow-list for the canonical Sui stablecoins. Used in\n * two places:\n * 1. `fetchTokenPrices` short-circuit — the LLM rarely needs to quote\n * USDC/USDT against an external feed, and skipping the network call\n * saves ~200–400ms p50 per balance render.\n * 2. Sui-RPC degraded fallback inside `fetchAddressPortfolio` — when\n * BlockVision is unavailable, stables still resolve to USD so the\n * visible \"$X total\" doesn't suddenly read $0.\n *\n * Coverage rationale: the four native Sui stables (USDC/USDT/USDe/USDsui)\n * plus the two Wormhole-bridged variants present in legacy wallets. We\n * intentionally do NOT include long-tail \"USD*\" tokens — depeg risk is\n * real (e.g. Frax, sUSD) and a stale $1.00 on a depegged asset is more\n * misleading than `null`.\n */\nconst STABLE_USD_PRICES: Readonly<Record<string, number>> = {\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC': 1,\n '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT': 1,\n '0x41d587e5336f1c86cad50d38a7136db99333bb9bda91cea4ba69115defeb1402::sui_usde::SUI_USDE': 1,\n '0x44f838219cf67b058f3b37907b655f226153c18e33dfcd0da559a844fea9b1c1::usdsui::USDSUI': 1,\n '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN': 1,\n '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN': 1,\n};\n\nexport interface PortfolioCoin {\n coinType: string;\n symbol: string;\n decimals: number;\n /** Raw on-chain amount (string to preserve precision). */\n balance: string;\n /** USD spot price; `null` when not available (long-tail, degraded mode). */\n price: number | null;\n /** balance/10^decimals * price; `null` when price is `null`. */\n usdValue: number | null;\n}\n\nexport interface AddressPortfolio {\n coins: PortfolioCoin[];\n totalUsd: number;\n pricedAt: number;\n source: 'blockvision' | 'sui-rpc-degraded';\n}\n\n// [PR 1 — v0.55] The module-level `portfolioCache` Map is gone.\n// Replaced by the pluggable `WalletCacheStore` (default `InMemoryWalletCacheStore`,\n// Audric injects `UpstashWalletCacheStore`). See `wallet-cache.ts` for\n// the why — same SSOT bug class as the v0.54 DeFi work, just on the\n// wallet half. `portfolioInflight` is kept as an in-process coalescer\n// so N concurrent in-process callers share one promise; cross-process\n// coalescing is handled by `awaitOrFetch` in PR 2.\nconst portfolioInflight = new Map<string, Promise<AddressPortfolio>>();\n\ninterface PriceMapCacheEntry {\n prices: Record<string, { price: number; change24h?: number }>;\n ts: number;\n}\nlet priceMapCache: PriceMapCacheEntry | null = null;\n\ninterface BlockVisionAccountCoinsResponse {\n code: number;\n message: string;\n result?: {\n coins?: Array<{\n coinType: string;\n name?: string;\n symbol?: string;\n decimals?: number;\n balance: string;\n verified?: boolean;\n logo?: string;\n usdValue?: string;\n objects?: number;\n price?: string;\n priceChangePercentage24H?: string;\n }>;\n usdValue?: string;\n };\n}\n\ninterface BlockVisionPriceListResponse {\n code: number;\n message: string;\n result?: {\n prices?: Record<string, string>;\n coin24HChange?: Record<string, string>;\n };\n}\n\n/** Source-aware fresh-TTL lookup for wallet portfolio entries. */\nfunction walletFreshTtlMs(source: AddressPortfolio['source']): number {\n switch (source) {\n case 'blockvision':\n return WALLET_FRESH_TTL_MS_BLOCKVISION;\n case 'sui-rpc-degraded':\n return WALLET_FRESH_TTL_MS_DEGRADED;\n }\n}\n\n/**\n * Store-write helper that swallows backend errors. A Redis hiccup\n * during write should never break a successful read — the next caller\n * will simply re-fetch on cache miss. Errors are logged so an outage\n * is still observable in Vercel logs. Mirrors `safeStoreSet` in the\n * DeFi half.\n */\nasync function safeWalletStoreSet(\n store: WalletCacheStore,\n address: string,\n entry: WalletCacheEntry,\n ttlSec: number,\n): Promise<void> {\n try {\n await store.set(address, entry, ttlSec);\n } catch (err) {\n console.warn('[wallet] cache set failed (non-fatal):', err);\n }\n}\n\n/**\n * Read the wallet store, swallowing transport errors as cache misses.\n * Used by both the leader (pre-fanout check) and the follower (poll\n * loop while another instance fetches).\n */\nasync function safeWalletStoreGet(\n store: WalletCacheStore,\n address: string,\n): Promise<WalletCacheEntry | null> {\n try {\n return await store.get(address);\n } catch (err) {\n console.warn('[wallet] cache get failed (continuing as cache miss):', err);\n return null;\n }\n}\n\n/**\n * One-shot wallet portfolio fetcher. BlockVision returns balances + USD\n * prices in a single call; on failure we degrade to a Sui-RPC coin\n * fetch with hardcoded stablecoin pricing.\n *\n * Caching shape (PR 1+2 — v0.55):\n * 1. Store-level cache (Redis in prod, in-memory in CLI/tests). Read\n * first; if entry is fresh-for-source serve directly.\n * 2. In-process inflight Map dedupes concurrent in-process callers\n * onto one promise.\n * 3. The leader path runs under a cross-instance lock\n * (`bv-lock:wallet:<addr>`) so at most one Vercel instance per\n * address is hitting BlockVision at any moment. Followers poll\n * the store for the leader's write; if the leader dies they fall\n * through to a direct fetch as a defensive degraded path.\n *\n * Sticky-positive write rules mirror the DeFi half:\n * - `blockvision` (any total) → write unconditionally; latest BV\n * truth always wins.\n * - `sui-rpc-degraded` → write only when no fresher positive\n * `blockvision` entry exists in the sticky window (30 min). When\n * a positive sticky entry exists, return it as-is and DO NOT\n * overwrite — preserves the original `pricedAt` so a UI can\n * render \"last refresh Nm ago\".\n */\nexport async function fetchAddressPortfolio(\n address: string,\n apiKey: string | undefined,\n fallbackRpcUrl?: string,\n // [SPEC 8 v0.5.1 B3.2] Optional retry-stats counter forwarded to\n // `fetchBlockVisionWithRetry`. The dispatcher passes\n // `ctx.retryStats` here; the wrapper bumps `.attemptCount` on each\n // retry; the dispatcher reads the final value and surfaces it on\n // the `tool_result` event when > 1.\n opts: { retryStats?: { attemptCount: number } } = {},\n): Promise<AddressPortfolio> {\n const store = getWalletCacheStore();\n\n // ---------------------------------------------------------------\n // Read path — source-aware freshness\n // ---------------------------------------------------------------\n const cachedEntry = await safeWalletStoreGet(store, address);\n if (cachedEntry) {\n const ageMs = Date.now() - cachedEntry.pricedAt;\n if (ageMs < walletFreshTtlMs(cachedEntry.data.source)) {\n getTelemetrySink().counter('bv.cache_hit', { kind: 'wallet', freshness: 'fresh' });\n return cachedEntry.data;\n }\n // Stale hit — kept in scope for the sticky-positive fallback below.\n getTelemetrySink().counter('bv.cache_hit', { kind: 'wallet', freshness: 'stale-served' });\n } else {\n getTelemetrySink().counter('bv.cache_hit', { kind: 'wallet', freshness: 'miss' });\n }\n\n // In-process inflight dedup. Even with a cross-instance lock, we\n // still want concurrent in-process callers to share one promise.\n const existing = portfolioInflight.get(address);\n if (existing) return existing;\n\n const promise = (async (): Promise<AddressPortfolio> => {\n try {\n return await awaitOrFetch<AddressPortfolio>(\n WALLET_LOCK_KEY(address),\n // ----------------------------------------------------------\n // Leader path — runs after we've won the cross-instance lock.\n // Re-checks the cache (small window where another leader on a\n // different process just wrote) before paying for the BV call.\n // ----------------------------------------------------------\n async () => {\n const recheck = await safeWalletStoreGet(store, address);\n if (recheck) {\n const ageMs = Date.now() - recheck.pricedAt;\n if (ageMs < walletFreshTtlMs(recheck.data.source)) {\n return recheck.data;\n }\n }\n\n // Try BlockVision first (fast path).\n if (apiKey && apiKey.trim().length > 0) {\n const blockvision = await fetchPortfolioFromBlockVision(address, apiKey, opts.retryStats);\n if (blockvision) {\n // `blockvision` always wins — latest BV truth.\n await safeWalletStoreSet(\n store,\n address,\n { data: blockvision, pricedAt: Date.now() },\n WALLET_STICKY_TTL_SEC,\n );\n return blockvision;\n }\n }\n\n // [v0.50.3] Pass apiKey through so the RPC fallback can\n // still use the BlockVision price-list endpoint to USD-price\n // non-stables. Without this, a transient `/account/coins`\n // failure (429, 5xx, network) would silently zero out every\n // non-stable holding in the wallet view.\n const degraded = await fetchPortfolioFromSuiRpc(address, apiKey, fallbackRpcUrl);\n\n // -----------------------------------------------------\n // Sticky-positive write rules (PR 1 — v0.55)\n //\n // If a positive `blockvision` entry exists within the sticky\n // window, prefer it over a fresh degraded read. This stops a\n // BV burst from poisoning the cache with a $0/missing-token\n // wallet across every Vercel instance simultaneously — the\n // exact divergence that fired three different totals on the\n // same chat turn pre-v0.54 (DeFi half) and pre-v0.55 (wallet\n // half).\n //\n // We use `recheck` (which we read inside the lock) as the\n // basis for the comparison. If `recheck` is null but the\n // pre-lock `cachedEntry` was positive within the sticky\n // window, prefer that — covers the case where the pre-lock\n // read raced a deleting writer.\n // -----------------------------------------------------\n const stickyCandidate =\n recheck && recheck.data.source === 'blockvision' && recheck.data.totalUsd > 0\n ? recheck\n : cachedEntry &&\n cachedEntry.data.source === 'blockvision' &&\n cachedEntry.data.totalUsd > 0\n ? cachedEntry\n : null;\n\n const stickyFresh =\n stickyCandidate && Date.now() - stickyCandidate.pricedAt < WALLET_STICKY_TTL_SEC * 1000;\n\n if (stickyFresh) {\n // Return the cached positive as-is — preserve `pricedAt` so\n // a UI consumer can decide whether to caveat staleness.\n // Do NOT overwrite the cache; the existing entry is still\n // the most truthful thing we have for this address.\n return stickyCandidate!.data;\n }\n\n // No sticky fallback — write the degraded result with a\n // short TTL so the next caller retries BV soon. Pre-PR-1\n // this used the `ts: Date.now() - (CACHE_TTL_MS -\n // DEGRADED_CACHE_TTL_MS)` aging trick to emulate a short\n // TTL on top of the long base TTL; under Redis's\n // server-enforced `EX` that no longer works, so we pass\n // an explicit per-source TTL instead.\n await safeWalletStoreSet(\n store,\n address,\n { data: degraded, pricedAt: Date.now() },\n Math.ceil(WALLET_FRESH_TTL_MS_DEGRADED / 1000),\n );\n return degraded;\n },\n {\n // Followers poll the wallet cache while the leader fetches.\n // Returns non-null only when the leader has written a\n // fresh-for-source entry — stale entries keep the poll going.\n pollCache: async () => {\n const e = await safeWalletStoreGet(store, address);\n if (!e) return null;\n const ageMs = Date.now() - e.pricedAt;\n return ageMs < walletFreshTtlMs(e.data.source) ? e.data : null;\n },\n },\n );\n } finally {\n portfolioInflight.delete(address);\n }\n })();\n\n portfolioInflight.set(address, promise);\n return promise;\n}\n\nasync function fetchPortfolioFromBlockVision(\n address: string,\n apiKey: string,\n retryStats?: { attemptCount: number },\n): Promise<AddressPortfolio | null> {\n const url = `${BLOCKVISION_BASE}/account/coins?account=${encodeURIComponent(address)}`;\n const signal = AbortSignal.timeout(PORTFOLIO_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchBlockVisionWithRetry(\n url,\n {\n headers: { 'x-api-key': apiKey, accept: 'application/json' },\n signal,\n },\n { signal, retryStats },\n );\n } catch (err) {\n console.warn('[blockvision-prices] portfolio fetch threw, degrading:', err);\n return null;\n }\n\n if (!res.ok) {\n console.warn(`[blockvision-prices] portfolio HTTP ${res.status}, degrading`);\n return null;\n }\n\n let json: BlockVisionAccountCoinsResponse;\n try {\n json = (await res.json()) as BlockVisionAccountCoinsResponse;\n } catch (err) {\n console.warn('[blockvision-prices] portfolio JSON parse failed, degrading:', err);\n return null;\n }\n\n if (json.code !== 200 || !json.result) {\n console.warn(`[blockvision-prices] portfolio code=${json.code} msg=${json.message}, degrading`);\n return null;\n }\n\n const rawCoins = json.result.coins ?? [];\n const coins: PortfolioCoin[] = rawCoins.map((c) => {\n const coinType = c.coinType;\n // [v0.55.0 Fix 1] Prefer canonical SDK symbol over the raw symbol returned\n // by BlockVision when the coin type is in COIN_REGISTRY. BlockVision can\n // return uppercase variants (e.g. 'USDSUI') that don't match the canonical\n // mixed-case symbol ('USDsui'), and downstream consumers (balance.ts\n // STABLE_SYMBOLS set + saveableUsdsui find, audric chip flows, useBalance\n // hook) all key off the canonical form. The earlier `c.symbol || resolveSymbol`\n // ordering caused saveableUsdsui to read 0 right after a USDC→USDsui swap\n // because BV's 'USDSUI' beat the registry's 'USDsui' and the find() missed.\n //\n // We use `isInRegistry` (NOT `isSupported`) on purpose: USDsui/USDe/USDT\n // are legacy/no-tier registry entries today, but they STILL have canonical\n // symbol metadata that downstream code keys off. `isSupported` would\n // exclude them and re-introduce the bug.\n //\n // For coins NOT in the registry (memecoins, long-tail tokens) we fall\n // back to whatever BV returns since it's typically more user-friendly\n // than resolveSymbol's last-segment heuristic.\n const symbol = isInRegistry(coinType)\n ? resolveSymbol(coinType)\n : c.symbol || resolveSymbol(coinType);\n const decimals = typeof c.decimals === 'number' ? c.decimals : getDecimalsForCoinType(coinType);\n const stablePrice = STABLE_USD_PRICES[coinType];\n const apiPrice = parseNumberOrNull(c.price);\n const apiUsd = parseNumberOrNull(c.usdValue);\n const price = apiPrice ?? stablePrice ?? null;\n let usdValue = apiUsd;\n if (usdValue == null && price != null) {\n const amount = Number(c.balance) / 10 ** decimals;\n usdValue = Number.isFinite(amount) ? amount * price : null;\n }\n return {\n coinType,\n symbol,\n decimals,\n balance: c.balance,\n price,\n usdValue,\n };\n });\n\n const apiTotal = parseNumberOrNull(json.result.usdValue);\n const totalUsd = apiTotal ?? coins.reduce((sum, c) => sum + (c.usdValue ?? 0), 0);\n\n return {\n coins,\n totalUsd,\n pricedAt: Date.now(),\n source: 'blockvision',\n };\n}\n\nasync function fetchPortfolioFromSuiRpc(\n address: string,\n apiKey: string | undefined,\n fallbackRpcUrl?: string,\n): Promise<AddressPortfolio> {\n const walletCoins = await fetchWalletCoins(address, fallbackRpcUrl).catch((err) => {\n console.warn('[blockvision-prices] sui rpc coin fetch failed:', err);\n return [];\n });\n\n // [v0.50.3] When the BV `/account/coins` endpoint is unavailable\n // (typically a 429 burst, sometimes a 5xx) we still hit the BV\n // `/coin/price/list` endpoint to USD-price non-stable holdings. The two\n // endpoints have separate rate limits and price-list responses are\n // cached for `CACHE_TTL_MS`, so this is cheap and frequently a hot hit.\n // If price-list ALSO fails (e.g. true BV outage) we degrade further to\n // stables-only, which matches the v0.50.2 behaviour. Net effect: one\n // more chance to recover from a BV blip before the wallet shows $0.\n const nonStableCoinTypes = walletCoins\n .map((c) => c.coinType)\n .filter((coinType) => !(coinType in STABLE_USD_PRICES));\n const livePrices =\n apiKey && apiKey.trim().length > 0 && nonStableCoinTypes.length > 0\n ? await fetchTokenPrices(nonStableCoinTypes, apiKey).catch((err) => {\n console.warn('[blockvision-prices] price-list fallback failed:', err);\n return {} as Record<string, { price: number; change24h?: number }>;\n })\n : {};\n\n const coins: PortfolioCoin[] = walletCoins.map((c) => {\n const stablePrice = STABLE_USD_PRICES[c.coinType] ?? null;\n const livePrice = livePrices[c.coinType]?.price ?? null;\n const price = stablePrice ?? livePrice;\n const amount = Number(c.totalBalance) / 10 ** c.decimals;\n const usdValue = price != null && Number.isFinite(amount) ? amount * price : null;\n return {\n coinType: c.coinType,\n symbol: c.symbol,\n decimals: c.decimals,\n balance: c.totalBalance,\n price,\n usdValue,\n };\n });\n\n const totalUsd = coins.reduce((sum, c) => sum + (c.usdValue ?? 0), 0);\n return {\n coins,\n totalUsd,\n pricedAt: Date.now(),\n source: 'sui-rpc-degraded',\n };\n}\n\n/**\n * Multi-token price lookup. Returns a map of coinType → `{ price, change24h }`\n * with the `change24h` field populated when BlockVision returns it.\n * Hardcoded stable allow-list short-circuits before the network call so\n * USDC/USDT lookups don't pay the BlockVision RTT. Chunks transparently\n * (BlockVision caps `tokenIds` at 10 per call). Cached in-process for\n * `CACHE_TTL_MS` with merge-on-miss semantics — a cache containing 8 of 10\n * requested coins fetches only the missing 2 instead of throwing the\n * whole map away.\n */\nexport async function fetchTokenPrices(\n coinTypes: string[],\n apiKey: string | undefined,\n // [SPEC 8 v0.5.1 B3.2] See `fetchAddressPortfolio` for the retry-stats\n // contract.\n opts: { retryStats?: { attemptCount: number } } = {},\n): Promise<Record<string, { price: number; change24h?: number }>> {\n if (coinTypes.length === 0) return {};\n\n const now = Date.now();\n const cacheValid = priceMapCache !== null && now - priceMapCache.ts < CACHE_TTL_MS;\n const cached = cacheValid ? priceMapCache!.prices : {};\n\n // [v0.47.1] Cache + STABLE_USD_PRICES are keyed by long-form coin types\n // (64-hex address). Caller inputs may be short-form (`0x2::sui::SUI`).\n // Normalize for lookup, but preserve the caller's original string in\n // the result map so consumers indexing by their input keys still work.\n const result: Record<string, { price: number; change24h?: number }> = {};\n const stillMissing: string[] = [];\n for (const original of coinTypes) {\n const norm = normalizeCoinType(original);\n if (cached[norm]) {\n result[original] = cached[norm];\n continue;\n }\n const stable = STABLE_USD_PRICES[norm];\n if (typeof stable === 'number') {\n result[original] = { price: stable };\n continue;\n }\n stillMissing.push(original);\n }\n\n if (stillMissing.length === 0) return result;\n if (!apiKey || apiKey.trim().length === 0) {\n return result;\n }\n\n const fetched = await fetchPricesFromBlockVision(stillMissing, apiKey, opts.retryStats);\n Object.assign(result, fetched);\n\n // Cache by long form so subsequent calls with either form hit the cache.\n const cacheUpdates: Record<string, { price: number; change24h?: number }> = {};\n for (const [original, value] of Object.entries(fetched)) {\n cacheUpdates[normalizeCoinType(original)] = value;\n }\n const merged = { ...cached, ...cacheUpdates };\n priceMapCache = { prices: merged, ts: cacheValid ? priceMapCache!.ts : now };\n\n return result;\n}\n\nasync function fetchPricesFromBlockVision(\n coinTypes: string[],\n apiKey: string,\n retryStats?: { attemptCount: number },\n): Promise<Record<string, { price: number; change24h?: number }>> {\n const out: Record<string, { price: number; change24h?: number }> = {};\n\n // [v0.47.1] BlockVision's `/coin/price/list` requires fully-normalized\n // 64-hex coin types — short forms like `0x2::sui::SUI` come back with\n // `result.prices = {}` even on Pro. Normalize before sending; build a\n // long→original map so callers who passed `0x2::sui::SUI` see exactly\n // that key in the response (not the long form BlockVision echoes back).\n const longToOriginal = new Map<string, string>();\n for (const original of coinTypes) {\n const long = normalizeCoinType(original);\n if (!longToOriginal.has(long)) longToOriginal.set(long, original);\n }\n const longForms = Array.from(longToOriginal.keys());\n\n for (let i = 0; i < longForms.length; i += PRICE_LIST_CHUNK) {\n const chunk = longForms.slice(i, i + PRICE_LIST_CHUNK);\n const tokenIds = encodeURIComponent(chunk.join(','));\n const url = `${BLOCKVISION_BASE}/coin/price/list?tokenIds=${tokenIds}&show24hChange=true`;\n const signal = AbortSignal.timeout(PRICES_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchBlockVisionWithRetry(\n url,\n {\n headers: { 'x-api-key': apiKey, accept: 'application/json' },\n signal,\n },\n { signal, retryStats },\n );\n } catch (err) {\n console.warn('[blockvision-prices] price chunk threw, skipping:', err);\n continue;\n }\n\n if (!res.ok) {\n console.warn(`[blockvision-prices] price chunk HTTP ${res.status}`);\n continue;\n }\n\n let json: BlockVisionPriceListResponse;\n try {\n json = (await res.json()) as BlockVisionPriceListResponse;\n } catch (err) {\n console.warn('[blockvision-prices] price chunk JSON parse failed:', err);\n continue;\n }\n if (json.code !== 200 || !json.result) continue;\n const prices = json.result.prices ?? {};\n const changes = json.result.coin24HChange ?? {};\n for (const [returnedType, priceStr] of Object.entries(prices)) {\n const price = parseNumberOrNull(priceStr);\n if (price == null) continue;\n // BlockVision echoes whatever long form we sent. Map back to the\n // caller's input string, falling through to the returned key for\n // safety if BlockVision ever normalizes differently than we do.\n const original = longToOriginal.get(returnedType) ?? returnedType;\n const change24h = parseNumberOrNull(changes[returnedType]);\n out[original] = change24h == null ? { price } : { price, change24h };\n }\n }\n return out;\n}\n\nfunction parseNumberOrNull(input: unknown): number | null {\n if (typeof input === 'number') return Number.isFinite(input) ? input : null;\n if (typeof input !== 'string' || input.trim().length === 0) return null;\n const n = Number(input);\n return Number.isFinite(n) ? n : null;\n}\n\n// ---------------------------------------------------------------------------\n// [v0.50.2] DeFi portfolio aggregation\n//\n// `balance_check` historically returned only wallet coins + NAVI savings,\n// missing DeFi positions across the rest of Sui DeFi — for active users\n// this can be a meaningful fraction of net worth.\n//\n// v0.50 introduced parallel fan-out across BlockVision's\n// `/account/defiPortfolio` endpoint (excluding NAVI, which is already\n// covered by `positionFetcher` / NAVI MCP). v0.50.1 expanded to all 26\n// supported protocols, but 26 simultaneous BV calls + the wallet\n// `/account/coins` call hit BlockVision's per-second burst cap, so the\n// wallet endpoint occasionally 429'd and silently degraded to Sui RPC\n// (which only prices stables, leaving non-stables at $0). v0.50.2 walks\n// it back to 9 protocols — the original 6 majors plus the 3 native-token\n// stakings users were missing — keeping the burst at 10 parallel calls\n// (1 wallet + 9 DeFi). Adding a future protocol is a 1-line append in\n// `DEFI_PROTOCOLS` below.\n//\n// Two-pass design:\n//\n// 1. Generic shape walker — recursively walks the response tree,\n// extracting paired-LP shapes (coinTypeA/B + balance, with X/Y and\n// tokenX/Y aliases) and single-coin shapes (coinType +\n// balance/amount/value), automatically handling Scallop's pre-USD\n// totals, NAVI's `type: 'Supply'|'Borrow'` flag, and parent-key debt\n// detection (`borrows`, `debt`, `borrowings` → subtract). Skips\n// `rewards` / `fees` / `pendingRewards` branches to avoid double-\n// counting incentives.\n//\n// 2. Bespoke shims for shapes the walker can't infer (implied coin types):\n// - bluefin: usdcVault/blueVault expose `{amount}` with implied coin type\n// - haedal: stakings expose `{sui_amount}` with implied SUI\n// - suistake / walrus / suins-staking: stakings of an implied native\n// token (SUI / WAL / NS); walker can't guess the coin type from\n// a bare `{amount}` field\n//\n// Pricing: callers pass a `priceHints` map (typically derived from the\n// wallet portfolio's coin prices). Coin types that appear in DeFi\n// positions but not in the wallet (e.g. one half of an LP that the user\n// doesn't otherwise hold) are looked up via a single batched\n// `fetchTokenPrices` call. STABLE_USD_PRICES short-circuits stables.\n//\n// Failure isolation: a 5xx for one protocol drops just that protocol. The\n// `source` field on the result surfaces 'partial' when any protocol failed.\n//\n// Concurrency: 9 parallel BV calls per balance_check + 1 wallet coins\n// call = 10 simultaneous, comfortably below BV Pro-tier burst caps.\n// Cache TTL 60s dedupes repeated balance_check calls for the same address\n// inside a chat session.\n// ---------------------------------------------------------------------------\n\nconst DEFI_PORTFOLIO_TIMEOUT_MS = 4_000;\n\n/**\n * Source-aware freshness thresholds. When a cache hit has age <\n * threshold, the fetcher serves it directly without re-attempting\n * BlockVision. When age >= threshold but < `STICKY_TTL_SEC`, the entry\n * is kept around as a sticky-positive fallback (see fetcher logic).\n */\nconst DEFI_FRESH_TTL_MS_BLOCKVISION = 60_000; // 60s — fully successful\nconst DEFI_FRESH_TTL_MS_PARTIAL = 15_000; // 15s — at least one protocol failed; retry sooner\nconst DEFI_FRESH_TTL_MS_PARTIAL_STALE = 0; // 0s — always re-fetch in background\n\n/**\n * [v0.54] Sticky-positive window: entries persist in the cache store\n * for this long even after their fresh-TTL has elapsed, so a brief\n * BlockVision burst that would otherwise return `partial+0` or\n * `degraded` can fall back to the last-known-good positive value\n * (marked `partial-stale` so consumers can render an honest \"last\n * refresh Nm ago\" caveat). 30 minutes is long enough to absorb a\n * sustained BV outage without serving wildly stale data; users hold\n * positions on the order of hours/days, so a 30-minute lag rarely\n * misleads. Tunable per-deployment via the cache store TTL.\n */\nconst DEFI_STICKY_TTL_SEC = 30 * 60;\n\n// [v0.50.2] 9 protocols — the v0.50 majors (Cetus/Suilend/Scallop/Bluefin/\n// Aftermath/Haedal) plus three native-token stakings (Suistake/SuiNS-staking/\n// Walrus). v0.50.1 expanded to all 26 BlockVision protocols, but the resulting\n// 26-call burst caused the wallet `/account/coins` endpoint to occasionally\n// 429, falling back to Sui-RPC degraded mode where non-stables are unpriced\n// — so wallet display showed $0 for users with MANIFEST/FAITH/etc. holdings.\n// 9 protocols = 9+1 burst per balance_check, comfortably below BV burst\n// caps. Walker + bespoke shims stay as-is — adding a future protocol is a\n// 1-line append here. Deliberately excludes NAVI (already covered by\n// `savings_info` via positionFetcher / NAVI MCP — including would\n// double-count savings).\nconst DEFI_PROTOCOLS = [\n 'aftermath',\n 'bluefin',\n 'cetus',\n 'haedal',\n 'scallop',\n 'suilend',\n 'suins-staking',\n 'suistake',\n 'walrus',\n] as const;\nexport type DefiProtocol = (typeof DEFI_PROTOCOLS)[number];\n\n// Implied coin types for protocols whose response shape buries the coin\n// identity in the protocol's own conventions (no `coinType` field).\nconst SUI_TYPE_FULL =\n '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI';\nconst USDC_TYPE_FULL =\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC';\nconst BLUE_TYPE_FULL =\n '0xe1b45a0e641b9955a20aa0ad1c1f4ad86aad8afb07296d4085e349a50e90bdca::blue::BLUE';\nconst WAL_TYPE_FULL =\n '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL';\nconst NS_TYPE_FULL =\n '0x5145494a5f5100e645e4b0aa950fa6b68f614e8c59e17bc5ded3495123a79178::ns::NS';\n\nexport interface DefiSummary {\n /** Net USD value of all aggregated DeFi positions (supply + collateral - debt). */\n totalUsd: number;\n /** Per-protocol breakdown for cards / debugging. Only protocols with non-zero value are present. */\n perProtocol: Partial<Record<DefiProtocol, number>>;\n pricedAt: number;\n /**\n * `blockvision` — every protocol in `DEFI_PROTOCOLS` responded successfully.\n * `partial` — at least one protocol failed; total may under-count.\n * `partial-stale` — fresh fetch returned degraded/partial-zero, but we have a\n * positive value cached within the sticky window\n * (`DEFI_STICKY_TTL_SEC`, default 30min). The numbers are\n * real, just not freshly verified — UI should caveat with\n * \"last refresh Nm ago\" so the user knows the provenance.\n * Introduced in v0.54 to fix cross-instance SSOT divergence\n * when BlockVision is bursting.\n * `degraded` — no API key, or every protocol failed AND no sticky\n * fallback exists; total = 0.\n */\n source: 'blockvision' | 'partial' | 'partial-stale' | 'degraded';\n}\n\n// Process-local inflight dedup. Even with a shared cache store (Redis),\n// we still want to coalesce 9 BlockVision calls when N concurrent\n// callers in the same process miss the cache simultaneously — one\n// fetch fans out, all callers await the same promise. The store\n// handles cross-process dedup via TTL (last writer wins, but the\n// sticky-positive write rules below ensure the wrong winner can't\n// poison cached known-good data).\nconst defiInflight = new Map<string, Promise<DefiSummary>>();\n\n/** Source-aware fresh-TTL lookup. See constants block above for rationale. */\nfunction freshTtlForSource(source: DefiSummary['source']): number {\n switch (source) {\n case 'blockvision':\n return DEFI_FRESH_TTL_MS_BLOCKVISION;\n case 'partial':\n return DEFI_FRESH_TTL_MS_PARTIAL;\n case 'partial-stale':\n return DEFI_FRESH_TTL_MS_PARTIAL_STALE;\n case 'degraded':\n return 0;\n }\n}\n\n/**\n * Store-write helper that swallows backend errors. A Redis hiccup\n * during write should never break a successful read — the next caller\n * will simply re-fetch on cache miss. Errors are logged so an outage\n * is still observable in Vercel logs.\n */\nasync function safeStoreSet(\n store: DefiCacheStore,\n address: string,\n entry: DefiCacheEntry,\n): Promise<void> {\n try {\n await store.set(address, entry, DEFI_STICKY_TTL_SEC);\n } catch (err) {\n console.warn('[defi] cache set failed (non-fatal):', err);\n }\n}\n\n/**\n * Read the DeFi store, swallowing transport errors as cache misses.\n * Used by both the leader (pre-fanout + post-lock recheck) and the\n * follower (poll loop). Mirrors `safeWalletStoreGet`.\n */\nasync function safeDefiStoreGet(\n store: DefiCacheStore,\n address: string,\n): Promise<DefiCacheEntry | null> {\n try {\n return await store.get(address);\n } catch (err) {\n console.warn('[defi] cache get failed (continuing as cache miss):', err);\n return null;\n }\n}\n\n// Warn-once gate so we don't spam logs every time `balance_check` runs in a\n// misconfigured environment. The first request that hits the missing-key\n// guard logs a loud, scannable warning; subsequent requests stay quiet.\n// Reset on process restart, which is fine — the next deploy logs again\n// until the operator sets the key.\n//\n// Defense-in-depth note: the audric web app gates the empty-key class of\n// bug at server boot via `apps/web/lib/env.ts`. This warn-and-degrade\n// path remains because the engine package is also consumed by the CLI,\n// MCP server, and other hosts that may not have the same gate, AND the\n// SDK form of `balance_check` accepts the apiKey as a runtime parameter\n// — degrading visibly is the right behavior when a caller passes blank.\nlet warnedMissingApiKey = false;\n\ninterface BlockVisionDefiResponse {\n code: number;\n message: string;\n result?: Record<string, unknown>;\n}\n\nexport async function fetchAddressDefiPortfolio(\n address: string,\n apiKey: string | undefined,\n priceHints: Record<string, number> = {},\n // [SPEC 8 v0.5.1 B3.2] See `fetchAddressPortfolio` for the retry-stats\n // contract.\n opts: { retryStats?: { attemptCount: number } } = {},\n): Promise<DefiSummary> {\n if (!apiKey || apiKey.trim().length === 0) {\n if (!warnedMissingApiKey) {\n warnedMissingApiKey = true;\n // Loud, single-line warning so it's grep-able in log explorers.\n // BLOCKVISION_API_KEY missing OR empty string (\"\") — both produce\n // identical silent-zero behavior, which the v0.50 fix-it pass after\n // the audric-roadmap S.18 work surfaced as a class of bug\n // (env var present in Vercel but blank → degraded forever).\n console.warn(\n '[defi] BLOCKVISION_API_KEY missing or empty — DeFi positions will report $0 across all protocols. Set the key in your runtime env to enable Bluefin/Suilend/Cetus/etc. aggregation.',\n );\n }\n return { totalUsd: 0, perProtocol: {}, pricedAt: Date.now(), source: 'degraded' };\n }\n\n const store = getDefiCacheStore();\n\n // ---------------------------------------------------------------\n // Read path — source-aware freshness\n //\n // `cachedEntry` may be present but past its source-specific\n // freshness threshold. In that case we fall through to a fresh\n // fetch but keep the entry in scope as a sticky-positive fallback\n // (see write rules below). Store-level errors are swallowed; we\n // log and continue as if the cache were empty so a Redis hiccup\n // never breaks `balance_check`.\n // ---------------------------------------------------------------\n const cachedEntry = await safeDefiStoreGet(store, address);\n if (cachedEntry) {\n const ageMs = Date.now() - cachedEntry.pricedAt;\n const freshTtlMs = freshTtlForSource(cachedEntry.data.source);\n if (ageMs < freshTtlMs) {\n // Fresh hit — serve directly without re-fetching.\n getTelemetrySink().counter('bv.cache_hit', { kind: 'defi', freshness: 'fresh' });\n return cachedEntry.data;\n }\n // Stale hit kept in scope for the sticky-positive fallback below.\n getTelemetrySink().counter('bv.cache_hit', { kind: 'defi', freshness: 'stale-served' });\n } else {\n getTelemetrySink().counter('bv.cache_hit', { kind: 'defi', freshness: 'miss' });\n }\n\n let inflight = defiInflight.get(address);\n if (inflight) return inflight;\n\n // ---------------------------------------------------------------\n // [PR 2 — v0.55] Cross-instance coalescer wraps the WHOLE 9-protocol\n // fan-out as a single unit. Lock key is `bv-lock:defi:<addr>` —\n // distinct from the wallet lock so they don't block each other.\n //\n // IMPORTANT: the lock sits at the fan-out level, NOT around each\n // individual `fetchOneDefiProtocol` call. Per-protocol locking would\n // cause the 9 sibling protocols to compete for the same lock — one\n // would win and 8 would poll-then-refetch, completely defeating\n // coalescing.\n // ---------------------------------------------------------------\n inflight = (async () => {\n try {\n return await awaitOrFetch<DefiSummary>(\n DEFI_LOCK_KEY(address),\n // Leader path — runs after acquiring the lock.\n async () => {\n // Re-check the cache after acquiring the lock — a leader on\n // another process may have written between our pre-lock\n // miss and our lock acquisition.\n const recheck = await safeDefiStoreGet(store, address);\n if (recheck) {\n const ageMs = Date.now() - recheck.pricedAt;\n if (ageMs < freshTtlForSource(recheck.data.source)) {\n return recheck.data;\n }\n }\n // Use the freshest sticky basis we have for the write rules\n // below. Prefer `recheck` over the pre-lock `cachedEntry`\n // (covers the case where a previous leader's write expired\n // since our pre-lock read).\n const stickyBasis: DefiCacheEntry | null = recheck ?? cachedEntry;\n const fanoutAt = Date.now();\n\n const settled = await Promise.allSettled(\n DEFI_PROTOCOLS.map((p) => fetchOneDefiProtocol(address, p, apiKey, opts.retryStats)),\n );\n\n // Pass 1 — discover every coin type referenced across all protocol\n // responses, then fill any missing prices in a single batched call.\n const seen = new Set<string>();\n for (const s of settled) {\n if (s.status === 'fulfilled' && s.value) collectCoinTypes(s.value, seen);\n }\n const normalizedHints: Record<string, number> = {};\n for (const [k, v] of Object.entries(priceHints)) {\n normalizedHints[normalizeCoinType(k)] = v;\n }\n const missing = Array.from(seen).filter((ct) => {\n const norm = normalizeCoinType(ct);\n return !normalizedHints[norm] && !STABLE_USD_PRICES[norm];\n });\n let fetchedPrices: Record<string, { price: number }> = {};\n if (missing.length > 0) {\n try {\n fetchedPrices = await fetchTokenPrices(missing, apiKey);\n } catch (err) {\n console.warn('[defi] fill-missing-prices failed:', err);\n }\n }\n\n const prices: Record<string, number> = { ...normalizedHints };\n for (const [ct, v] of Object.entries(fetchedPrices)) {\n prices[normalizeCoinType(ct)] ??= v.price;\n }\n for (const [ct, p] of Object.entries(STABLE_USD_PRICES)) {\n prices[normalizeCoinType(ct)] ??= p;\n }\n\n // Pass 2 — run the per-protocol normaliser. Bespoke handlers cover\n // the protocols the walker can't infer (implied coin types, nested\n // phantomType); everything else falls through to the generic walker.\n let totalUsd = 0;\n let failures = 0;\n const perProtocol: Partial<Record<DefiProtocol, number>> = {};\n\n for (let i = 0; i < DEFI_PROTOCOLS.length; i++) {\n const proto = DEFI_PROTOCOLS[i];\n const s = settled[i];\n if (s.status !== 'fulfilled' || !s.value) {\n failures++;\n continue;\n }\n try {\n const usd = normalizeProtocol(proto, s.value, prices);\n if (Number.isFinite(usd) && usd !== 0) {\n perProtocol[proto] = usd;\n totalUsd += usd;\n }\n } catch (err) {\n console.warn(`[defi] ${proto} normaliser threw:`, err);\n failures++;\n }\n }\n\n // Floor under-zero rollups to 0 — net negative would mean borrows >\n // supplies on a *DeFi-only* basis, which is implausible without\n // collateral counted; safer to surface 0 than a misleading negative.\n if (totalUsd < 0) totalUsd = 0;\n\n const fetchedAt = Date.now();\n const summary: DefiSummary = {\n totalUsd,\n perProtocol,\n pricedAt: fetchedAt,\n source:\n failures === DEFI_PROTOCOLS.length\n ? 'degraded'\n : failures > 0\n ? 'partial'\n : 'blockvision',\n };\n\n // -------------------------------------------------------------\n // Sticky-positive write rules (v0.54 — see header for the\n // four-state truth table). `stickyBasis` was captured inside\n // the lock above so it reflects the freshest known state at\n // leader-entry time (not the pre-lock observation, which may\n // have raced a deleting writer).\n // -------------------------------------------------------------\n const cachedPositive =\n stickyBasis &&\n stickyBasis.data.totalUsd > 0 &&\n fanoutAt - stickyBasis.pricedAt < DEFI_STICKY_TTL_SEC * 1000;\n\n if (summary.source === 'blockvision') {\n // Fully successful — overwrites unconditionally.\n await safeStoreSet(store, address, { data: summary, pricedAt: fetchedAt });\n return summary;\n }\n\n if (summary.source === 'partial' && summary.totalUsd > 0) {\n // Observed real value despite a failure — write but with a\n // short fresh-TTL so the next reader retries the failing\n // protocols within 15s.\n await safeStoreSet(store, address, { data: summary, pricedAt: fetchedAt });\n return summary;\n }\n\n // partial+0 OR degraded — fall back to the sticky cache if we\n // have a positive entry that's fresher than 30 minutes.\n if (cachedPositive) {\n const stale: DefiSummary = {\n ...stickyBasis!.data,\n source: 'partial-stale',\n };\n // Don't write — preserve the original `pricedAt` so the UI\n // can render an honest \"last refresh Nm ago\" caveat.\n // Re-writing would reset the age and hide the staleness.\n return stale;\n }\n\n // No fallback available — return as-is, don't cache so the\n // next caller retries BlockVision.\n return summary;\n },\n {\n // Followers poll the DeFi cache while the leader fans out.\n // Returns non-null only when the leader has written a\n // fresh-for-source entry — stale entries keep the poll going.\n pollCache: async () => {\n const e = await safeDefiStoreGet(store, address);\n if (!e) return null;\n const ageMs = Date.now() - e.pricedAt;\n return ageMs < freshTtlForSource(e.data.source) ? e.data : null;\n },\n },\n );\n } finally {\n defiInflight.delete(address);\n }\n })();\n\n defiInflight.set(address, inflight);\n return inflight;\n}\n\nasync function fetchOneDefiProtocol(\n address: string,\n protocol: DefiProtocol,\n apiKey: string,\n retryStats?: { attemptCount: number },\n): Promise<Record<string, unknown> | null> {\n const url = `${BLOCKVISION_BASE}/account/defiPortfolio?address=${encodeURIComponent(address)}&protocol=${protocol}`;\n const signal = AbortSignal.timeout(DEFI_PORTFOLIO_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchBlockVisionWithRetry(\n url,\n {\n headers: { 'x-api-key': apiKey, accept: 'application/json' },\n signal,\n },\n { signal, retryStats },\n );\n } catch (err) {\n console.warn(`[defi] ${protocol} fetch threw:`, err);\n return null;\n }\n if (!res.ok) {\n console.warn(`[defi] ${protocol} HTTP ${res.status}`);\n return null;\n }\n let json: BlockVisionDefiResponse;\n try {\n json = (await res.json()) as BlockVisionDefiResponse;\n } catch (err) {\n console.warn(`[defi] ${protocol} JSON parse failed:`, err);\n return null;\n }\n if (json.code !== 200 || !json.result) return null;\n return json.result;\n}\n\n// ---------------------------------------------------------------------------\n// Shape extraction — generic walker\n//\n// Recursively walks a protocol's response and sums net USD value, handling\n// the common shape patterns BlockVision returns:\n//\n// - Paired LPs: {coinTypeA, coinTypeB, balanceA, balanceB} with X/Y and\n// tokenX/Y aliases (Cetus/Bluefin/Haedal/Steamm/Turbos/Magma/Ferra/\n// FlowX/Kriya/Momentum/BlueMove); decimals can be at sibling\n// (coinTypeADecimals, decimalsA) or nested (coinA.decimals).\n// - Single-coin: {coinType, amount/balance/value, decimals?} with\n// `type: 'Borrow'` flag for NAVI-style flat lists.\n// - Pre-USD totals: Scallop's totalSupplyValue / totalDebtValue /\n// totalCollateralValue / totalLockedScaValue at root.\n//\n// Debt detection happens in two ways: the parent key (`borrows`, `debt`,\n// `borrowings` → flips debtSide for the entire subtree) OR the item's own\n// `type` field set to `'Borrow'` (NAVI flat list).\n//\n// Reward / fee branches (`rewards`, `fees`, `pendingRewards`, etc.) are\n// skipped entirely — those amounts are typically already implicit in the\n// position's principal value, and double-counting them inflates net worth.\n// Power users rarely have unclaimed-reward stacks worth >1% of their LP.\n// ---------------------------------------------------------------------------\n\nconst PAIR_A_COIN_KEYS = ['coinTypeA', 'coinTypeX', 'tokenXType'] as const;\nconst PAIR_B_COIN_KEYS = ['coinTypeB', 'coinTypeY', 'tokenYType'] as const;\nconst PAIR_A_AMOUNT_KEYS = [\n 'balanceA',\n 'amountA',\n 'coinAmountA',\n 'coinAAmount',\n 'coinTypeAAmount',\n 'tokenXBalance',\n 'tokenXAmount',\n 'amountX',\n 'valueA',\n] as const;\nconst PAIR_B_AMOUNT_KEYS = [\n 'balanceB',\n 'amountB',\n 'coinAmountB',\n 'coinBAmount',\n 'coinTypeBAmount',\n 'tokenYBalance',\n 'tokenYAmount',\n 'amountY',\n 'valueB',\n] as const;\nconst PAIR_A_DECIMALS_KEYS = ['coinTypeADecimals', 'tokenXDecimals', 'decimalsA'] as const;\nconst PAIR_B_DECIMALS_KEYS = ['coinTypeBDecimals', 'tokenYDecimals', 'decimalsB'] as const;\n\nconst SINGLE_COIN_KEYS = ['coinType', 'depositToken', 'token'] as const;\nconst SINGLE_AMOUNT_KEYS = ['amount', 'balance', 'value', 'equity'] as const;\nconst SINGLE_DECIMALS_KEYS = ['decimals', 'decimal', 'coinDecimals'] as const;\n\nconst DEBT_KEYS = new Set([\n 'borrow',\n 'borrows',\n 'debt',\n 'debts',\n 'borrowings',\n 'borrowedpools',\n]);\n// Skip reward/fee/incentive subtrees so we don't double-count pending yield\n// already implied by the position principal value.\nconst SKIP_KEYS = new Set([\n 'rewards',\n 'reward',\n 'fees',\n 'fee',\n 'pendingrewards',\n 'incentiveinfos',\n 'feereward',\n 'incentivereward',\n]);\n\nfunction isCoinTypeString(v: unknown): v is string {\n if (typeof v !== 'string' || !v.includes('::')) return false;\n // Accept both `0x…::module::TYPE` and unprefixed `…::module::TYPE`\n // (Typus's `depositToken` / `rewardsToken` omit the leading `0x`).\n return v.startsWith('0x') || /^[0-9a-fA-F]/.test(v);\n}\n\nfunction ensure0xPrefix(coinType: string): string {\n return coinType.startsWith('0x') ? coinType : '0x' + coinType;\n}\n\nfunction isAmountValue(v: unknown): v is string | number {\n return (\n (typeof v === 'string' && v.trim().length > 0) ||\n (typeof v === 'number' && Number.isFinite(v))\n );\n}\n\nfunction isFiniteNumber(v: unknown): v is number {\n return typeof v === 'number' && Number.isFinite(v);\n}\n\nfunction pickField<T>(\n obj: Record<string, unknown>,\n keys: readonly string[],\n predicate: (v: unknown) => v is T,\n): T | undefined {\n for (const k of keys) {\n const v = obj[k];\n if (predicate(v)) return v;\n }\n return undefined;\n}\n\nfunction nestedDecimals(node: unknown): number | undefined {\n if (!node || typeof node !== 'object') return undefined;\n const obj = node as Record<string, unknown>;\n if (typeof obj.decimals === 'number') return obj.decimals;\n return undefined;\n}\n\n/**\n * Convert a BlockVision amount field to a human-readable token quantity.\n * BlockVision is inconsistent across protocols:\n * - integer string (\"229380000000\") or integer number (1485) → raw,\n * divide by 10^decimals\n * - decimal-string (\"4.240927787\") or non-integer JS number (4.24) →\n * already human-readable, return as-is\n */\nfunction toHumanQuantity(raw: string | number, decimalsHint: number | undefined): number {\n if (typeof raw === 'number') {\n if (!Number.isFinite(raw)) return 0;\n if (!Number.isInteger(raw)) return raw;\n if (decimalsHint != null) return raw / 10 ** decimalsHint;\n return raw;\n }\n const trimmed = raw.trim();\n if (trimmed.length === 0) return 0;\n if (trimmed.includes('.') || trimmed.includes('e') || trimmed.includes('E')) {\n const n = Number(trimmed);\n return Number.isFinite(n) ? n : 0;\n }\n const n = Number(trimmed);\n if (!Number.isFinite(n)) return 0;\n const dec = decimalsHint ?? 9;\n return n / 10 ** dec;\n}\n\nfunction priceFor(coinType: string, prices: Record<string, number>): number {\n const prefixed = ensure0xPrefix(coinType);\n const norm = normalizeCoinType(prefixed);\n return prices[norm] ?? prices[prefixed] ?? prices[coinType] ?? STABLE_USD_PRICES[norm] ?? 0;\n}\n\nfunction toUsd(\n coinType: string,\n raw: unknown,\n decimalsHint: number | undefined,\n prices: Record<string, number>,\n): number {\n if (raw == null || (typeof raw !== 'string' && typeof raw !== 'number')) return 0;\n if (typeof raw === 'string' && raw.trim().length === 0) return 0;\n const prefixed = ensure0xPrefix(coinType);\n const decimals =\n typeof decimalsHint === 'number' ? decimalsHint : getDecimalsForCoinType(prefixed);\n const human = toHumanQuantity(raw, decimals);\n if (!Number.isFinite(human)) return 0;\n return human * priceFor(prefixed, prices);\n}\n\ninterface ExtractedPair {\n coinTypeA: string;\n amountA: string | number;\n decimalsA: number | undefined;\n coinTypeB: string;\n amountB: string | number;\n decimalsB: number | undefined;\n}\n\nfunction extractPair(obj: Record<string, unknown>): ExtractedPair | null {\n const coinTypeA = pickField(obj, PAIR_A_COIN_KEYS, isCoinTypeString);\n const coinTypeB = pickField(obj, PAIR_B_COIN_KEYS, isCoinTypeString);\n if (!coinTypeA || !coinTypeB) return null;\n const amountA = pickField(obj, PAIR_A_AMOUNT_KEYS, isAmountValue);\n const amountB = pickField(obj, PAIR_B_AMOUNT_KEYS, isAmountValue);\n if (amountA == null || amountB == null) return null;\n const decimalsA =\n pickField(obj, PAIR_A_DECIMALS_KEYS, isFiniteNumber) ??\n nestedDecimals(obj.coinA);\n const decimalsB =\n pickField(obj, PAIR_B_DECIMALS_KEYS, isFiniteNumber) ??\n nestedDecimals(obj.coinB);\n return { coinTypeA, amountA, decimalsA, coinTypeB, amountB, decimalsB };\n}\n\ninterface ExtractedSingle {\n coinType: string;\n amount: string | number;\n decimals: number | undefined;\n isBorrow: boolean;\n}\n\nfunction extractSingle(obj: Record<string, unknown>): ExtractedSingle | null {\n const coinType = pickField(obj, SINGLE_COIN_KEYS, isCoinTypeString);\n if (!coinType) return null;\n const amount = pickField(obj, SINGLE_AMOUNT_KEYS, isAmountValue);\n if (amount == null) return null;\n const decimals = pickField(obj, SINGLE_DECIMALS_KEYS, isFiniteNumber);\n const isBorrow = obj.type === 'Borrow';\n return { coinType, amount, decimals, isBorrow };\n}\n\nfunction walkProtocolResponse(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n let total = 0;\n walk(result, false);\n return total;\n\n function walk(node: unknown, debtSide: boolean): void {\n if (!node || typeof node !== 'object') return;\n if (Array.isArray(node)) {\n for (const item of node) walk(item, debtSide);\n return;\n }\n const obj = node as Record<string, unknown>;\n\n // Scallop pre-USD totals (root-level only, but cheap to check anywhere).\n if (typeof obj.totalSupplyValue === 'number') total += obj.totalSupplyValue;\n if (typeof obj.totalCollateralValue === 'number') total += obj.totalCollateralValue;\n if (typeof obj.totalLockedScaValue === 'number') total += obj.totalLockedScaValue;\n if (typeof obj.totalDebtValue === 'number') total -= obj.totalDebtValue;\n\n const pair = extractPair(obj);\n if (pair) {\n const a = toUsd(pair.coinTypeA, pair.amountA, pair.decimalsA, prices);\n const b = toUsd(pair.coinTypeB, pair.amountB, pair.decimalsB, prices);\n total += debtSide ? -(a + b) : a + b;\n } else {\n const single = extractSingle(obj);\n if (single) {\n const usd = toUsd(single.coinType, single.amount, single.decimals, prices);\n total += debtSide || single.isBorrow ? -usd : usd;\n }\n }\n\n for (const [k, v] of Object.entries(obj)) {\n const lk = k.toLowerCase();\n if (SKIP_KEYS.has(lk)) continue;\n const childDebt = debtSide || DEBT_KEYS.has(lk);\n walk(v, childDebt);\n }\n }\n}\n\n/**\n * Walks the response object recursively and collects every string value at\n * any key that looks like a Sui coin-type field. Used to discover which\n * token prices we still need to fetch before normalisers run. Coin types\n * may be returned without the `0x` prefix (Typus); we normalize before\n * adding so the price-cache key matches subsequent lookups.\n */\nfunction collectCoinTypes(obj: unknown, out: Set<string>): void {\n if (!obj || typeof obj !== 'object') return;\n if (Array.isArray(obj)) {\n for (const x of obj) collectCoinTypes(x, out);\n return;\n }\n for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n if (typeof v === 'string' && isCoinTypeString(v)) {\n const lk = k.toLowerCase();\n if (\n lk.includes('cointype') ||\n lk === 'tokenxtype' ||\n lk === 'tokenytype' ||\n lk === 'deposittoken' ||\n lk === 'rewardstoken' ||\n lk === 'token' ||\n lk === 'coinaddress' ||\n lk === 'phantomtype' ||\n lk === 'typename'\n ) {\n out.add(ensure0xPrefix(v));\n }\n } else if (typeof v === 'object' && v !== null) {\n collectCoinTypes(v, out);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Bespoke handlers — protocols whose shape the generic walker can't infer\n// (implied coin types or non-standard amount/decimals nesting).\n// ---------------------------------------------------------------------------\n\ninterface BluefinLp {\n coinTypeA?: string;\n coinTypeB?: string;\n coinAmountA?: number | string;\n coinAmountB?: number | string;\n}\n\nfunction normalizeBluefin(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data =\n (result.bluefin as {\n lps?: BluefinLp[];\n usdcVault?: { amount?: number | string };\n blueVault?: { amount?: number | string };\n }) ?? {};\n let total = 0;\n for (const lp of data.lps ?? []) {\n if (lp.coinTypeA && lp.coinAmountA != null) {\n total += toUsd(lp.coinTypeA, lp.coinAmountA, undefined, prices);\n }\n if (lp.coinTypeB && lp.coinAmountB != null) {\n total += toUsd(lp.coinTypeB, lp.coinAmountB, undefined, prices);\n }\n }\n // Vaults expose a raw `amount` without a coinType — usdcVault implies USDC\n // (6dp) and blueVault implies BLUE (9dp) per the BlockVision schema.\n if (data.usdcVault?.amount != null) {\n total += toUsd(USDC_TYPE_FULL, data.usdcVault.amount, 6, prices);\n }\n if (data.blueVault?.amount != null) {\n total += toUsd(BLUE_TYPE_FULL, data.blueVault.amount, 9, prices);\n }\n return total;\n}\n\nfunction normalizeHaedal(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data =\n (result.haedal as {\n lps?: Array<{\n coinTypeA?: string;\n coinTypeB?: string;\n balanceA?: number | string;\n balanceB?: number | string;\n }>;\n stakings?: Array<{ sui_amount?: number | string }>;\n }) ?? {};\n let total = 0;\n for (const lp of data.lps ?? []) {\n if (lp.coinTypeA && lp.balanceA != null) {\n total += toUsd(lp.coinTypeA, lp.balanceA, undefined, prices);\n }\n if (lp.coinTypeB && lp.balanceB != null) {\n total += toUsd(lp.coinTypeB, lp.balanceB, undefined, prices);\n }\n }\n for (const stake of data.stakings ?? []) {\n if (stake.sui_amount != null) {\n total += toUsd(SUI_TYPE_FULL, stake.sui_amount, 9, prices);\n }\n }\n return total;\n}\n\ninterface BareStaking {\n amount?: number | string;\n sui_amount?: number | string;\n}\n\nfunction sumBareStakings(\n data: { stakings?: BareStaking[] } | undefined,\n impliedCoinType: string,\n decimals: number,\n prices: Record<string, number>,\n): number {\n if (!data) return 0;\n let total = 0;\n for (const s of data.stakings ?? []) {\n const amt = s.sui_amount ?? s.amount;\n if (amt != null) total += toUsd(impliedCoinType, amt, decimals, prices);\n }\n return total;\n}\n\nfunction normalizeSuistake(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data = result.suistake as { stakings?: BareStaking[] } | undefined;\n return sumBareStakings(data, SUI_TYPE_FULL, 9, prices);\n}\n\nfunction normalizeWalrus(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data = result.walrus as { stakings?: BareStaking[] } | undefined;\n return sumBareStakings(data, WAL_TYPE_FULL, 9, prices);\n}\n\nfunction normalizeSuinsStaking(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n // BlockVision may expose this under either `suins-staking`, `suinsStaking`,\n // or `suins_staking` — probe all three since the doc uses the kebab form\n // for the protocol param but JS conventions tend to camelCase response keys.\n const data =\n (result['suins-staking'] as { stakings?: BareStaking[] } | undefined) ??\n (result.suinsStaking as { stakings?: BareStaking[] } | undefined) ??\n (result.suins_staking as { stakings?: BareStaking[] } | undefined);\n return sumBareStakings(data, NS_TYPE_FULL, 6, prices);\n}\n\nconst BESPOKE_NORMALIZERS: Partial<\n Record<DefiProtocol, (result: Record<string, unknown>, prices: Record<string, number>) => number>\n> = {\n bluefin: normalizeBluefin,\n haedal: normalizeHaedal,\n suistake: normalizeSuistake,\n walrus: normalizeWalrus,\n 'suins-staking': normalizeSuinsStaking,\n};\n\nfunction normalizeProtocol(\n protocol: DefiProtocol,\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const bespoke = BESPOKE_NORMALIZERS[protocol];\n if (bespoke) return bespoke(result, prices);\n return walkProtocolResponse(result, prices);\n}\n\nexport async function clearDefiCache(): Promise<void> {\n // Clears both the active store (Redis or in-memory) and any\n // in-flight promises. Async because store.clear() may need to\n // round-trip to Redis. Existing callers (tests, post-write refresh)\n // were sync and didn't await — we keep the promise return so new\n // callers can await but legacy fire-and-forget still works.\n await getDefiCacheStore().clear();\n defiInflight.clear();\n}\n\nexport async function clearDefiCacheFor(address: string): Promise<void> {\n await getDefiCacheStore().delete(address);\n defiInflight.delete(address);\n}\n\n/**\n * Wipe the wallet portfolio cache plus any in-flight promises.\n *\n * Async because the underlying store may be Redis-backed. Existing\n * fire-and-forget callers (tests, `clearDefiCache`-shape utilities)\n * still work since they just don't `await` — they get the same\n * effective \"schedule the clear\" behavior.\n */\nexport async function clearPortfolioCache(): Promise<void> {\n await getWalletCacheStore().clear();\n portfolioInflight.clear();\n}\n\n/**\n * [v1.4 — Day 2.5] Per-address invalidator.\n *\n * Engine `runPostWriteRefresh` calls this right before the 1.5s\n * Sui-RPC-indexer-lag delay so the next `fetchAddressPortfolio` for\n * the affected address is forced to hit BlockVision again instead of\n * returning the cached pre-write snapshot.\n *\n * **MUST be awaited** — pre-PR-1 the cache was a synchronous Map and\n * the `engine.ts` caller fired-and-forgot. Now the underlying store\n * is async (Upstash in production), so without `await` the next\n * `balance_check` races the Redis delete and can fetch the stale\n * pre-write balance — exactly the symptom v0.54 sticky cache shipped\n * to fix. `engine.ts` `runPostWriteRefresh` was updated to await this\n * in the same PR.\n *\n * No-op when `address` doesn't match a cached entry — cheap to call\n * unconditionally on every write.\n */\nexport async function clearPortfolioCacheFor(address: string): Promise<void> {\n await getWalletCacheStore().delete(address);\n portfolioInflight.delete(address);\n}\n\nexport function clearPriceMapCache(): void {\n priceMapCache = null;\n}\n","// ---------------------------------------------------------------------------\n// Audric canonical-API client.\n//\n// When the engine runs server-side inside the Audric Next.js host, every\n// portfolio / history / price read should resolve through Audric's\n// canonical fetchers (`apps/web/lib/portfolio.ts`,\n// `apps/web/lib/transaction-history.ts`) so that the LLM, the dashboard,\n// and the daily cron all see identical numbers. This file is the engine's\n// thin client for those routes.\n//\n// Activation: set `T2000_AUDRIC_API` (preferred) or fall back to\n// `AUDRIC_INTERNAL_API_URL` / `NEXT_PUBLIC_APP_URL`. When neither is\n// available — e.g. CLI, MCP server, or any non-Audric embedding — the\n// helpers return `null` and callers MUST use their existing in-engine\n// path. This preserves the engine's standalone usability.\n//\n// All calls inherit the request `AbortSignal` from `ToolContext.signal`\n// so engine-level cancellation propagates to in-flight HTTP fetches.\n// ---------------------------------------------------------------------------\n\nimport type { AddressPortfolio, DefiSummary, PortfolioCoin } from './blockvision-prices.js';\nimport type { ServerPositionData } from './types.js';\n\nconst FETCH_TIMEOUT_MS = 6_000;\n\n/**\n * Resolve the audric API base URL from the engine's env shim, falling\n * back to `process.env`. Returns `null` when no override is configured —\n * callers MUST treat this as \"use in-engine fallback path\".\n *\n * Lookup order (first defined wins):\n * 1. `env.T2000_AUDRIC_API` — canonical override\n * 2. `process.env.T2000_AUDRIC_API` — same, picked up directly\n * 3. `env.AUDRIC_INTERNAL_API_URL` — legacy alias from audric host\n * 4. `process.env.AUDRIC_INTERNAL_API_URL`\n * 5. `process.env.NEXT_PUBLIC_APP_URL` — last-ditch host hint\n */\nexport function getAudricApiBase(env?: Record<string, string>): string | null {\n const fromEnv =\n env?.T2000_AUDRIC_API ??\n env?.AUDRIC_INTERNAL_API_URL ??\n null;\n if (fromEnv && fromEnv.trim().length > 0) return fromEnv.replace(/\\/$/, '');\n\n const fromProcess =\n process.env.T2000_AUDRIC_API ??\n process.env.AUDRIC_INTERNAL_API_URL ??\n process.env.NEXT_PUBLIC_APP_URL ??\n null;\n if (fromProcess && fromProcess.trim().length > 0) return fromProcess.replace(/\\/$/, '');\n\n return null;\n}\n\ninterface AudricPortfolioWire {\n address: string;\n netWorthUsd: number;\n walletValueUsd: number;\n walletAllocations: Record<string, number>;\n wallet: PortfolioCoin[];\n positions: {\n savings: number;\n borrows: number;\n savingsRate: number;\n healthFactor: number | null;\n maxBorrow: number;\n pendingRewards: number;\n supplies: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n borrowsDetail: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n };\n estimatedDailyYield: number;\n source: AddressPortfolio['source'];\n pricedAt: number;\n // [Bug — 2026-04-28] Surface DeFi from audric's canonical /api/portfolio.\n // Pre-fix the engine wire shape stripped these fields, so any tool that\n // resolved through the audric snapshot path (portfolio_analysis,\n // future timeline tools) silently dropped DeFi value from totals — even\n // though balance_check (which calls fetchAddressDefiPortfolio directly)\n // reported them correctly. Same SSOT-divergence class as the v0.54\n // FullPortfolioCanvas bug, manifesting in a different tool.\n // Optional on the wire so older audric deploys (pre-defi) don't error.\n defiValueUsd?: number;\n defiSource?: DefiSummary['source'];\n}\n\nexport interface AudricPortfolioResult {\n /** Wallet half — directly compatible with the existing `AddressPortfolio` shape. */\n portfolio: AddressPortfolio;\n /** NAVI lending positions, normalized to the engine's `ServerPositionData`. */\n positions: ServerPositionData;\n /** Net worth derived audric-side (`wallet + savings + defi - borrows`). */\n netWorthUsd: number;\n /** `savings * savingsRate / 365`, capped at 0. */\n estimatedDailyYield: number;\n /** Per-symbol balance map — convenient for adapters that already used `WalletBalances`. */\n walletAllocations: Record<string, number>;\n /**\n * [Bug — 2026-04-28] Aggregated DeFi value (Cetus LPs, Bluefin, Suilend,\n * etc.) when available. `defiSource === 'degraded'` when audric's wire\n * didn't include the field — callers should treat that as \"fall back to\n * a direct fetchAddressDefiPortfolio call\" (same convention used\n * inside the audric web app's UI components).\n */\n defiValueUsd: number;\n defiSource: DefiSummary['source'];\n}\n\n/**\n * Fetch the canonical portfolio snapshot from audric. Returns `null` if\n * audric isn't configured for this runtime, or if the request fails for\n * any reason — callers MUST fall back to the in-engine BlockVision +\n * NAVI path on `null`.\n */\nexport async function fetchAudricPortfolio(\n address: string,\n env?: Record<string, string>,\n signal?: AbortSignal,\n): Promise<AudricPortfolioResult | null> {\n const base = getAudricApiBase(env);\n if (!base) return null;\n\n try {\n const res = await fetch(\n `${base}/api/portfolio?address=${encodeURIComponent(address)}`,\n { signal: signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS) },\n );\n if (!res.ok) {\n console.warn(`[audric-api] portfolio ${address.slice(0, 10)} → HTTP ${res.status}`);\n return null;\n }\n const json = (await res.json()) as AudricPortfolioWire;\n\n const portfolio: AddressPortfolio = {\n coins: Array.isArray(json.wallet) ? json.wallet : [],\n totalUsd: json.walletValueUsd ?? 0,\n pricedAt: json.pricedAt ?? Date.now(),\n source: json.source ?? 'blockvision',\n };\n\n const positions: ServerPositionData = {\n savings: json.positions?.savings ?? 0,\n borrows: json.positions?.borrows ?? 0,\n savingsRate: json.positions?.savingsRate ?? 0,\n healthFactor: json.positions?.healthFactor ?? null,\n maxBorrow: json.positions?.maxBorrow ?? 0,\n pendingRewards: json.positions?.pendingRewards ?? 0,\n supplies: json.positions?.supplies ?? [],\n // The engine type calls this `borrows_detail`; audric's wire shape\n // calls it `borrowsDetail`. Normalize on the engine side so\n // downstream tools can keep their existing field names.\n borrows_detail: json.positions?.borrowsDetail ?? [],\n };\n\n return {\n portfolio,\n positions,\n netWorthUsd: json.netWorthUsd ?? portfolio.totalUsd + positions.savings - positions.borrows,\n estimatedDailyYield: json.estimatedDailyYield ?? 0,\n walletAllocations: json.walletAllocations ?? {},\n // Default to 'degraded' (not 'partial') when the wire shape lacks\n // DeFi: 'partial' implies \"we tried and got partial data\" which is\n // misleading for a route that simply doesn't return the field.\n // Callers that need DeFi must fall back to a direct fetch on\n // 'degraded' — exactly the convention BalanceCard already uses.\n defiValueUsd: typeof json.defiValueUsd === 'number' ? json.defiValueUsd : 0,\n defiSource: json.defiSource ?? 'degraded',\n };\n } catch (err) {\n console.warn(`[audric-api] portfolio ${address.slice(0, 10)} fetch failed:`, err);\n return null;\n }\n}\n\ninterface AudricHistoryWireItem {\n digest: string;\n action: string;\n label?: string;\n direction?: 'in' | 'out';\n amount?: number;\n asset?: string;\n counterparty?: string;\n timestamp: number;\n gasCost?: number;\n}\n\nexport interface AudricHistoryRecord {\n digest: string;\n action: string;\n label?: string;\n direction?: 'in' | 'out';\n amount?: number;\n asset?: string;\n /** Counterparty address (only set for transfers with a clear recipient). */\n recipient?: string;\n timestamp: number;\n date?: string;\n gasCost?: number;\n}\n\n/**\n * Fetch the canonical transaction history list from audric. Same fall\n * back contract as `fetchAudricPortfolio` — `null` means \"use in-engine\n * Sui-RPC path\". Audric's `/api/history` already merges `FromAddress` +\n * `ToAddress`, dedupes by digest, and parses Move calls via\n * `@t2000/sdk`'s shared parser, so the wire shape is a 1:1 match for the\n * engine's existing `TxRecord` once we rename `counterparty` →\n * `recipient`.\n */\nexport async function fetchAudricHistory(\n address: string,\n opts: { limit?: number },\n env?: Record<string, string>,\n signal?: AbortSignal,\n): Promise<AudricHistoryRecord[] | null> {\n const base = getAudricApiBase(env);\n if (!base) return null;\n\n const params = new URLSearchParams({ address });\n if (opts.limit != null) params.set('limit', String(opts.limit));\n\n try {\n const res = await fetch(`${base}/api/history?${params}`, {\n signal: signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n if (!res.ok) {\n console.warn(`[audric-api] history ${address.slice(0, 10)} → HTTP ${res.status}`);\n return null;\n }\n const json = (await res.json()) as { items?: AudricHistoryWireItem[] };\n const items = Array.isArray(json.items) ? json.items : [];\n\n return items.map((item) => ({\n digest: item.digest,\n action: item.action,\n label: item.label,\n direction: item.direction,\n amount: item.amount,\n asset: item.asset,\n recipient: item.counterparty,\n timestamp: item.timestamp,\n date: item.timestamp > 0 ? new Date(item.timestamp).toISOString() : undefined,\n gasCost: item.gasCost,\n }));\n } catch (err) {\n console.warn(`[audric-api] history ${address.slice(0, 10)} fetch failed:`, err);\n return null;\n }\n}\n","// ---------------------------------------------------------------------------\n// Sui address + SuiNS normalization — single source of truth.\n//\n// Background. Six read tools (balance, health, savings, history,\n// activity-summary, portfolio-analysis) accept an optional `address`\n// parameter so the LLM can inspect any public Sui wallet. Pre-v1.2 each\n// tool re-implemented the same `/^0x[a-fA-F0-9]{1,64}$/` regex inline AND\n// rejected SuiNS names (`obehi.sui`) entirely — the LLM had no way to\n// answer \"transaction list for obehi.sui\" because the schema would\n// reject the name before the call ever reached the tool body.\n//\n// This module is the canonical normalizer. It consolidates the regex,\n// adds SuiNS resolution via Sui RPC's `suix_resolveNameServiceAddress`,\n// and returns a structured `{ address, suinsName, raw }` triple so\n// downstream tools can both query the right 0x address AND surface the\n// name on result cards (e.g. titling \"Transaction history · obehi.sui\"\n// instead of \"Transaction history · 0x1234…abcd\").\n//\n// Single source of truth — see `.cursor/rules/single-source-of-truth.mdc`\n// and `.cursor/rules/engineering-principles.mdc` Principle 2.\n// ---------------------------------------------------------------------------\n\nconst SUI_MAINNET_URL = 'https://fullnode.mainnet.sui.io:443';\n\n/**\n * Canonical 0x-address shape. Loose lower bound (>= 1 hex char) so\n * pre-v1.0 short addresses still validate; tools that need a full 64-hex\n * address can additionally check `length === 66`. Case-insensitive on\n * the `0x` prefix because some upstream callers (and historic tests)\n * uppercase the prefix as part of address normalization tests; the\n * normalizer always returns the lowercased canonical form regardless.\n */\nexport const SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;\n\n/**\n * Strict canonical 0x-address shape (66 chars total). Used by the\n * resolver's \"looks like\" check to disambiguate \"user pasted an\n * address\" vs \"user typed a SuiNS name\".\n */\nexport const SUI_ADDRESS_STRICT_REGEX = /^0x[a-fA-F0-9]{64}$/i;\n\n/**\n * Mirrors the pattern in `audric/apps/web/lib/suins-resolver.ts` so the\n * host-side send executor and the engine-side read normalizer agree on\n * what counts as a SuiNS name. SuiNS allows nested labels (`team.alex.sui`)\n * but every label must use only `[a-z0-9-]`.\n */\nexport const SUINS_NAME_REGEX = /^[a-z0-9-]+(\\.[a-z0-9-]+)*\\.sui$/;\n\nexport class InvalidAddressError extends Error {\n constructor(public readonly raw: string) {\n super(\n `\"${raw}\" isn't a valid Sui address or SuiNS name. ` +\n `Pass a 0x-prefixed hex address (e.g. 0x40cd…3e62) or a SuiNS name ending in .sui (e.g. alex.sui).`,\n );\n this.name = 'InvalidAddressError';\n }\n}\n\nexport class SuinsNotRegisteredError extends Error {\n constructor(public readonly name_: string) {\n super(\n `\"${name_}\" isn't a registered SuiNS name. Double-check the spelling, ` +\n `or paste the full Sui address (0x… 64 hex characters).`,\n );\n this.name = 'SuinsNotRegisteredError';\n }\n}\n\nexport class SuinsRpcError extends Error {\n constructor(public readonly name_: string, detail: string) {\n super(`SuiNS lookup failed for \"${name_}\" (${detail}). Try again, or paste the full Sui address.`);\n this.name = 'SuinsRpcError';\n }\n}\n\n/**\n * Returns true if `value` looks like a SuiNS name (case-insensitive).\n * Cheap synchronous check — use to avoid an unnecessary RPC round-trip\n * for inputs that obviously aren't names (0x addresses, contact handles).\n */\nexport function looksLikeSuiNs(value: string): boolean {\n if (!value) return false;\n return SUINS_NAME_REGEX.test(value.trim().toLowerCase());\n}\n\n/**\n * Resolve a SuiNS name to its on-chain Sui address via the public\n * `suix_resolveNameServiceAddress` JSON-RPC method. Returns `null` if\n * the name resolves to no address (= not registered or expired). Throws\n * `SuinsRpcError` on RPC/network failure.\n *\n * The host SHOULD pass a `rpcUrl` that includes any vendor key (e.g.\n * audric's BlockVision-keyed URL) so the call benefits from the host's\n * paid retry/cache budget. Falls back to the public mainnet endpoint.\n */\nexport async function resolveSuinsViaRpc(\n rawName: string,\n ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<string | null> {\n const name = rawName.trim().toLowerCase();\n if (!SUINS_NAME_REGEX.test(name)) {\n throw new InvalidAddressError(rawName);\n }\n\n const url = ctx.suiRpcUrl || SUI_MAINNET_URL;\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_resolveNameServiceAddress',\n params: [name],\n }),\n signal: ctx.signal ?? AbortSignal.timeout(8_000),\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(name, msg);\n }\n\n if (!res.ok) {\n throw new SuinsRpcError(name, `HTTP ${res.status}`);\n }\n\n let body: { result?: string | null; error?: { code: number; message: string } };\n try {\n body = (await res.json()) as typeof body;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(name, `JSON parse failed: ${msg}`);\n }\n\n if (body.error) {\n throw new SuinsRpcError(name, body.error.message);\n }\n\n // result is the 0x…64-hex address, or null when the name has never\n // been registered (or has expired and the record was reaped).\n return body.result ?? null;\n}\n\n/**\n * Reverse-resolve a 0x address to its registered SuiNS names via\n * `suix_resolveNameServiceNames`. Returns the names sorted by the\n * registry (the first entry is conventionally the user's \"primary\"\n * name on dApps that show one), or `[]` when the address has no\n * SuiNS records. Throws `SuinsRpcError` on RPC/network failure.\n *\n * Why this is its own helper (not folded into `normalizeAddressInput`):\n * a reverse lookup adds a second RPC round-trip per tool call. We don't\n * want every read tool that takes an `address` to silently double its\n * latency. The lookup primitive is opt-in via the `resolve_suins` tool;\n * normalizers stay forward-only.\n */\nexport async function resolveAddressToSuinsViaRpc(\n rawAddress: string,\n ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<string[]> {\n const address = rawAddress.trim().toLowerCase();\n if (!SUI_ADDRESS_REGEX.test(address)) {\n throw new InvalidAddressError(rawAddress);\n }\n\n const url = ctx.suiRpcUrl || SUI_MAINNET_URL;\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_resolveNameServiceNames',\n params: [address],\n }),\n signal: ctx.signal ?? AbortSignal.timeout(8_000),\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(address, msg);\n }\n\n if (!res.ok) {\n throw new SuinsRpcError(address, `HTTP ${res.status}`);\n }\n\n // SuiNS reverse-lookup returns a paginated page object. We don't\n // bother paginating because (a) the LLM consumer only needs the\n // primary name, and (b) addresses with >50 names are vanishingly\n // rare. The first page (default 50) is the canonical view.\n let body: {\n result?: { data: string[]; nextCursor: string | null; hasNextPage: boolean };\n error?: { code: number; message: string };\n };\n try {\n body = (await res.json()) as typeof body;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(address, `JSON parse failed: ${msg}`);\n }\n\n if (body.error) {\n throw new SuinsRpcError(address, body.error.message);\n }\n\n return body.result?.data ?? [];\n}\n\nexport interface NormalizedAddress {\n /**\n * Canonical 0x-prefixed lowercase hex address. Always set on success.\n * Tools should use this for any downstream query (BlockVision, NAVI,\n * positionFetcher, etc.) and for cache keys.\n */\n address: string;\n /**\n * The user-facing name when the input was resolved via SuiNS, otherwise\n * `null`. Tools should stamp this on result data so card titles can\n * render \"Balance · obehi.sui\" instead of \"Balance · 0x1234…abcd\".\n */\n suinsName: string | null;\n /**\n * The original input (pre-normalization). Useful for error narration —\n * \"I tried to resolve `Obehi.Sui` and …\" reads better than the\n * post-trim/lowercase form.\n */\n raw: string;\n}\n\n/**\n * Canonical normalizer. Accepts a 0x address OR a SuiNS name; returns\n * a structured `NormalizedAddress`. Throws:\n * - `InvalidAddressError` if the input matches neither shape.\n * - `SuinsNotRegisteredError` if the SuiNS name is well-formed but\n * resolves to null (= not registered).\n * - `SuinsRpcError` if the RPC fails.\n *\n * Every read tool that accepts a user-supplied `address` parameter MUST\n * call this helper before any downstream lookup. Doing the check inline\n * (1) duplicates the regex, (2) silently rejects SuiNS names, (3) makes\n * cache keys inconsistent across tools (some lowercase, some not).\n */\nexport async function normalizeAddressInput(\n value: string,\n ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<NormalizedAddress> {\n const trimmed = value.trim();\n if (SUI_ADDRESS_REGEX.test(trimmed)) {\n return { address: trimmed.toLowerCase(), suinsName: null, raw: value };\n }\n if (looksLikeSuiNs(trimmed)) {\n const name = trimmed.toLowerCase();\n const address = await resolveSuinsViaRpc(name, ctx);\n if (!address) {\n throw new SuinsNotRegisteredError(name);\n }\n return { address: address.toLowerCase(), suinsName: name, raw: value };\n }\n throw new InvalidAddressError(value);\n}\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, requireAgent } from './utils.js';\nimport type { McpClientManager } from '../mcp-client.js';\nimport { NAVI_SERVER_NAME, NaviTools } from '../navi-config.js';\nimport {\n parseMcpJson,\n transformPositions,\n transformRewards,\n} from '../navi-transforms.js';\nimport {\n fetchAddressPortfolio,\n fetchAddressDefiPortfolio,\n type AddressPortfolio,\n type DefiSummary,\n} from '../blockvision-prices.js';\nimport { fetchAudricPortfolio, type AudricPortfolioResult } from '../audric-api.js';\nimport { normalizeAddressInput } from '../sui-address.js';\n\nconst GAS_RESERVE_SUI = 0.05;\n\n// vSUI (Volo's liquid-staked SUI). BlockVision sometimes lacks a price for\n// this token — when missing we read the official Volo exchange rate and\n// derive vSUI = rate × SUI price. See [v1.4.1 — M1'] for the rewrite that\n// mutates the portfolio in place.\nconst VSUI_COIN_TYPE =\n '0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT';\nconst SUI_COIN_TYPE = '0x2::sui::SUI';\nconst VSUI_FALLBACK_RATE = 1.05;\n\nasync function callNavi<T = unknown>(\n manager: McpClientManager,\n tool: string,\n args: Record<string, unknown> = {},\n): Promise<T> {\n const result = await manager.callTool(NAVI_SERVER_NAME, tool, args);\n if (result.isError) {\n const msg = result.content\n .filter((c: { type: string; text?: string }) => c.type === 'text' && c.text)\n .map((c: { type: string; text?: string }) => c.text!)\n .join(' ');\n throw new Error(`NAVI MCP error (${tool}): ${msg || 'unknown error'}`);\n }\n return parseMcpJson<T>(result.content);\n}\n\n/**\n * [v1.4.1 — M1'] Mutates `portfolio` in place to fill in the vSUI USD\n * price/value when BlockVision returned no price for it. Reads the\n * canonical exchange rate from Volo's public stats endpoint and falls\n * back to a hardcoded 1.05× SUI multiplier if the call fails.\n *\n * No-op when the wallet doesn't hold vSUI or BlockVision already returned\n * a price.\n */\nasync function applyVsuiPriceFallback(portfolio: AddressPortfolio): Promise<void> {\n const vsuiIdx = portfolio.coins.findIndex((c) => c.coinType === VSUI_COIN_TYPE);\n if (vsuiIdx === -1) return;\n const vsui = portfolio.coins[vsuiIdx];\n if (vsui.price != null) return;\n\n const suiCoin = portfolio.coins.find((c) => c.coinType === SUI_COIN_TYPE);\n const suiPrice = suiCoin?.price ?? null;\n if (suiPrice == null) return;\n\n let rate = VSUI_FALLBACK_RATE;\n try {\n const statsRes = await fetch('https://open-api.naviprotocol.io/api/volo/stats', {\n signal: AbortSignal.timeout(5_000),\n });\n if (statsRes.ok) {\n const json = (await statsRes.json()) as {\n data?: { exchange_rate?: number; exchangeRate?: number };\n exchange_rate?: number;\n exchangeRate?: number;\n };\n const data = json.data ?? json;\n rate = data.exchange_rate ?? data.exchangeRate ?? VSUI_FALLBACK_RATE;\n }\n } catch {\n // Network error — keep the hardcoded fallback rate.\n }\n\n const price = rate * suiPrice;\n const amount = Number(vsui.balance) / 10 ** vsui.decimals;\n const usdValue = Number.isFinite(amount) ? amount * price : null;\n const previousUsd = vsui.usdValue ?? 0;\n portfolio.coins[vsuiIdx] = { ...vsui, price, usdValue };\n if (usdValue != null) {\n portfolio.totalUsd = portfolio.totalUsd - previousUsd + usdValue;\n }\n}\n\nasync function loadPortfolio(\n address: string,\n blockvisionApiKey: string | undefined,\n fallbackRpcUrl: string | undefined,\n cache: Map<string, AddressPortfolio> | undefined,\n // [SPEC 8 v0.5.1 B3.2] Forward the per-tool retry counter so any\n // BlockVision retries during the wallet read surface as `attemptCount`\n // on the eventual `tool_result` event.\n retryStats?: { attemptCount: number },\n): Promise<AddressPortfolio> {\n if (cache) {\n const hit = cache.get(address);\n if (hit) return hit;\n }\n const portfolio = await fetchAddressPortfolio(address, blockvisionApiKey, fallbackRpcUrl, { retryStats });\n if (cache) cache.set(address, portfolio);\n return portfolio;\n}\n\nexport const balanceCheckTool = buildTool({\n name: 'balance_check',\n description:\n 'Get the full balance breakdown for the signed-in user OR any public Sui address or SuiNS name. Returns wallet holdings (tokens the address owns — NOT savings), NAVI savings deposits (USDC and/or USDsui deposited into NAVI Protocol earning yield), outstanding debt, pending rewards, gas reserve, total net worth, saveableUsdc (USDC wallet balance available to save), and saveableUsdsui (USDsui wallet balance available to save — surfaces only when > 0). IMPORTANT: wallet holdings like GOLD, SUI, USDT, USDe are NOT savings positions and are NOT saveable — only USDC and USDsui can be saved/borrowed. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v1.4 BlockVision] Wallet contents change after every send / swap /\n // save / etc. and the price half of this result is sourced from\n // BlockVision's Indexer REST API. Microcompact must NEVER dedupe these\n // calls — each one reflects a different on-chain + market snapshot.\n cacheable: false,\n\n async call(input, context) {\n /**\n * [v0.49] Address-scope: tool now accepts an optional `address` param\n * so the LLM can inspect any public Sui wallet (contacts, watched\n * addresses, etc.). Pre-v0.49 the tool only ever queried\n * `context.walletAddress`, which masked any contact-balance question\n * by silently returning the signed-in user's data instead. Falls back\n * to `context.walletAddress` when the param is absent. Stamps\n * `address` + `isSelfQuery` on the result so the UI can title cards\n * appropriately when rendering a non-self balance.\n *\n * The host-provided `positionFetcher(address)` takes an address\n * argument and works for any wallet, so savings / debt / rewards\n * automatically scope correctly. Empty wallets and unknown addresses\n * surface honestly (zero balance) rather than failing.\n */\n // [v1.2 SuiNS] Normalize the user-supplied address. Accepts both 0x\n // hex and *.sui names; throws structured errors when the input is\n // malformed or the SuiNS name doesn't resolve. Stamps `suinsName` on\n // the result so the host card can render \"Balance · alex.sui · 0x12…ab\"\n // instead of just the truncated hex.\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n if (hasNaviMcpGlobal(context)) {\n if (!targetAddress) {\n throw new Error('No wallet address provided. Sign in or pass `address` to inspect a public wallet.');\n }\n const address = targetAddress;\n const mgr = getMcpManager(context);\n\n // [v0.47] When a host-side `positionFetcher` is configured (Audric\n // production), savings/debt/rewards come from the host instead of\n // NAVI MCP. Skip those MCP calls entirely — they were previously\n // fetched in parallel and then discarded.\n const hasPositionFetcher = !!context.positionFetcher;\n\n // [single-source-of-truth — Apr 2026] When the engine runs inside\n // audric (T2000_AUDRIC_API / AUDRIC_INTERNAL_API_URL set), prefer\n // audric's canonical `/api/portfolio` so the LLM, dashboard, and\n // daily cron all read identical numbers. Returns null in\n // CLI / MCP / standalone mode → falls back to the BlockVision +\n // NAVI MCP path below.\n const audricPortfolio = await fetchAudricPortfolio(\n address,\n context.env,\n context.signal,\n );\n\n // [v1.4 BlockVision] Single BlockVision call returns coins +\n // balances + prices in one shot, replacing the parallel\n // (Sui RPC fetchWalletCoins + DefiLlama fetchTokenPrices) pair.\n // Run alongside positions / rewards / positionFetcher so total\n // wall time is bound by the slowest of the four.\n //\n // [v0.50.2] DeFi portfolio fetch added as a 5th parallel leg —\n // hits BlockVision /account/defiPortfolio for the 9 most-used Sui\n // DeFi protocols (Cetus, Suilend, Scallop, Bluefin, Aftermath,\n // Haedal, Suistake, SuiNS-staking, Walrus). Excludes NAVI to avoid\n // double-counting against positionFetcher/MCP savings. v0.50.1\n // briefly fanned out to all 26 BV protocols but the resulting\n // burst caused the wallet `/account/coins` call to occasionally\n // 429 and silently degrade to RPC (where non-stables are unpriced)\n // — so wallet display showed $0 for users with non-stable\n // holdings. v0.50.2 walks back to 9 (1 wallet + 9 DeFi = 10 burst,\n // safely below BV burst caps). Cached 60s, parallel-fanout, 5xx\n // on one protocol drops just that protocol. See\n // blockvision-prices.ts header for the generic-walker design.\n // When audric returned a canonical snapshot we already have\n // wallet + positions in one shot — short-circuit the parallel\n // BlockVision + NAVI fan-out so we don't double-pay the latency\n // and so the numbers in the result match audric's API exactly.\n const usingAudricSnapshot = audricPortfolio !== null;\n const audric: AudricPortfolioResult | null = audricPortfolio;\n\n const [portfolio, positions, rewards, serverPositions, defiPortfolio] = await Promise.all([\n usingAudricSnapshot\n ? Promise.resolve(audric!.portfolio)\n : loadPortfolio(\n address,\n context.blockvisionApiKey,\n context.suiRpcUrl,\n context.portfolioCache,\n context.retryStats,\n ).catch((err) => {\n console.warn('[balance_check] portfolio fetch failed, returning empty:', err);\n const fallback: AddressPortfolio = {\n coins: [],\n totalUsd: 0,\n pricedAt: Date.now(),\n source: 'sui-rpc-degraded',\n };\n return fallback;\n }),\n usingAudricSnapshot || hasPositionFetcher\n ? Promise.resolve(null)\n : callNavi(mgr, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }).catch((err) => {\n console.warn('[balance_check] NAVI GET_POSITIONS failed:', err);\n return null;\n }),\n usingAudricSnapshot || hasPositionFetcher\n ? Promise.resolve(null)\n : callNavi(mgr, NaviTools.GET_AVAILABLE_REWARDS, { address }).catch((err) => {\n console.warn('[balance_check] NAVI GET_AVAILABLE_REWARDS failed:', err);\n return null;\n }),\n usingAudricSnapshot\n ? Promise.resolve(audric!.positions)\n : hasPositionFetcher\n ? context.positionFetcher!(address).catch((err) => {\n console.warn('[balance_check] positionFetcher failed:', err);\n return null;\n })\n : Promise.resolve(null),\n // [v0.50] DeFi leg — independent of NAVI (excluded) and the wallet\n // portfolio (which only has coin holdings). Failure here surfaces\n // as defi.totalUsd === 0 and `source: 'degraded'`, leaving the\n // rest of balance_check unaffected. The fetcher fills its own\n // prices via fetchTokenPrices for any coin types it discovers.\n fetchAddressDefiPortfolio(address, context.blockvisionApiKey, {}, { retryStats: context.retryStats }).catch((err) => {\n console.warn('[balance_check] defi fetch failed:', err);\n const fallback: DefiSummary = {\n totalUsd: 0,\n perProtocol: {},\n pricedAt: Date.now(),\n source: 'degraded',\n };\n return fallback;\n }),\n ]);\n\n // [v1.4.1 — M1'] vSUI workaround mutates the portfolio in place\n // (BlockVision occasionally lacks a price for vSUI; we derive it\n // from the SUI price + Volo exchange rate). No-op when the wallet\n // doesn't hold vSUI.\n await applyVsuiPriceFallback(portfolio);\n\n // [v1.4.1 — M2'] NAVI MCP `GET_COINS` fallback removed. Previously\n // when Sui RPC returned an empty coin list we'd hit NAVI as a\n // tertiary source; with BlockVision as the primary and Sui RPC\n // already serving as the degraded fallback inside\n // `fetchAddressPortfolio`, the third tier added complexity without\n // real coverage (NAVI's coin endpoint shares infrastructure with\n // its already-failing positions endpoint). An empty wallet now\n // surfaces honestly to the user rather than silently swapping\n // sources mid-render.\n\n let availableUsd = 0;\n let stablesUsd = 0;\n let gasReserveUsd = 0;\n\n const STABLE_SYMBOLS = new Set(['USDC', 'USDT', 'USDe', 'USDsui', 'wUSDC', 'wUSDT']);\n const holdings: Array<{ symbol: string; coinType: string; balance: number; usdValue: number }> = [];\n\n for (const coin of portfolio.coins) {\n const balance = Number(coin.balance) / 10 ** coin.decimals;\n const price = coin.price ?? 0;\n\n if (coin.symbol === 'SUI' || coin.coinType === SUI_COIN_TYPE) {\n const reserveAmount = Math.min(balance, GAS_RESERVE_SUI);\n gasReserveUsd = reserveAmount * price;\n availableUsd += (balance - reserveAmount) * price;\n } else {\n availableUsd += balance * price;\n if (STABLE_SYMBOLS.has(coin.symbol)) {\n stablesUsd += balance * price;\n }\n }\n\n if (balance > 0) {\n holdings.push({\n symbol: coin.symbol || coin.coinType.split('::').pop() || coin.coinType,\n coinType: coin.coinType,\n balance,\n usdValue: balance * price,\n });\n }\n }\n\n let savings: number;\n let debt: number;\n let pendingRewardsUsd: number;\n\n if (serverPositions) {\n savings = serverPositions.savings;\n debt = serverPositions.borrows;\n pendingRewardsUsd = serverPositions.pendingRewards;\n } else {\n const posEntries = transformPositions(positions);\n const rewardEntries = transformRewards(rewards);\n savings = posEntries\n .filter((p) => p.type === 'supply')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n debt = posEntries\n .filter((p) => p.type === 'borrow')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n pendingRewardsUsd = rewardEntries.reduce((sum, r) => sum + r.valueUsd, 0);\n }\n\n const visibleHoldings = holdings\n .filter((h) => h.usdValue >= 0.01)\n .sort((a, b) => b.usdValue - a.usdValue);\n\n const usdcHolding = holdings.find((h) => h.symbol === 'USDC');\n const saveableUsdc = usdcHolding ? usdcHolding.balance : 0;\n // [v0.51.0] USDsui is the second permitted saveable asset. Surface its\n // balance separately so the LLM can answer \"how much can I save?\" with\n // both stables, and so the displayText flags it (saveable) instead of\n // letting the LLM treat it as a generic holding. Not rolled into\n // `saveableUsdc` — the field name is canonical for USDC and downstream\n // permission/Tier resolvers depend on it.\n const usdsuiHolding = holdings.find((h) => h.symbol === 'USDsui');\n const saveableUsdsui = usdsuiHolding ? usdsuiHolding.balance : 0;\n\n // [v0.50] DeFi summary already resolved in the parallel fan-out\n // above. The fetcher fills its own prices via fetchTokenPrices for\n // any coin types found in DeFi positions that aren't stables.\n // Long-tail LP partner tokens that BlockVision's price list\n // doesn't cover may under-count — acceptable Phase 1 trade-off.\n const defi: DefiSummary = defiPortfolio;\n\n const bal = {\n available: availableUsd,\n savings,\n debt,\n pendingRewards: pendingRewardsUsd,\n gasReserve: gasReserveUsd,\n defi: defi.totalUsd,\n defiByProtocol: defi.perProtocol,\n defiSource: defi.source,\n // [v0.54] Forward the DeFi entry's pricedAt so the BalanceCard\n // can render \"cached Nm ago\" when source === 'partial-stale'.\n // Always populated; consumers ignore unless source is stale.\n defiPricedAt: defi.pricedAt,\n total: availableUsd + savings + gasReserveUsd + pendingRewardsUsd + defi.totalUsd - debt,\n stables: stablesUsd,\n holdings: visibleHoldings,\n saveableUsdc,\n saveableUsdsui,\n priceSource: portfolio.source,\n address,\n isSelfQuery,\n suinsName,\n };\n\n const holdingsList = visibleHoldings.map((h) => `${h.symbol}: ${h.balance < 1 ? h.balance.toFixed(6) : h.balance.toFixed(2)} ($${h.usdValue.toFixed(2)})`).join(', ');\n const subjectLabel = suinsName ?? `${address.slice(0, 6)}…${address.slice(-4)}`;\n const subjectPrefix = isSelfQuery ? 'Balance' : `Balance for ${subjectLabel}`;\n // Surface the DeFi fetch state so the LLM can answer accurately:\n // - `blockvision` + total > 0 → list protocols and dollar value\n // - `blockvision` + total === 0 → genuinely no positions in the 9 covered protocols\n // - `partial` → at least one protocol failed; total may under-count\n // - `degraded` → no API key OR every protocol failed; total UNKNOWN, not zero\n // Pre-v0.50.3 we silently emitted `''` for zero/degraded, which let\n // the LLM confidently assert \"no DeFi positions\" when in reality the\n // fetcher had been short-circuited by a missing BLOCKVISION_API_KEY.\n const defiSummaryText = (() => {\n if (defi.source === 'degraded') {\n return ' DeFi positions (Bluefin / Suilend / Cetus / etc.): UNAVAILABLE — DeFi data source is currently unreachable. Do NOT assert \"no DeFi positions\"; tell the user this slice is temporarily unknown and the total above EXCLUDES DeFi.';\n }\n if (defi.source === 'partial-stale' && defi.totalUsd > 0) {\n // [v0.54] Sticky-positive cache fallback — fresh BlockVision\n // call failed but we have a recent positive value. The total\n // INCLUDES this stale value (it's the most accurate number\n // we have right now), but mention provenance honestly.\n const ageMin = Math.round((Date.now() - defi.pricedAt) / 60_000);\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)} (last refresh ${ageMin}m ago — live BlockVision call failed, using cached value).`;\n }\n if (defi.totalUsd > 0) {\n const partialNote = defi.source === 'partial' ? ' (partial — one or more protocols failed; value may under-count)' : '';\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)}${partialNote}.`;\n }\n if (defi.source === 'partial') {\n // [v0.53.4] Stronger wording. Pre-fix this returned a soft\n // \"caveat that the picture may be incomplete\", which the\n // LLM consistently dropped from its narration when at least\n // one major protocol (Bluefin/Suilend/Cetus) 429'd during a\n // burst. The narration would then claim \"$X total\" with NO\n // mention of the missing slice, even when the same address\n // 30s later (cache miss → fresh fetch) showed thousands of\n // dollars in DeFi via the timeline canvas. Reworded to be\n // an explicit instruction matching the `degraded` branch.\n // (v0.54 reduces how often this branch fires by adding the\n // sticky-positive fallback above — partial+0 with a recent\n // positive cache now resolves to `partial-stale` instead.)\n return ' DeFi positions: UNKNOWN — at least one protocol failed to respond. The total above EXCLUDES any DeFi the failing protocols may hold. Do NOT assert \"no DeFi positions\" or \"DeFi: $0\"; tell the user DeFi is temporarily unreachable for this address.';\n }\n return '';\n })();\n const saveableSummary = saveableUsdsui > 0\n ? `Saveable: ${saveableUsdc.toFixed(2)} USDC + ${saveableUsdsui.toFixed(saveableUsdsui < 1 ? 4 : 2)} USDsui (only USDC and USDsui can be saved/borrowed).`\n : `Saveable USDC (only USDC and USDsui can be saved): ${saveableUsdc.toFixed(2)} USDC.`;\n return {\n data: bal,\n displayText: `${subjectPrefix}: $${bal.total.toFixed(2)} total. Wallet holdings (NOT savings): ${holdingsList || 'none'}. NAVI savings deposits: $${bal.savings.toFixed(2)}.${defiSummaryText} ${saveableSummary}`,\n };\n }\n\n // SDK agent fallback — only meaningful for the signed-in user (the\n // SDK's `balance()` method is bound to the agent's own wallet). If\n // the LLM passed a different address (post-normalization), refuse\n // rather than silently returning the agent's own balance.\n if (\n targetAddress &&\n context.walletAddress &&\n targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()\n ) {\n throw new Error(\n `Cannot inspect ${targetAddress.slice(0, 8)}… without NAVI MCP enabled. Configure NAVI MCP to enable third-party address reads.`,\n );\n }\n const agent = requireAgent(context);\n // [v0.50] In the SDK fallback path (CLI-only, self-query) we also\n // fan out to BlockVision /account/defiPortfolio so the CLI matches\n // engine + audric numbers. No-op when blockvisionApiKey is unset\n // (returns DefiSummary with source: 'degraded' and totalUsd: 0).\n const fetchAddress = (targetAddress ?? context.walletAddress) as string;\n const [balance, defi] = await Promise.all([\n agent.balance(),\n fetchAddressDefiPortfolio(fetchAddress, context.blockvisionApiKey, {}, { retryStats: context.retryStats }).catch((err) => {\n console.warn('[balance_check] sdk-path defi fetch failed:', err);\n const fallback: DefiSummary = {\n totalUsd: 0,\n perProtocol: {},\n pricedAt: Date.now(),\n source: 'degraded',\n };\n return fallback;\n }),\n ]);\n\n const gasReserveUsd = typeof balance.gasReserve === 'number'\n ? balance.gasReserve\n : (balance.gasReserve as { usdEquiv: number }).usdEquiv ?? 0;\n const stablesTotal = typeof balance.stables === 'number'\n ? balance.stables\n : Object.values(balance.stables as Record<string, number>).reduce((a: number, b: number) => a + b, 0);\n\n const sdkHoldings = (balance as unknown as Record<string, unknown>).holdings;\n const holdingsArr = Array.isArray(sdkHoldings) ? sdkHoldings : [];\n\n const usdcHolding = holdingsArr.find((h: { symbol?: string }) => h.symbol === 'USDC');\n const sdkSaveableUsdc = usdcHolding ? ((usdcHolding as { balance?: number }).balance ?? 0) : 0;\n const usdsuiHolding = holdingsArr.find((h: { symbol?: string }) => h.symbol === 'USDsui');\n const sdkSaveableUsdsui = usdsuiHolding ? ((usdsuiHolding as { balance?: number }).balance ?? 0) : 0;\n\n const sdkDefiSummaryText = (() => {\n if (defi.source === 'degraded') {\n return ' DeFi positions: UNAVAILABLE — data source unreachable. Do NOT claim \"no DeFi positions\"; report this slice as temporarily unknown and the total above EXCLUDES DeFi.';\n }\n if (defi.source === 'partial-stale' && defi.totalUsd > 0) {\n // [v0.54] Mirror of MCP-path sticky-positive narration.\n const ageMin = Math.round((Date.now() - defi.pricedAt) / 60_000);\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)} (last refresh ${ageMin}m ago — live BlockVision call failed, using cached value).`;\n }\n if (defi.totalUsd > 0) {\n const partialNote = defi.source === 'partial' ? ' (partial — one or more protocols failed; value may under-count)' : '';\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)}${partialNote}.`;\n }\n if (defi.source === 'partial') {\n // [v0.53.4] Mirror of the MCP-path strengthening — see the\n // companion comment ~70 lines up for full rationale.\n return ' DeFi positions: UNKNOWN — at least one protocol failed to respond. The total above EXCLUDES any DeFi the failing protocols may hold. Do NOT assert \"no DeFi positions\" or \"DeFi: $0\"; tell the user DeFi is temporarily unreachable for this wallet.';\n }\n return '';\n })();\n const sdkTotal = balance.total + defi.totalUsd;\n\n return {\n data: {\n available: balance.available,\n savings: balance.savings,\n debt: balance.debt,\n pendingRewards: balance.pendingRewards,\n gasReserve: gasReserveUsd,\n defi: defi.totalUsd,\n defiByProtocol: defi.perProtocol,\n defiSource: defi.source,\n // [v0.54] Same staleness provenance as the MCP path above.\n defiPricedAt: defi.pricedAt,\n total: sdkTotal,\n stables: stablesTotal,\n holdings: holdingsArr,\n saveableUsdc: sdkSaveableUsdc,\n saveableUsdsui: sdkSaveableUsdsui,\n address: targetAddress ?? '',\n isSelfQuery: true,\n suinsName,\n },\n displayText: `Balance: $${sdkTotal.toFixed(2)} total. Wallet: $${balance.available.toFixed(2)} available. NAVI savings deposits: $${balance.savings.toFixed(2)}.${sdkDefiSummaryText} ${sdkSaveableUsdsui > 0 ? `Saveable: ${sdkSaveableUsdc.toFixed(2)} USDC + ${sdkSaveableUsdsui.toFixed(sdkSaveableUsdsui < 1 ? 4 : 2)} USDsui (only USDC and USDsui can be saved/borrowed).` : `Saveable USDC (only USDC and USDsui can be saved): ${sdkSaveableUsdc.toFixed(2)} USDC.`}`,\n };\n },\n});\n","// ---------------------------------------------------------------------------\n// NaviCacheStore — pluggable cache backend for NAVI MCP composite reads\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// PR 4 of the scaling spec adds a 30s cache for `savings_info` and\n// `health_check` reads, and a 5-minute cache for `rates_info`. Without\n// it, every `savings_info` / `health_check` call in a chat turn issues\n// 2–4 NAVI MCP round-trips (~200–500ms each). At 500 DAU sustained, this\n// puts visible pressure on NAVI's endpoint and adds 400–1000ms of tail\n// latency to those tools every turn.\n//\n// The cache is keyed by `navi:<endpoint>:<address>` for address-scoped\n// reads and `navi:rates` for the global rates table:\n// - `navi:savings:<address>` — 30s TTL\n// - `navi:health:<address>` — 30s TTL\n// - `navi:rates` — 300s (5 min) TTL\n//\n// The default `InMemoryNaviCacheStore` is per-process (CLI/tests/dev).\n// Audric injects `UpstashNaviCacheStore` at engine init via\n// `init-engine-stores.ts` so all Vercel instances share one cache.\n//\n// Store contract\n// --------------\n// The store is a dumb typed key-value with TTL. Cache freshness logic\n// (when to re-fetch, when to serve stale) lives in the FETCHER so\n// implementations can be swapped without re-implementing policy. `get`\n// returns `null` on miss, expiry, or backend error. `set` swallows errors.\n// ---------------------------------------------------------------------------\n\n/** Cache entry shape. `cachedAt` is the wall-clock ms at write time. */\nexport interface NaviCacheEntry {\n data: unknown;\n /** Wall-clock ms when the entry was written. Used by callers for freshness math. */\n cachedAt: number;\n}\n\n/**\n * Pluggable cache backend for NAVI MCP reads.\n *\n * All methods are async to accommodate Redis-backed implementations.\n * `get` must return `null` (not throw) on backend failure.\n * `set` must swallow errors.\n */\nexport interface NaviCacheStore {\n get(key: string): Promise<NaviCacheEntry | null>;\n set(key: string, entry: NaviCacheEntry, ttlSec: number): Promise<void>;\n delete(key: string): Promise<void>;\n clear(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\nexport class InMemoryNaviCacheStore implements NaviCacheStore {\n private readonly store = new Map<string, { entry: NaviCacheEntry; expiresAt: number }>();\n\n async get(key: string): Promise<NaviCacheEntry | null> {\n const slot = this.store.get(key);\n if (!slot) return null;\n if (Date.now() >= slot.expiresAt) {\n this.store.delete(key);\n return null;\n }\n return slot.entry;\n }\n\n async set(key: string, entry: NaviCacheEntry, ttlSec: number): Promise<void> {\n this.store.set(key, {\n entry,\n expiresAt: Date.now() + ttlSec * 1000,\n });\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeStore: NaviCacheStore = new InMemoryNaviCacheStore();\n\n/** Swap the active NAVI cache store. Called once at engine init by Audric. */\nexport function setNaviCacheStore(store: NaviCacheStore): void {\n activeStore = store;\n}\n\n/** Returns the currently active store. Used by navi-reads.ts. */\nexport function getNaviCacheStore(): NaviCacheStore {\n return activeStore;\n}\n\n/** Restore the default in-memory store. Used by test teardowns. */\nexport function resetNaviCacheStore(): void {\n activeStore = new InMemoryNaviCacheStore();\n}\n\n// ---------------------------------------------------------------------------\n// Cache key helpers\n// ---------------------------------------------------------------------------\n\n/** 30s TTL for address-scoped reads (savings, health). */\nexport const NAVI_ADDR_TTL_SEC = 30;\n\n/** 300s (5 min) TTL for the global rates table. */\nexport const NAVI_RATES_TTL_SEC = 300;\n\nexport const naviKey = {\n rates: () => 'navi:rates',\n savings: (address: string) => `navi:savings:${address.toLowerCase()}`,\n health: (address: string) => `navi:health:${address.toLowerCase()}`,\n} as const;\n","import type { McpClientManager, McpCallResult } from './mcp-client.js';\nimport { NAVI_SERVER_NAME, NaviTools } from './navi-config.js';\nimport {\n parseMcpJson,\n transformBalance,\n transformHealthFactor,\n transformPositions,\n transformRates,\n transformRewards,\n transformSavings,\n type BalanceResult,\n type HealthFactorResult,\n type PendingReward,\n type PositionEntry,\n type RatesResult,\n type SavingsResult,\n} from './navi-transforms.js';\nimport {\n getNaviCacheStore,\n naviKey,\n NAVI_ADDR_TTL_SEC,\n NAVI_RATES_TTL_SEC,\n} from './navi-cache.js';\nimport { getTelemetrySink } from './telemetry.js';\n\n// ---------------------------------------------------------------------------\n// Options for composite reads\n// ---------------------------------------------------------------------------\n\nexport interface NaviReadOptions {\n /** MCP server name override (default: 'navi'). */\n serverName?: string;\n /** Skip the cache for this call (default: false). Useful for post-write refreshes. */\n skipCache?: boolean;\n}\n\nfunction sn(opts?: NaviReadOptions): string {\n return opts?.serverName ?? NAVI_SERVER_NAME;\n}\n\n// ---------------------------------------------------------------------------\n// Circuit breaker (PR 4)\n//\n// NAVI MCP can return errors (rate limits, 5xx) under load. A process-local\n// CB mirrors the BlockVision pattern: open after NAVI_CB_THRESHOLD errors\n// in NAVI_CB_WINDOW_MS, suppress retries for NAVI_CB_COOLDOWN_MS.\n// Per-process state is intentional — same rationale as BV CB.\n// ---------------------------------------------------------------------------\nconst NAVI_CB_WINDOW_MS = 5_000;\nconst NAVI_CB_THRESHOLD = 10;\nconst NAVI_CB_COOLDOWN_MS = 30_000;\n\nlet naviCb429Timestamps: number[] = [];\nlet naviCbOpenUntil = 0;\n\nfunction naviCbIsOpen(now: number): boolean {\n return now < naviCbOpenUntil;\n}\n\nfunction naviCbRecordError(now: number): void {\n naviCb429Timestamps.push(now);\n naviCb429Timestamps = naviCb429Timestamps.filter((t) => now - t < NAVI_CB_WINDOW_MS);\n if (naviCb429Timestamps.length >= NAVI_CB_THRESHOLD && !naviCbIsOpen(now)) {\n naviCbOpenUntil = now + NAVI_CB_COOLDOWN_MS;\n getTelemetrySink().gauge('navi.cb_open', 1);\n console.warn(\n `[navi-reads] circuit breaker OPEN — ${NAVI_CB_THRESHOLD} errors in ${NAVI_CB_WINDOW_MS}ms, retries disabled for ${NAVI_CB_COOLDOWN_MS / 1000}s`,\n );\n naviCb429Timestamps = [];\n }\n}\n\n/** Test seam — reset NAVI CB state between tests. */\nexport function _resetNaviCircuitBreaker(): void {\n naviCb429Timestamps = [];\n naviCbOpenUntil = 0;\n}\n\n// ---------------------------------------------------------------------------\n// Retry config\n// ---------------------------------------------------------------------------\nconst NAVI_RETRY_MAX_ATTEMPTS = 3;\nconst NAVI_RETRY_BASE_DELAY_MS = 200;\nconst NAVI_RETRY_BACKOFF_FACTOR = 3;\n\n// ---------------------------------------------------------------------------\n// Helper: call NAVI tool with retry and circuit breaker\n// ---------------------------------------------------------------------------\n\nasync function callNavi<T = unknown>(\n manager: McpClientManager,\n tool: string,\n args: Record<string, unknown> = {},\n opts?: NaviReadOptions,\n): Promise<T> {\n const result: McpCallResult = await manager.callTool(sn(opts), tool, args);\n if (result.isError) {\n const msg = result.content\n .filter((c) => c.type === 'text' && c.text)\n .map((c) => c.text!)\n .join(' ');\n throw new Error(`NAVI MCP error (${tool}): ${msg || 'unknown error'}`);\n }\n return parseMcpJson<T>(result.content);\n}\n\nasync function callNaviWithRetry<T = unknown>(\n manager: McpClientManager,\n tool: string,\n args: Record<string, unknown> = {},\n opts?: NaviReadOptions,\n): Promise<T> {\n const sink = getTelemetrySink();\n const now = () => Date.now();\n\n if (naviCbIsOpen(now())) {\n sink.counter('navi.requests', { tool, status: 'cb_open' });\n throw new Error(`[navi-reads] circuit breaker open — skipping ${tool}`);\n }\n\n let lastError: Error | undefined;\n for (let attempt = 0; attempt < NAVI_RETRY_MAX_ATTEMPTS; attempt++) {\n if (attempt > 0) {\n const delay = NAVI_RETRY_BASE_DELAY_MS * Math.pow(NAVI_RETRY_BACKOFF_FACTOR, attempt - 1);\n await new Promise<void>((r) => setTimeout(r, delay));\n }\n try {\n const result = await callNavi<T>(manager, tool, args, opts);\n sink.counter('navi.requests', { tool, status: '2xx', attempt: String(attempt) });\n return result;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n sink.counter('navi.requests', { tool, status: '5xx', attempt: String(attempt) });\n naviCbRecordError(now());\n\n if (naviCbIsOpen(now())) {\n throw lastError;\n }\n }\n }\n throw lastError ?? new Error(`NAVI MCP: ${tool} failed after ${NAVI_RETRY_MAX_ATTEMPTS} attempts`);\n}\n\n// ---------------------------------------------------------------------------\n// Cache helpers\n// ---------------------------------------------------------------------------\n\nasync function cacheGet<T>(key: string): Promise<T | null> {\n try {\n const entry = await getNaviCacheStore().get(key);\n if (entry !== null) {\n getTelemetrySink().counter('navi.cache_hit', { key_prefix: key.split(':').slice(0, 2).join(':'), freshness: 'fresh' });\n return entry.data as T; // safe cast: we control what we write\n }\n getTelemetrySink().counter('navi.cache_hit', { key_prefix: key.split(':').slice(0, 2).join(':'), freshness: 'miss' });\n return null;\n } catch {\n return null;\n }\n}\n\nasync function cacheSet<T>(key: string, data: T, ttlSec: number): Promise<void> {\n try {\n await getNaviCacheStore().set(key, { data, cachedAt: Date.now() }, ttlSec);\n } catch {\n // swallow — cache miss is always tolerable\n }\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: rates\n// ---------------------------------------------------------------------------\n\nexport async function fetchRates(\n manager: McpClientManager,\n opts?: NaviReadOptions,\n): Promise<RatesResult> {\n const key = naviKey.rates();\n if (!opts?.skipCache) {\n const cached = await cacheGet<RatesResult>(key);\n if (cached) return cached;\n }\n\n const pools = await callNaviWithRetry(manager, NaviTools.GET_POOLS, {}, opts);\n const result = transformRates(pools);\n await cacheSet(key, result, NAVI_RATES_TTL_SEC);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: health factor (enriched with positions)\n// ---------------------------------------------------------------------------\n\nexport async function fetchHealthFactor(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<HealthFactorResult> {\n const key = naviKey.health(address);\n if (!opts?.skipCache) {\n const cached = await cacheGet<HealthFactorResult>(key);\n if (cached) return cached;\n }\n\n const [hfRaw, posRaw] = await Promise.all([\n callNaviWithRetry(manager, NaviTools.GET_HEALTH_FACTOR, { address }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }, opts),\n ]);\n\n const result = transformHealthFactor(hfRaw, posRaw);\n await cacheSet(key, result, NAVI_ADDR_TTL_SEC);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: balance breakdown\n// ---------------------------------------------------------------------------\n\nexport async function fetchBalance(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<BalanceResult> {\n const [coins, positions, rewards, pools] = await Promise.all([\n callNaviWithRetry(manager, NaviTools.GET_COINS, { address }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }, opts),\n callNaviWithRetry(manager, NaviTools.GET_AVAILABLE_REWARDS, { address }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POOLS, {}, opts),\n ]);\n\n const rates = transformRates(pools);\n const prices: Record<string, number> = {};\n for (const [symbol, rate] of Object.entries(rates)) {\n prices[symbol] = rate.price;\n }\n\n return transformBalance(coins, positions, rewards, prices);\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: savings info (positions + pool APYs)\n// ---------------------------------------------------------------------------\n\nexport async function fetchSavings(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<SavingsResult> {\n const key = naviKey.savings(address);\n if (!opts?.skipCache) {\n const cached = await cacheGet<SavingsResult>(key);\n if (cached) return cached;\n }\n\n const [positions, pools] = await Promise.all([\n callNaviWithRetry(manager, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POOLS, {}, opts),\n ]);\n\n const result = transformSavings(positions, pools);\n await cacheSet(key, result, NAVI_ADDR_TTL_SEC);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: positions only\n// ---------------------------------------------------------------------------\n\nexport async function fetchPositions(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions & { protocols?: string },\n): Promise<PositionEntry[]> {\n const raw = await callNaviWithRetry(\n manager,\n NaviTools.GET_POSITIONS,\n { address, protocols: opts?.protocols ?? 'navi', format: 'json' },\n opts,\n );\n return transformPositions(raw);\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: available rewards\n// ---------------------------------------------------------------------------\n\nexport async function fetchAvailableRewards(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<PendingReward[]> {\n const raw = await callNaviWithRetry(\n manager,\n NaviTools.GET_AVAILABLE_REWARDS,\n { address },\n opts,\n );\n return transformRewards(raw);\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: protocol stats\n// ---------------------------------------------------------------------------\n\nexport interface ProtocolStats {\n tvl: number;\n totalBorrowUsd: number;\n utilization: number;\n maxApy: number;\n totalUsers: number;\n}\n\nexport async function fetchProtocolStats(\n manager: McpClientManager,\n opts?: NaviReadOptions,\n): Promise<ProtocolStats> {\n const raw = await callNaviWithRetry<{\n tvl?: number;\n totalBorrowUsd?: number;\n averageUtilization?: number;\n maxApy?: number;\n userAmount?: number;\n }>(manager, NaviTools.GET_PROTOCOL_STATS, {}, opts);\n\n return {\n tvl: raw?.tvl ?? 0,\n totalBorrowUsd: raw?.totalBorrowUsd ?? 0,\n utilization: raw?.averageUtilization ?? 0,\n maxApy: raw?.maxApy ?? 0,\n totalUsers: raw?.userAmount ?? 0,\n };\n}\n","import { z } from 'zod';\nimport { fetchSavings } from '../navi-reads.js';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, requireAgent } from './utils.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { PositionEntry, SavingsResult } from '../navi-transforms.js';\nimport type { ServerPositionData } from '../types.js';\n\nconst DUST_THRESHOLD_USD = 0.01;\n\nfunction buildSavingsFromPositions(sp: ServerPositionData): SavingsResult {\n const positions: PositionEntry[] = [\n ...sp.supplies\n .filter((s) => s.amountUsd >= DUST_THRESHOLD_USD)\n .map((s) => ({\n protocol: s.protocol,\n type: 'supply' as const,\n symbol: s.asset,\n amount: s.amount,\n valueUsd: s.amountUsd,\n apy: s.apy,\n liquidationThreshold: 0,\n })),\n ...sp.borrows_detail\n .filter((b) => b.amountUsd >= DUST_THRESHOLD_USD)\n .map((b) => ({\n protocol: b.protocol,\n type: 'borrow' as const,\n symbol: b.asset,\n amount: b.amount,\n valueUsd: b.amountUsd,\n apy: b.apy,\n liquidationThreshold: 0,\n })),\n ];\n\n const supplied = sp.savings;\n const weightedApy = supplied > 0 ? sp.savingsRate : 0;\n const dailyEarning = (supplied * weightedApy) / 365;\n\n return {\n positions,\n earnings: {\n totalYieldEarned: 0,\n currentApy: weightedApy,\n dailyEarning,\n supplied,\n },\n fundStatus: {\n supplied,\n apy: weightedApy,\n earnedToday: dailyEarning,\n earnedAllTime: 0,\n projectedMonthly: dailyEarning * 30,\n },\n };\n}\n\nfunction formatSavingsDisplay(\n result: SavingsResult,\n isSelfQuery: boolean = true,\n address?: string,\n suinsName?: string | null,\n): string {\n const { positions, earnings, fundStatus } = result;\n const supplies = positions.filter((p) => p.type === 'supply');\n const borrows = positions.filter((p) => p.type === 'borrow');\n\n const subjectLabel = suinsName ?? (address ? `${address.slice(0, 6)}…${address.slice(-4)}` : null);\n const subjectPrefix = isSelfQuery || !subjectLabel ? '' : `${subjectLabel} — `;\n\n const lines: string[] = [];\n if (supplies.length > 0) {\n lines.push(`${subjectPrefix}Savings: $${fundStatus.supplied.toFixed(2)} at ${(earnings.currentApy * 100).toFixed(2)}% blended APY`);\n for (const s of supplies) {\n lines.push(` ${s.symbol}: ${s.amount.toFixed(s.amount < 1 ? 6 : 2)} ($${s.valueUsd.toFixed(2)}) at ${(s.apy * 100).toFixed(2)}% APY`);\n }\n } else {\n lines.push(`${subjectPrefix}No savings positions.`);\n }\n if (borrows.length > 0) {\n const totalDebt = borrows.reduce((s, b) => s + b.valueUsd, 0);\n lines.push(`Debt: $${totalDebt.toFixed(2)}`);\n }\n lines.push(`Daily earnings: $${fundStatus.earnedToday.toFixed(4)}`);\n lines.push(`Monthly projected: $${fundStatus.projectedMonthly.toFixed(4)}`);\n return lines.join('\\n');\n}\n\nexport const savingsInfoTool = buildTool({\n name: 'savings_info',\n description:\n 'Get detailed savings positions and earnings for the signed-in user OR any public Sui address or SuiNS name: current deposits by protocol, APY, total yield earned, daily earning rate, and projected monthly returns. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v1.5.1] NAVI deposits change on save_deposit / withdraw / claim.\n // Each call reflects a fresh on-chain snapshot — never dedupe.\n cacheable: false,\n\n async call(input, context) {\n /**\n * [v0.49] Address-scope: tool now accepts an optional `address` param\n * so the LLM can inspect any public Sui wallet's NAVI deposits.\n * Pre-v0.49 the tool only ever queried `context.walletAddress`,\n * silently returning the signed-in user's positions for \"How much\n * has funkii saved?\" type questions. Falls back to\n * `context.walletAddress` when the param is absent. Stamps `address`\n * + `isSelfQuery` on the result.\n */\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n if (context.positionFetcher && targetAddress) {\n const sp = await context.positionFetcher(targetAddress);\n const result = buildSavingsFromPositions(sp);\n const stamped = { ...result, address: targetAddress, isSelfQuery, suinsName };\n return { data: stamped, displayText: formatSavingsDisplay(result, isSelfQuery, targetAddress, suinsName) };\n }\n\n if (hasNaviMcpGlobal(context) && targetAddress) {\n const savings = await fetchSavings(getMcpManager(context), targetAddress);\n savings.positions = savings.positions.filter((p) => p.valueUsd >= DUST_THRESHOLD_USD);\n const stamped = { ...savings, address: targetAddress, isSelfQuery, suinsName };\n return { data: stamped, displayText: formatSavingsDisplay(savings, isSelfQuery, targetAddress, suinsName) };\n }\n\n if (\n targetAddress &&\n context.walletAddress &&\n targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()\n ) {\n throw new Error(\n `Cannot inspect ${targetAddress.slice(0, 8)}… without NAVI MCP or a positionFetcher. Configure NAVI MCP to enable third-party address reads.`,\n );\n }\n const agent = requireAgent(context);\n const [posResult, earnings, fundStatus] = await Promise.all([\n agent.positions(),\n agent.earnings(),\n agent.fundStatus(),\n ]);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const positions = (posResult.positions ?? []).map((p: any) => ({\n protocol: (p.protocol ?? 'navi') as string,\n type: p.type === 'borrow' ? ('borrow' as const) : ('supply' as const),\n symbol: ((p.asset ?? p.symbol) ?? 'UNKNOWN') as string,\n amount: (p.amount ?? 0) as number,\n valueUsd: ((p.amountUsd ?? p.valueUsd) ?? 0) as number,\n apy: (p.apy ?? 0) as number,\n liquidationThreshold: (p.liquidationThreshold ?? 0) as number,\n })).filter((p: PositionEntry) => p.valueUsd >= DUST_THRESHOLD_USD);\n\n const result: SavingsResult = {\n positions,\n earnings: {\n totalYieldEarned: earnings.totalYieldEarned,\n currentApy: earnings.currentApy,\n dailyEarning: earnings.dailyEarning,\n supplied: earnings.supplied,\n },\n fundStatus: {\n supplied: fundStatus.supplied,\n apy: fundStatus.apy,\n earnedToday: fundStatus.earnedToday,\n earnedAllTime: fundStatus.earnedAllTime,\n projectedMonthly: fundStatus.projectedMonthly,\n },\n };\n\n const stamped = { ...result, address: targetAddress ?? '', isSelfQuery: true, suinsName };\n return { data: stamped, displayText: formatSavingsDisplay(result, true, undefined, suinsName) };\n },\n});\n","import { z } from 'zod';\nimport { fetchHealthFactor } from '../navi-reads.js';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, requireAgent } from './utils.js';\nimport { normalizeAddressInput } from '../sui-address.js';\n\n/**\n * Anything below this threshold is treated as \"no real debt\" — NAVI can\n * accrue dust between blocks (sub-cent) even after a full repay, and we\n * don't want a $0.000018 phantom borrow flipping the user from \"Healthy\"\n * to \"Warning\" or worse.\n */\nconst DEBT_DUST_USD = 0.01;\n\nfunction hfStatus(hf: number, borrowed: number): string {\n // Zero (or dust-only) debt accounts are maximally safe — math says HF=∞,\n // but the SDK sometimes returns 0 as a sentinel for that case. Treating\n // it as \"critical\" is a pure UI bug (the user has no liquidation risk).\n if (borrowed <= DEBT_DUST_USD) return 'healthy';\n if (hf >= 2.0) return 'healthy';\n if (hf >= 1.5) return 'moderate';\n if (hf >= 1.2) return 'warning';\n return 'critical';\n}\n\n/**\n * Normalise a health factor for transport. JSON.stringify(Infinity) ===\n * \"null\", and the LLM / UI both end up coercing that null to 0, which\n * then renders as the misleading \"Critical 0.00\" status. We therefore\n * collapse any non-finite (or no-debt) value to `null` deliberately so\n * that consumers can branch on `borrowed <= dust || healthFactor == null`\n * to render \"∞\" / \"Healthy\" rather than a misleading numeric value.\n */\nfunction serializeHf(hf: number | null | undefined, borrowed: number): number | null {\n if (borrowed <= DEBT_DUST_USD) return null;\n if (hf == null || !Number.isFinite(hf)) return null;\n return hf;\n}\n\nfunction displayHfText(\n hf: number | null,\n borrowed: number,\n status: string,\n isSelfQuery: boolean = true,\n address?: string,\n suinsName?: string | null,\n): string {\n const subjectLabel = suinsName ?? (address ? `${address.slice(0, 6)}…${address.slice(-4)}` : null);\n const subject = isSelfQuery || !subjectLabel\n ? 'Health Factor'\n : `Health Factor for ${subjectLabel}`;\n if (hf == null) {\n return `${subject}: ∞ (${status} — no debt)`;\n }\n return `${subject}: ${hf.toFixed(2)} (${status})`;\n}\n\nexport const healthCheckTool = buildTool({\n name: 'health_check',\n description:\n 'Check the lending health factor for the signed-in user OR any public Sui address or SuiNS name: current HF ratio, total supplied collateral, total borrowed, max additional borrow capacity, and liquidation threshold. HF < 1.5 is risky, < 1.2 is critical. When the address has no debt the tool returns healthFactor=null (semantically infinity) — render that as \"Healthy\" / ∞, never as 0 or \"Critical\". Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v1.5.1] Health factor changes on every borrow / repay / collateral\n // movement and even passively as oracle prices update. Never dedupe.\n cacheable: false,\n\n async call(input, context) {\n /**\n * [v0.49] Address-scope: tool now accepts an optional `address` param\n * so the LLM can inspect any public Sui wallet's NAVI lending\n * position. Pre-v0.49 the tool only ever queried\n * `context.walletAddress`, which silently returned the signed-in\n * user's HF for \"How is funkii's account health?\" type questions.\n * Falls back to `context.walletAddress` when the param is absent.\n * Stamps `address` + `isSelfQuery` on the result.\n */\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n if (context.positionFetcher && targetAddress) {\n const sp = await context.positionFetcher(targetAddress);\n const borrowed = sp.borrows;\n const rawHf = sp.healthFactor ?? (borrowed > 0 ? 0 : Infinity);\n const status = hfStatus(rawHf, borrowed);\n const transportHf = serializeHf(rawHf, borrowed);\n return {\n data: {\n healthFactor: transportHf,\n supplied: sp.savings,\n borrowed,\n maxBorrow: sp.maxBorrow,\n liquidationThreshold: 0,\n status,\n address: targetAddress,\n isSelfQuery,\n suinsName,\n },\n displayText: displayHfText(transportHf, borrowed, status, isSelfQuery, targetAddress, suinsName),\n };\n }\n\n if (hasNaviMcpGlobal(context) && targetAddress) {\n const hf = await fetchHealthFactor(getMcpManager(context), targetAddress);\n const borrowed = hf.borrowed;\n const status = hfStatus(hf.healthFactor, borrowed);\n const transportHf = serializeHf(hf.healthFactor, borrowed);\n return {\n data: { ...hf, healthFactor: transportHf, status, address: targetAddress, isSelfQuery, suinsName },\n displayText: displayHfText(transportHf, borrowed, status, isSelfQuery, targetAddress, suinsName),\n };\n }\n\n // SDK agent fallback — only meaningful for the signed-in user (the\n // SDK's `healthFactor()` method is bound to the agent's own wallet).\n if (\n targetAddress &&\n context.walletAddress &&\n targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()\n ) {\n throw new Error(\n `Cannot inspect ${targetAddress.slice(0, 8)}… without NAVI MCP or a positionFetcher. Configure NAVI MCP to enable third-party address reads.`,\n );\n }\n const agent = requireAgent(context);\n const hf = await agent.healthFactor();\n const borrowed = hf.borrowed;\n const status = hfStatus(hf.healthFactor, borrowed);\n const transportHf = serializeHf(hf.healthFactor, borrowed);\n\n return {\n data: {\n healthFactor: transportHf,\n supplied: hf.supplied,\n borrowed,\n maxBorrow: hf.maxBorrow,\n liquidationThreshold: hf.liquidationThreshold,\n status,\n address: targetAddress ?? '',\n isSelfQuery: true,\n suinsName,\n },\n displayText: displayHfText(transportHf, borrowed, status, true, undefined, suinsName),\n };\n },\n});\n","import { z } from 'zod';\nimport { fetchRates } from '../navi-reads.js';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, hasAgent, requireAgent } from './utils.js';\n\n// [v1.4 — Day 3] DefiLlama fallback removed. The two upstream tiers\n// (NAVI MCP + SDK agent) cover every authenticated and read-only-system\n// path the harness exercises in production. The Tier 3 DefiLlama lookup\n// was a leftover from when SDK agent rates weren't reliable; the SDK\n// path has been stable for ~v0.45+ and the DefiLlama supply-only payload\n// (no borrow APYs) was already a degraded experience. Honest \"rates\n// unavailable\" is better than a half-correct mark from a deprecated\n// vendor. Audited and accepted as a regression in the Day-3 deletion\n// pass — see AUDRIC_HARNESS_INTELLIGENCE_SPEC_v1.4.1.md.\n\n/**\n * [v0.46.6] Stablecoin allow-list used by the `stableOnly` filter.\n *\n * Lower-cased symbol matching — covers the canonical USDC/USDT family\n * and the Sui-native synthetic stables (USDSUI, USDY, suiUSDT, USDe,\n * AUSD, FDUSD, BUCK). Excludes XAUm (gold-pegged, not USD-pegged) and\n * any LST/LRT.\n */\nconst STABLECOIN_SYMBOLS = new Set<string>([\n 'usdc',\n 'wusdc',\n 'usdt',\n 'wusdt',\n 'suiusdt',\n 'usdy',\n 'usdsui',\n 'usde',\n 'ausd',\n 'fdusd',\n 'buck',\n]);\n\ntype RateMap = Record<string, { saveApy: number; borrowApy: number }>;\n\nfunction isStable(symbol: string): boolean {\n return STABLECOIN_SYMBOLS.has(symbol.toLowerCase());\n}\n\n/**\n * [Bug — 2026-04-28] Token alias expansion for the `assets` filter.\n *\n * NAVI mainnet lists multiple variants for the same underlying asset:\n * - USDT family: `wUSDT` (Wormhole), `suiUSDT` (Sui-native), and the\n * legacy `USDT` Portal symbol.\n * - USDC family: `USDC` (canonical), `wUSDC` (Wormhole legacy).\n * - USDe family: `USDe`, `suiUSDe` (Sui-native).\n *\n * Pre-fix the filter did exact-string lowercase match: a user asking for\n * `usdt` got back nothing because NAVI's pool list returns `suiUSDT`\n * (lowercased: `suiusdt`), not `usdt`. The LLM then hallucinated a\n * factually wrong narration (\"USDT: not actively listed on NAVI\") to\n * explain the empty payload — the worst possible UX.\n *\n * The map is intentionally narrow: only the well-known stablecoin\n * synonyms that the user's mental model treats as \"the same asset\". We\n * do NOT alias e.g. SUI → vSUI / haSUI because those are distinct yield\n * positions with their own APY profiles — collapsing them would HIDE\n * meaningful rate differences.\n */\nconst TOKEN_ALIASES: Record<string, string[]> = {\n usdt: ['usdt', 'wusdt', 'suiusdt'],\n usdc: ['usdc', 'wusdc'],\n usde: ['usde', 'suiusde', 'sui_usde'],\n usdsui: ['usdsui'],\n};\n\nfunction expandAliases(symbols: string[]): Set<string> {\n const out = new Set<string>();\n for (const s of symbols) {\n const norm = s.toLowerCase();\n const aliases = TOKEN_ALIASES[norm] ?? [norm];\n for (const a of aliases) out.add(a);\n }\n return out;\n}\n\nfunction applyFilters(\n rates: RateMap,\n opts: { assets?: string[]; stableOnly?: boolean; topN?: number },\n): RateMap {\n let entries = Object.entries(rates);\n if (opts.assets && opts.assets.length) {\n const wanted = expandAliases(opts.assets);\n entries = entries.filter(([sym]) => wanted.has(sym.toLowerCase()));\n } else if (opts.stableOnly) {\n entries = entries.filter(([sym]) => isStable(sym));\n }\n // Sort by save APY desc so `topN` picks the best yields when no\n // explicit `assets` filter was supplied.\n entries.sort(([, a], [, b]) => b.saveApy - a.saveApy);\n if (opts.topN && opts.topN > 0) {\n entries = entries.slice(0, opts.topN);\n }\n return Object.fromEntries(entries);\n}\n\nfunction formatRatesSummary(rates: RateMap): string {\n return Object.entries(rates)\n .map(([asset, r]) => `${asset}: Save ${(r.saveApy * 100).toFixed(2)}% / Borrow ${(r.borrowApy * 100).toFixed(2)}%`)\n .join(', ');\n}\n\nexport const ratesInfoTool = buildTool({\n name: 'rates_info',\n description:\n '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).',\n inputSchema: z.object({\n assets: z\n .array(z.string())\n .optional()\n .describe('Filter to specific asset symbols (e.g. [\"USDC\"], [\"USDC\",\"USDT\",\"USDSUI\"]). Case-insensitive.'),\n stableOnly: z\n .boolean()\n .optional()\n .describe('When true, return only stablecoin markets (USDC, USDT, USDSUI, USDY, suiUSDT, etc.). Ignored when `assets` is supplied.'),\n topN: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe('Cap the number of rows in the card (default 8). Use 50 to render the full NAVI catalog.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n assets: {\n type: 'array',\n items: { type: 'string' },\n description: 'Filter to specific asset symbols (case-insensitive).',\n },\n stableOnly: {\n type: 'boolean',\n description: 'When true, return only stablecoin markets. Ignored when `assets` is supplied.',\n },\n topN: {\n type: 'number',\n description: 'Cap the number of rows in the card (default 8, max 50).',\n },\n },\n required: [],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const opts = {\n assets: input.assets,\n stableOnly: input.stableOnly,\n topN: input.topN ?? 8,\n };\n\n if (hasNaviMcpGlobal(context)) {\n const all = await fetchRates(getMcpManager(context));\n const filtered = applyFilters(all, opts);\n return { data: filtered, displayText: formatRatesSummary(filtered) };\n }\n\n if (hasAgent(context)) {\n const agent = requireAgent(context);\n const all = await agent.rates();\n const filtered = applyFilters(all, opts);\n return { data: filtered, displayText: formatRatesSummary(filtered) };\n }\n\n // [v1.4 — Day 3] No third tier. Both upstream paths are unavailable\n // — surface that honestly so the LLM can route the user (e.g. \"try\n // again in a moment\") instead of fabricating a number from a\n // deprecated vendor.\n throw new Error(\n 'rates_info: NAVI lending data is currently unavailable. Try again shortly.',\n );\n },\n});\n\n// Exported for testing.\nexport const _internal = { applyFilters, isStable, STABLECOIN_SYMBOLS, expandAliases, TOKEN_ALIASES };\n","import { z } from 'zod';\nimport {\n classifyTransaction,\n extractTransferDetails,\n type ClassifyBalanceChange,\n type TxDirection,\n} from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\nimport { fetchAudricHistory } from '../audric-api.js';\nimport { normalizeAddressInput } from '../sui-address.js';\n\ntype RpcBalanceChange = ClassifyBalanceChange;\n\ninterface RpcTxBlock {\n digest: string;\n timestampMs?: string;\n transaction?: unknown;\n effects?: { gasUsed?: { computationCost: string; storageCost: string; storageRebate: string } };\n balanceChanges?: RpcBalanceChange[];\n}\n\ninterface TxRecord {\n digest: string;\n /**\n * [v1.4] Coarse bucket — one of `'send' | 'lending' | 'swap' |\n * 'transaction'`. Used by the ACI `action` filter and persisted\n * downstream queries depend on these values, so they are STABLE.\n */\n action: string;\n /**\n * [v1.5.3] Finer-grained display label derived from the\n * Move-call function name (e.g. `'deposit'`, `'withdraw'`,\n * `'payment_link'`, `'on-chain'`). Optional — frontends should\n * fall back to `action` when missing. Never used by filters.\n */\n label?: string;\n amount?: number;\n asset?: string;\n recipient?: string;\n /**\n * [v0.46.2] Direction of the user's principal balance change on\n * this tx (`'in'` → user received, `'out'` → user spent). Lets the\n * card render the correct sign without parsing the textual label.\n */\n direction?: TxDirection;\n timestamp: number;\n date?: string;\n gasCost?: number;\n}\n\nfunction parseRpcTx(tx: RpcTxBlock, address: string): TxRecord {\n const gasUsed = tx.effects?.gasUsed;\n const gasCost = gasUsed\n ? (Number(gasUsed.computationCost) + Number(gasUsed.storageCost) - Number(gasUsed.storageRebate)) / 1e9\n : undefined;\n\n const moveCallTargets: string[] = [];\n const commandTypes: string[] = [];\n try {\n /**\n * Sui JSON-RPC `suix_queryTransactionBlocks` returns the\n * ProgrammableTransaction body with the legacy field name\n * `transactions` (plural). Newer SDK-side types refer to the same\n * data as `commands`. Cover both — the v1.5.3 engine path was\n * only checking `commands`, which always returned empty for prod\n * RPC responses, so every row in the transaction history card\n * fell back to `label: 'on-chain'`.\n */\n const data = (tx.transaction as Record<string, unknown>)?.data as Record<string, unknown> | undefined;\n const inner = data?.transaction as Record<string, unknown> | undefined;\n const commands = (inner?.commands ?? inner?.transactions) as Record<string, unknown>[] | undefined;\n if (Array.isArray(commands)) {\n for (const cmd of commands) {\n if (cmd.MoveCall) {\n const mc = cmd.MoveCall as { package: string; module: string; function: string };\n moveCallTargets.push(`${mc.package}::${mc.module}::${mc.function}`);\n commandTypes.push('MoveCall');\n } else if (cmd.TransferObjects) {\n commandTypes.push('TransferObjects');\n }\n }\n }\n } catch { /* best effort */ }\n\n const changes = tx.balanceChanges ?? [];\n const { amount, asset, recipient, direction } = extractTransferDetails(changes, address);\n\n const timestampMs = Number(tx.timestampMs ?? 0);\n const { action, label } = classifyTransaction(moveCallTargets, commandTypes, changes, address);\n\n return {\n digest: tx.digest,\n action,\n label,\n amount,\n asset,\n recipient,\n direction,\n timestamp: timestampMs,\n date: timestampMs > 0 ? new Date(timestampMs).toISOString() : undefined,\n gasCost,\n };\n}\n\n/**\n * RPC query direction. `from` queries `FromAddress` (txs the address sent /\n * signed); `to` queries `ToAddress` (txs the address received). Pre-v0.48\n * the tool only used `from`, which silently dropped pure-receive\n * transactions (someone pays you, no balance-affecting outbound from your\n * account) — so user-reported counts like \"I had 15 txs that day, you\n * showed 13\" lined up with the missing inbound rows. The dual-direction\n * query parallelizes both filters and dedupes by `digest` since txs\n * involving two of the user's own addresses (rare) or self-sends would\n * appear in both result sets.\n */\ntype QueryDirection = 'from' | 'to';\n\nasync function queryHistoryPage(\n rpcUrl: string,\n address: string,\n direction: QueryDirection,\n limit: number,\n cursor: string | null,\n): Promise<{ data: RpcTxBlock[]; nextCursor: string | null; hasNextPage: boolean }> {\n const filter = direction === 'from' ? { FromAddress: address } : { ToAddress: address };\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_queryTransactionBlocks',\n params: [\n { filter, options: { showEffects: true, showInput: true, showBalanceChanges: true } },\n cursor,\n limit,\n true,\n ],\n }),\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!res.ok) throw new Error(`Sui RPC error: ${res.status}`);\n const json = (await res.json()) as {\n result?: { data: RpcTxBlock[]; nextCursor: string | null; hasNextPage: boolean };\n error?: { message: string };\n };\n if (json.error) throw new Error(`RPC error: ${json.error.message}`);\n return {\n data: json.result?.data ?? [],\n nextCursor: json.result?.nextCursor ?? null,\n hasNextPage: json.result?.hasNextPage ?? false,\n };\n}\n\n/**\n * Merge two arrays of RPC txs by `digest`, preserving the most-recent\n * timestamp ordering. Each digest appears at most once in the output.\n */\nfunction mergeAndDedupe(a: RpcTxBlock[], b: RpcTxBlock[]): RpcTxBlock[] {\n const byDigest = new Map<string, RpcTxBlock>();\n for (const tx of [...a, ...b]) {\n if (!byDigest.has(tx.digest)) byDigest.set(tx.digest, tx);\n }\n return [...byDigest.values()].sort((x, y) => Number(y.timestampMs ?? 0) - Number(x.timestampMs ?? 0));\n}\n\nasync function queryHistoryRpc(rpcUrl: string, address: string, limit: number): Promise<TxRecord[]> {\n // Over-fetch each direction by `limit` (Sui RPC caps page size, but most\n // active wallets won't hit it) so the merged set still has at least\n // `limit` rows after dedupe.\n const [fromPage, toPage] = await Promise.all([\n queryHistoryPage(rpcUrl, address, 'from', limit, null).catch(() => ({ data: [] as RpcTxBlock[], nextCursor: null, hasNextPage: false })),\n queryHistoryPage(rpcUrl, address, 'to', limit, null).catch(() => ({ data: [] as RpcTxBlock[], nextCursor: null, hasNextPage: false })),\n ]);\n const merged = mergeAndDedupe(fromPage.data, toPage.data);\n return merged.slice(0, limit).map((tx) => parseRpcTx(tx, address));\n}\n\n/**\n * Paginate backwards through transaction history (both directions in\n * parallel) to find transactions on a specific calendar day. Returns up\n * to `limit` transactions from that day. Each direction stops paginating\n * once it reaches a tx older than `dayStart` — the merge happens at the\n * end so neither direction exits the loop early just because the OTHER\n * direction's page contained newer rows.\n */\nasync function queryHistoryByDate(\n rpcUrl: string,\n address: string,\n targetDate: string,\n limit: number,\n): Promise<TxRecord[]> {\n const target = new Date(targetDate);\n const dayStart = new Date(target.getFullYear(), target.getMonth(), target.getDate()).getTime();\n const dayEnd = dayStart + 86_400_000;\n const MAX_PAGES = 20;\n const PAGE_SIZE = 50;\n\n async function paginateDirection(direction: QueryDirection): Promise<RpcTxBlock[]> {\n const collected: RpcTxBlock[] = [];\n let cursor: string | null = null;\n\n for (let page = 0; page < MAX_PAGES; page++) {\n let res: Awaited<ReturnType<typeof queryHistoryPage>>;\n try {\n res = await queryHistoryPage(rpcUrl, address, direction, PAGE_SIZE, cursor);\n } catch {\n break;\n }\n if (res.data.length === 0) break;\n\n let reachedOld = false;\n for (const tx of res.data) {\n const ts = Number(tx.timestampMs ?? 0);\n if (ts === 0) continue;\n if (ts < dayStart) { reachedOld = true; break; }\n if (ts >= dayStart && ts < dayEnd) collected.push(tx);\n }\n\n if (reachedOld || !res.hasNextPage || !res.nextCursor) break;\n cursor = res.nextCursor;\n }\n return collected;\n }\n\n const [fromTxs, toTxs] = await Promise.all([\n paginateDirection('from'),\n paginateDirection('to'),\n ]);\n const merged = mergeAndDedupe(fromTxs, toTxs);\n return merged.slice(0, limit).map((tx) => parseRpcTx(tx, address));\n}\n\n/**\n * [v1.4 ACI] Allowed values for the `action` filter — kept in sync with\n * `classifyAction` above (the labels it can return).\n */\nconst HISTORY_ACTIONS = ['send', 'lending', 'swap', 'transaction'] as const;\ntype HistoryAction = (typeof HISTORY_ACTIONS)[number];\n\nconst DEFAULT_LOOKBACK_DAYS = 30;\n\n// [v1.2 SuiNS] The local SUI_ADDRESS_REGEX has moved to `sui-address.ts`\n// (canonical normalizer). The Zod schema below accepts both 0x addresses\n// and *.sui names; `normalizeAddressInput` validates and resolves at the\n// top of `call()`.\n\nexport const transactionHistoryTool = buildTool({\n name: 'transaction_history',\n description:\n 'Retrieve recent transaction history (last 30 days by default): sends, saves, withdrawals, borrows, repayments, swaps, and rewards claims. Renders a rich transaction card.\\n\\n' +\n 'By default, queries the SIGNED-IN USER\\'S history. To inspect another wallet (a saved contact, a watched address, any public Sui address), pass `address` — e.g. user asks \"show funkii\\'s recent transactions\" with funkii at 0x40cd…3e62, call with `address: \"0x40cd…3e62\"`. To filter the user\\'s own history to a specific counterparty (user asks \"show transactions WITH funkii\"), pass `counterparty` — keeps the query rooted in the user\\'s wallet but shows only rows where funkii is the recipient or sender.\\n\\n' +\n 'Filter args: `date` (YYYY-MM-DD), `action` (send/lending/swap), `minUsd` (minimum amount in USD — 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 — never re-list the rows in narration.\\n\\n' +\n 'Internally queries both `FromAddress` and `ToAddress` filters in parallel and dedupes by digest, so pure-receive transactions (someone sends to the queried address with no balance-affecting outbound) are no longer dropped.',\n inputSchema: z.object({\n limit: z.number().int().min(1).max(50).optional(),\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (e.g. \"alex.sui\") to query history FOR. When omitted, defaults to the signed-in user\\'s wallet. Pass this when the user asks about a contact\\'s, watched address\\'s, or any other public wallet\\'s history.'),\n counterparty: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (e.g. \"alex.sui\") to filter rows by — only transactions where the queried address sent to or received from this counterparty are returned. Use for \"show transactions with <contact>\" queries. Compares against `tx.recipient` (case-insensitive).'),\n date: z.string().optional().describe('Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day.'),\n action: z.enum(HISTORY_ACTIONS).optional().describe('Filter by action: send, lending, swap, or transaction.'),\n minUsd: z.number().min(0).optional().describe('Minimum transaction amount in USD. Use this for \"transactions over $X\" — the amount is converted to USD using the asset price snapshot.'),\n assetSymbol: z.string().optional().describe('Filter to a single asset symbol (case-insensitive, e.g. \"USDC\", \"SUI\", \"LOFI\"). Matches `tx.asset` exactly.'),\n direction: z.enum(['in', 'out']).optional().describe('Filter by user-side balance flow: \"in\" = received, \"out\" = spent.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n limit: {\n type: 'number',\n description: 'Maximum number of transactions to return (1-50, default 10)',\n },\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui) to query history FOR (defaults to the signed-in user when omitted). The engine resolves SuiNS names to addresses before querying. Use for queries about a contact\\'s, watched address\\'s, or any other wallet\\'s history.',\n },\n counterparty: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui) to filter rows by — only transactions where the queried address sent to or received from this counterparty are returned. Use for \"show transactions with <contact>\" queries.',\n },\n date: {\n type: 'string',\n description: 'Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day.',\n },\n action: {\n type: 'string',\n enum: [...HISTORY_ACTIONS],\n description: 'Filter results by action category: send, lending, swap, or transaction.',\n },\n minUsd: {\n type: 'number',\n description: 'Minimum transaction amount in USD. Use this for \"transactions over $X\" queries.',\n },\n assetSymbol: {\n type: 'string',\n description: 'Filter to a single asset symbol (case-insensitive, e.g. \"USDC\", \"SUI\").',\n },\n direction: {\n type: 'string',\n enum: ['in', 'out'],\n description: 'Filter by direction of user balance change: \"in\" = received, \"out\" = spent.',\n },\n },\n },\n isReadOnly: true,\n maxResultSizeChars: 8_000,\n // [v1.5.1] New transactions land continuously. Even with an explicit\n // `date` filter the dedupe is wrong post-write because the just-\n // executed write may now be in history. Never dedupe.\n cacheable: false,\n /**\n * [v1.5.2] Custom truncation that preserves the structured shape.\n *\n * The default `budgetToolResult` slices the JSON string at the byte\n * limit, appends a \"[Truncated…]\" note, and tries `JSON.parse` — which\n * always fails for sliced JSON, so the engine falls back to returning\n * the raw string. The frontend's `transaction_history` card renderer\n * then sees `typeof data !== 'object'` and bails, so the rich card\n * never renders even though the LLM has the full text.\n *\n * Strategy: progressively halve the `transactions` array until the\n * serialized payload fits, then stamp `_truncated: true` and the\n * original length so the LLM knows to recall with `limit` if it needs\n * older entries. Result is always valid JSON, always object-shaped.\n */\n summarizeOnTruncate(serialized, maxChars) {\n type ParsedHistory = {\n transactions: unknown[];\n count: number;\n [k: string]: unknown;\n };\n let parsed: ParsedHistory;\n try {\n parsed = JSON.parse(serialized) as ParsedHistory;\n } catch {\n return JSON.stringify({\n transactions: [],\n count: 0,\n _truncated: true,\n _note: 'Result exceeded size budget and could not be summarized.',\n });\n }\n const original = Array.isArray(parsed.transactions) ? parsed.transactions : [];\n let trimmed = original.slice();\n let payload = JSON.stringify({ ...parsed, transactions: trimmed, _truncated: true, _originalCount: original.length });\n while (payload.length > maxChars && trimmed.length > 1) {\n trimmed = trimmed.slice(0, Math.max(1, Math.floor(trimmed.length / 2)));\n payload = JSON.stringify({ ...parsed, transactions: trimmed, _truncated: true, _originalCount: original.length });\n }\n return payload;\n },\n\n async call(\n input,\n context,\n ): Promise<{ data: Record<string, unknown>; displayText: string }> {\n const limit = input.limit ?? 10;\n const action = input.action as HistoryAction | undefined;\n const assetSymbol = input.assetSymbol?.toLowerCase();\n const direction = input.direction;\n const minUsd = input.minUsd;\n\n /**\n * [v1.2 SuiNS] Normalize both the primary address and counterparty\n * (each accepts a 0x address OR a *.sui name). Uses `Promise.all`\n * so a SuiNS round-trip on either field doesn't add up serially.\n */\n const [normalizedAddress, normalizedCounterparty] = await Promise.all([\n input.address\n ? normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n })\n : Promise.resolve(null),\n input.counterparty\n ? normalizeAddressInput(input.counterparty, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n })\n : Promise.resolve(null),\n ]);\n\n const suinsName = normalizedAddress?.suinsName ?? null;\n const counterpartySuinsName = normalizedCounterparty?.suinsName ?? null;\n const counterpartyLower = normalizedCounterparty?.address.toLowerCase();\n\n /**\n * Resolve the address whose history we're fetching. Normalized\n * `input.address` (when present) takes precedence; falls back to\n * the signed-in user. Tracking `isSelfQuery` lets the result payload\n * advertise whether the rows belong to the user or a third party,\n * which the frontend card uses to title itself (\"Recent\n * Transactions\" vs \"alex.sui — Recent Transactions\" vs \"0x40cd…3e62\n * — Recent Transactions\") and which the LLM uses to narrate\n * correctly without re-typing the address.\n */\n const targetAddress = normalizedAddress?.address ?? context.walletAddress;\n const isSelfQuery =\n !!targetAddress &&\n !!context.walletAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n /**\n * [v0.46.6] Price snapshot for `minUsd` filtering. Sourced from the\n * session-injected token-price map (populated by the prefetch step\n * in audric's engine-factory). Falls back to \"no USD value known\"\n * when the asset isn't in the snapshot — those rows skip the\n * `minUsd` filter rather than being silently dropped, since we\n * don't have ground truth.\n */\n const prices: Record<string, number> | undefined = (\n context as unknown as { tokenPrices?: Record<string, number> }\n ).tokenPrices;\n const priceFor = (sym: string | undefined): number | undefined => {\n if (!sym || !prices) return undefined;\n return prices[sym.toUpperCase()] ?? prices[sym.toLowerCase()] ?? prices[sym];\n };\n\n /**\n * [v1.4] After fetching, narrow by `action` (when supplied), and trim\n * to a `DEFAULT_LOOKBACK_DAYS` window when no explicit date is given —\n * keeps results recent and bounded so the LLM doesn't over-summarize.\n *\n * [v0.46.6] Now also honors `assetSymbol`, `direction`, and `minUsd`\n * so single questions like \"show transactions over $5\" or \"show my\n * USDC sends\" produce a card whose rows already match the question —\n * the LLM never needs to filter in narration.\n */\n const finalize = (records: TxRecord[]): TxRecord[] => {\n let scoped = records;\n if (action) scoped = scoped.filter((r) => r.action === action);\n if (assetSymbol) {\n scoped = scoped.filter((r) => r.asset?.toLowerCase() === assetSymbol);\n }\n if (direction) {\n scoped = scoped.filter((r) => r.direction === direction);\n }\n if (counterpartyLower) {\n // [v0.48] The `counterparty` filter is intentionally narrow: it\n // matches `tx.recipient` (the parsed counterparty extracted from\n // balance changes by `extractTransferDetails`) — not raw RPC\n // sender/receiver fields, since those reflect signer addresses\n // (often sponsor wallets) rather than the actual fund flow.\n // Rows with no counterparty (e.g. NAVI lending operations against\n // a shared object) are excluded — the user asked \"show\n // transactions with <X>\", and a NAVI deposit isn't with anyone.\n scoped = scoped.filter((r) => r.recipient?.toLowerCase() === counterpartyLower);\n }\n if (minUsd != null && minUsd > 0) {\n scoped = scoped.filter((r) => {\n if (r.amount == null) return false;\n // For USD-pegged assets we treat the unit amount as USD value.\n // For others, multiply by the snapshot price when known.\n const sym = r.asset?.toUpperCase() ?? '';\n const isStableLike =\n sym === 'USDC' || sym === 'USDT' || sym === 'WUSDC' || sym === 'WUSDT' ||\n sym === 'SUIUSDT' || sym === 'USDY' || sym === 'USDSUI' || sym === 'USDE' ||\n sym === 'AUSD' || sym === 'FDUSD' || sym === 'BUCK';\n const usd = isStableLike ? r.amount : (priceFor(sym) ?? 0) * r.amount;\n // When we genuinely don't know the price, KEEP the row rather\n // than silently dropping it — better to over-include than to\n // hide transactions the user expects to see.\n if (!isStableLike && priceFor(sym) == null) return true;\n return usd >= minUsd;\n });\n }\n return scoped.slice(0, limit);\n };\n\n const filterMeta = {\n date: input.date ?? null,\n action: action ?? null,\n minUsd: minUsd ?? null,\n assetSymbol: input.assetSymbol ?? null,\n direction: direction ?? null,\n // Pre-resolved counterparty address (for the LLM/UI). Original\n // SuiNS name is preserved in `counterpartySuinsName` below.\n counterparty: normalizedCounterparty?.address ?? null,\n counterpartySuinsName,\n address: targetAddress ?? null,\n isSelfQuery,\n suinsName,\n };\n\n /**\n * The agent path (used in CLI / SDK direct-tool mode) doesn't\n * support arbitrary-address queries today — the agent's `history()`\n * call is hardwired to its own wallet. Reject explicit `address`\n * usage here rather than silently returning the wrong rows. Callers\n * needing third-party history should use the RPC path (web).\n */\n if (context.agent) {\n if (input.address && !isSelfQuery) {\n throw new Error(\n 'transaction_history `address` parameter is not supported in CLI/SDK agent mode — only the signed-in user\\'s history is available. Use the web client for third-party address queries.',\n );\n }\n const agent = requireAgent(context);\n const records = await agent.history({ limit: input.date ? limit : Math.max(limit * 4, 50) });\n const filtered = finalize(records);\n return {\n data: { transactions: filtered, count: filtered.length, ...filterMeta },\n displayText: `${filtered.length} recent transaction(s)`,\n };\n }\n\n if (!targetAddress) {\n throw new Error('Transaction history requires a wallet address');\n }\n\n // [single-source-of-truth — Apr 2026] Try audric's canonical\n // `/api/history` first. The route already merges FromAddress +\n // ToAddress, dedupes by digest, and runs the same `parseSuiRpcTx`\n // parser the engine uses, so the wire shape is a 1:1 match. Returns\n // null in CLI / MCP / standalone mode → falls through to the\n // existing Sui-RPC path below.\n //\n // Note: the date-paginated path (`input.date`) keeps using direct\n // RPC because audric's `/api/history` doesn't currently expose a\n // date filter. Same goes for the standalone-engine fallback.\n if (!input.date) {\n const audricRecords = await fetchAudricHistory(\n targetAddress,\n { limit: Math.max(limit * 4, 50) },\n context.env,\n context.signal,\n );\n if (audricRecords) {\n const cutoffMs = Date.now() - DEFAULT_LOOKBACK_DAYS * 86_400_000;\n const recent = audricRecords.filter((r) => r.timestamp >= cutoffMs);\n const filtered = finalize(recent);\n return {\n data: {\n transactions: filtered,\n count: filtered.length,\n ...filterMeta,\n lookbackDays: DEFAULT_LOOKBACK_DAYS,\n },\n displayText: `${filtered.length} transaction(s) in the last ${DEFAULT_LOOKBACK_DAYS} days`,\n };\n }\n }\n\n if (!context.suiRpcUrl) {\n throw new Error('Transaction history requires a Sui RPC URL when audric API is unavailable');\n }\n\n if (input.date) {\n const records = await queryHistoryByDate(\n context.suiRpcUrl,\n targetAddress,\n input.date,\n Math.max(limit * 4, 50),\n );\n const filtered = finalize(records);\n const dateLabel = new Date(input.date).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });\n return {\n data: { transactions: filtered, count: filtered.length, ...filterMeta },\n displayText: filtered.length > 0\n ? `${filtered.length} transaction(s) on ${dateLabel}`\n : `No transactions found on ${dateLabel}`,\n };\n }\n\n // No date — last 30 days. Over-fetch then trim by lookback window.\n const cutoffMs = Date.now() - DEFAULT_LOOKBACK_DAYS * 86_400_000;\n const records = await queryHistoryRpc(\n context.suiRpcUrl,\n targetAddress,\n Math.max(limit * 4, 50),\n );\n const recent = records.filter((r) => r.timestamp >= cutoffMs);\n const filtered = finalize(recent);\n return {\n data: {\n transactions: filtered,\n count: filtered.length,\n ...filterMeta,\n lookbackDays: DEFAULT_LOOKBACK_DAYS,\n },\n displayText: `${filtered.length} transaction(s) in the last ${DEFAULT_LOOKBACK_DAYS} days`,\n };\n },\n});\n","import { z } from 'zod';\nimport { assertAllowedAsset } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n// [v0.51.0] Allowed save assets — keep in sync with OPERATION_ASSETS.save in\n// @t2000/sdk. We assert via `assertAllowedAsset('save', ...)` at runtime, but\n// the description + preflight + JSON schema also need to surface the allowed\n// set so the LLM picks correctly without trial-and-error.\nconst SAVE_ASSETS = ['USDC', 'USDsui'] as const;\n\nexport const saveDepositTool = buildTool({\n name: 'save_deposit',\n description:\n 'Deposit USDC or USDsui into NAVI savings to earn yield. ONLY these two stables are accepted. ' +\n 'If the user asks to save/deposit any other token (GOLD, SUI, USDT, USDe, ETH, etc.), do NOT call this tool ' +\n 'and do NOT automatically swap their tokens and deposit. Instead, tell the user that only USDC and USDsui ' +\n 'deposits are supported and ask if they would like to swap first. Let the user decide — never auto-chain ' +\n 'swap + deposit. ' +\n 'When the user says \"save 10 USDC\" pass asset=\"USDC\". When they say \"save 10 USDsui\" pass asset=\"USDsui\". ' +\n 'When they say \"save 10\" with no asset, ALWAYS call balance_check first and ask which stable they want to ' +\n 'deposit (or default to whichever they hold more of, with a one-line note). Never silently substitute USDsui ' +\n 'for USDC or vice versa.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.enum(SAVE_ASSETS).optional().describe('\"USDC\" or \"USDsui\". Defaults to USDC when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n description: 'Exact amount to deposit (in units of the chosen asset)',\n },\n asset: {\n type: 'string',\n enum: ['USDC', 'USDsui'],\n description: 'Stable to deposit. \"USDC\" or \"USDsui\". Defaults to USDC when omitted.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n preflight: (input) => {\n if (input.asset) {\n const allowed = (SAVE_ASSETS as readonly string[]).map((a) => a.toUpperCase());\n if (!allowed.includes(input.asset.toUpperCase())) {\n return { valid: false, error: `Only USDC or USDsui deposits are supported. Got: \"${input.asset}\"` };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n assertAllowedAsset('save', input.asset);\n\n const agent = requireAgent(context);\n // [v0.51.0] Pass asset through — pre-v0.51 the SDK silently rewrote any\n // asset to 'USDC'. The runtime allow-list (assertAllowedAsset above) still\n // gates the input set, so this is safe.\n const asset = (input.asset as 'USDC' | 'USDsui' | undefined) ?? 'USDC';\n const result = await agent.save({ amount: input.amount, asset });\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset,\n apy: result.apy,\n fee: result.fee,\n gasCost: result.gasCost,\n savingsBalance: result.savingsBalance,\n },\n displayText: `Saved ${result.amount.toFixed(result.amount < 1 ? 6 : 2)} ${asset} at ${(result.apy * 100).toFixed(2)}% APY (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const withdrawTool = buildTool({\n name: 'withdraw',\n description:\n 'Withdraw from NAVI lending back to wallet. Defaults to USDC; also withdraws USDsui (the second active saveable stable). Legacy positions in other assets (USDe, SUI) can still be withdrawn if the user has them — but only USDC and USDsui are eligible to be re-deposited via save_deposit.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.string().optional().describe('Asset to withdraw (default: USDC). Active: USDsui. Legacy positions: USDe, SUI.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n description: 'Exact amount to withdraw in token units',\n },\n asset: {\n type: 'string',\n description: 'Asset to withdraw (default: USDC). Active: USDsui. Legacy positions: USDe, SUI.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, affectsHealth: true },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.withdraw({\n amount: input.amount,\n asset: input.asset,\n });\n\n const withdrawnAsset = (result as { asset?: string }).asset ?? input.asset ?? 'USDC';\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset: withdrawnAsset,\n gasCost: result.gasCost,\n },\n displayText: `Withdrew ${result.amount.toFixed(result.amount < 1 ? 6 : 2)} ${withdrawnAsset} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { ALL_NAVI_ASSETS, SUPPORTED_ASSETS, type SupportedAsset } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n/**\n * Tokens send_transfer can move. Mirrors `SUPPORTED_ASSETS` so a new\n * coin in the SDK constants is automatically settable here without\n * touching the tool.\n *\n * The history of this tool: it was originally USDC-only (description\n * literally said \"Send USDC...\"). When the LLM was asked to send a\n * non-USDC token (e.g. just-swapped SUI), it would call send_transfer\n * with the SUI amount, and the tool would silently ship USDC instead —\n * the user lost real money. See the audric-send-safety-and-auth follow-up:\n * \"Done! Swapped 1 USDC for 1.0561 SUI and sent it all to Wallet 1.\" was\n * the LLM's hallucinated success while only USDC actually moved.\n */\nconst ASSET_LIST = ALL_NAVI_ASSETS.map((a) => String(a)).join(', ');\n\nexport const sendTransferTool = buildTool({\n name: 'send_transfer',\n description:\n `Send ANY supported token (${ASSET_LIST}) to another Sui address or contact name. Validates the address, checks balance, and executes the on-chain transfer. ` +\n `MUST set the \\`asset\\` field to the token symbol you want to send (case-insensitive). If \\`asset\\` is omitted, USDC is assumed — only do this when the user explicitly asks for USDC. ` +\n `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. ` +\n `Returns tx hash, gas cost, and updated balance.`,\n inputSchema: z.object({\n to: z.string().min(1),\n amount: z.number().positive(),\n asset: z.string().optional(),\n memo: z.string().optional(),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n to: {\n type: 'string',\n description: 'Sui address (0x…) or saved contact name',\n },\n amount: {\n type: 'number',\n 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.',\n },\n asset: {\n type: 'string',\n 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.`,\n },\n memo: {\n type: 'string',\n description: 'Optional note attached to the transfer (shown in transaction receipt)',\n },\n },\n required: ['to', 'amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true, irreversible: true },\n preflight: (input) => {\n if (input.to.startsWith('0x') && !/^0x[a-fA-F0-9]{64}$/.test(input.to)) {\n return { valid: false, error: `Invalid Sui address format: \"${input.to}\". Must be 0x followed by 64 hex characters.` };\n }\n const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000000000000000000000000000';\n if (input.to === ZERO_ADDRESS) {\n return { valid: false, error: 'This is the zero address (burn address). Sending funds here will permanently destroy them. If you really intend to burn tokens, please confirm explicitly.' };\n }\n if (input.amount <= 0) {\n return { valid: false, error: 'Amount must be positive.' };\n }\n if (input.asset !== undefined) {\n const normalized = String(input.asset).toUpperCase();\n if (!(normalized in SUPPORTED_ASSETS)) {\n return {\n valid: false,\n error: `Unsupported asset \"${input.asset}\". send_transfer accepts: ${ASSET_LIST}.`,\n };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const asset = input.asset\n ? (String(input.asset).toUpperCase() as SupportedAsset)\n : 'USDC';\n const result = await agent.send({ to: input.to, amount: input.amount, asset });\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset,\n to: result.to,\n contactName: result.contactName,\n gasCost: result.gasCost,\n balance: result.balance,\n memo: input.memo ?? null,\n },\n displayText: `Sent ${result.amount} ${asset} to ${result.contactName ?? `${result.to.slice(0, 10)}…`} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { assertAllowedAsset } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n// [v0.51.0] Allowed borrow assets — keep in sync with OPERATION_ASSETS.borrow.\nconst BORROW_ASSETS = ['USDC', 'USDsui'] as const;\n\nexport const borrowTool = buildTool({\n name: 'borrow',\n description:\n 'Borrow USDC or USDsui against savings collateral. ONLY these two stables are supported. ' +\n 'Requires existing savings deposits as collateral. Checks max safe borrow and health factor. ' +\n 'Returns tx hash, fee, asset borrowed, and post-borrow health factor. ' +\n 'When the user says \"borrow 10 USDC\" pass asset=\"USDC\". When they say \"borrow 10 USDsui\" pass asset=\"USDsui\". ' +\n 'When they say \"borrow 10\" with no asset, default to USDC unless the user has only USDsui collateral.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.enum(BORROW_ASSETS).optional().describe('\"USDC\" or \"USDsui\". Defaults to USDC when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n type: 'number',\n description: 'Amount to borrow (in units of the chosen asset)',\n },\n asset: {\n type: 'string',\n enum: ['USDC', 'USDsui'],\n description: 'Stable to borrow. \"USDC\" or \"USDsui\". Defaults to USDC when omitted.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, affectsHealth: true },\n preflight: (input) => {\n if (input.asset) {\n const allowed = (BORROW_ASSETS as readonly string[]).map((a) => a.toUpperCase());\n if (!allowed.includes(input.asset.toUpperCase())) {\n return { valid: false, error: `Only USDC or USDsui borrows are supported. Got: \"${input.asset}\"` };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n assertAllowedAsset('borrow', input.asset);\n\n const agent = requireAgent(context);\n // [v0.51.0] Pass asset through — pre-v0.51 the SDK silently rewrote any\n // asset to 'USDC'. The runtime allow-list (assertAllowedAsset above) still\n // gates the input set, so this is safe.\n const asset = (input.asset as 'USDC' | 'USDsui' | undefined) ?? 'USDC';\n const result = await agent.borrow({ amount: input.amount, asset });\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset: result.asset ?? asset,\n fee: result.fee,\n healthFactor: result.healthFactor,\n gasCost: result.gasCost,\n },\n displayText: `Borrowed ${result.amount.toFixed(2)} ${asset} — HF: ${result.healthFactor.toFixed(2)} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nconst REPAY_ASSETS = ['USDC', 'USDsui'] as const;\n\nexport const repayDebtTool = buildTool({\n name: 'repay_debt',\n description:\n 'Repay outstanding USDC or USDsui debt. Always call balance_check first to know the debt amount + which asset is owed (savings_info shows per-asset borrow positions). ' +\n 'Pass asset=\"USDC\" or asset=\"USDsui\" to target a specific debt. When omitted, repays the highest-APY borrow first. ' +\n 'Important: a USDsui debt MUST be repaid with USDsui (and USDC debt with USDC) — the SDK fetches the correct coin type for the targeted asset, but the user must hold enough of that stable in their wallet. ' +\n 'If the user has only the wrong stable, do NOT auto-swap — tell them to swap manually first. Returns tx hash, amount repaid, asset, and remaining debt.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.enum(REPAY_ASSETS).optional().describe('\"USDC\" or \"USDsui\". When omitted, repays the highest-APY borrow first.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n description: 'Exact amount to repay (in units of the chosen asset; call balance_check first)',\n },\n asset: {\n type: 'string',\n enum: ['USDC', 'USDsui'],\n description: 'Asset of the borrow being repaid. When omitted, picks the highest-APY borrow.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n preflight: (input) => {\n if (input.asset) {\n const allowed = (REPAY_ASSETS as readonly string[]).map((a) => a.toUpperCase());\n if (!allowed.includes(input.asset.toUpperCase())) {\n return { valid: false, error: `Only USDC or USDsui repays are supported. Got: \"${input.asset}\"` };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const asset = input.asset as 'USDC' | 'USDsui' | undefined;\n const result = await agent.repay({ amount: input.amount, asset });\n const repaidAsset = (result as { asset?: string }).asset ?? asset ?? 'USDC';\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset: repaidAsset,\n remainingDebt: result.remainingDebt,\n gasCost: result.gasCost,\n },\n displayText: `Repaid ${result.amount.toFixed(2)} ${repaidAsset} — remaining debt: $${result.remainingDebt.toFixed(2)} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n/**\n * Format an amount with adaptive precision so a 0.0165 vSUI claim\n * doesn't get stringified as \"0.02\" and the LLM can narrate the\n * actual on-chain credit accurately.\n */\nfunction formatAmount(amount: number): string {\n if (!Number.isFinite(amount) || amount <= 0) return '0';\n if (amount >= 1) return amount.toFixed(4).replace(/\\.?0+$/, '');\n if (amount >= 0.0001) return amount.toFixed(6).replace(/\\.?0+$/, '');\n return amount.toExponential(2);\n}\n\nexport const claimRewardsTool = buildTool({\n name: 'claim_rewards',\n description:\n 'Claim all pending protocol rewards across lending adapters. Returns the claimed reward breakdown (per-asset symbol + amount), total USD value (best effort — may be 0 when oracle prices are unavailable), and the on-chain tx hash. When the rewards list is empty the response will explicitly say \"no pending rewards\"; when it is non-empty narrate the per-symbol amounts even if totalValueUsd is 0 (the on-chain credit still happened).',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true },\n\n async call(_input, context) {\n const agent = requireAgent(context);\n const result = await agent.claimRewards();\n\n // The SDK adapter doesn't have access to a price oracle, so\n // `estimatedValueUsd` is always 0 from upstream. The engine, however,\n // has a `priceCache` populated by the harness (symbol → USD), so we\n // enrich here. This means the card / LLM can report \"$0.04 vSUI\"\n // instead of \"$0.00\" whenever a price is known, while still gracefully\n // degrading to per-symbol amounts when it isn't.\n const priceCache = context.priceCache;\n const enrichedRewards = result.rewards.map((r) => {\n if (r.estimatedValueUsd > 0) return r;\n const price = priceCache?.get(r.symbol.toUpperCase());\n if (!price || !Number.isFinite(price) || price <= 0) return r;\n return { ...r, estimatedValueUsd: r.amount * price };\n });\n\n const totalValueUsd = enrichedRewards.reduce(\n (s, r) => s + (Number.isFinite(r.estimatedValueUsd) ? r.estimatedValueUsd : 0),\n 0,\n );\n\n const txShort = result.tx ? `${result.tx.slice(0, 8)}…` : '';\n let displayText: string;\n\n if (enrichedRewards.length === 0) {\n displayText = 'No pending rewards to claim.';\n } else {\n // Always include per-symbol amounts so the narration is grounded\n // in the actual on-chain credit even when USD pricing is missing.\n const breakdown = enrichedRewards\n .map((r) => `${formatAmount(r.amount)} ${r.symbol}`)\n .join(', ');\n const usdSuffix = totalValueUsd > 0 ? ` (~$${totalValueUsd.toFixed(2)})` : '';\n const txSuffix = txShort ? ` (tx: ${txShort})` : '';\n displayText = `Claimed ${breakdown}${usdSuffix}${txSuffix}`;\n }\n\n return {\n data: {\n success: result.success,\n tx: result.tx || null,\n rewards: enrichedRewards,\n totalValueUsd,\n gasCost: result.gasCost,\n },\n displayText,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nconst MPP_GATEWAY = 'https://mpp.t2000.ai';\n\nconst SERVICE_PRICES: [RegExp, number][] = [\n [/\\/fal\\//, 0.03],\n [/\\/googlemaps\\//, 0.01],\n [/\\/perplexity\\//, 0.01],\n [/\\/firecrawl\\//, 0.01],\n [/\\/serpapi\\//, 0.01],\n [/\\/openweather\\//, 0.005],\n [/\\/brave\\//, 0.005],\n [/\\/serper\\//, 0.005],\n [/\\/newsapi\\//, 0.005],\n [/\\/coingecko\\//, 0.005],\n [/\\/alphavantage\\//, 0.005],\n [/\\/exchangerate\\//, 0.005],\n [/\\/deepl\\//, 0.005],\n [/\\/jina\\//, 0.005],\n [/\\/resend\\//, 0.005],\n];\n\nexport function estimatePayApiCost(url: string): number {\n for (const [pattern, price] of SERVICE_PRICES) {\n if (pattern.test(url)) return price;\n }\n return 0.005;\n}\n\nexport const payApiTool = buildTool({\n name: 'pay_api',\n description: `Execute any MPP gateway service via on-chain USDC micropayment. The gateway at ${MPP_GATEWAY} hosts 40+ services (88 endpoints). Payment is handled automatically.\n\nUse mpp_services tool first to discover available services and get the correct endpoint URL, required body parameters, and pricing. Then call this tool with the full URL and JSON body.\n\nAlways use POST. Construct the URL from the gateway base + service path. Pass parameters as a JSON string in body.\n\nCRITICAL — non-retryable errors: If the result contains \"doNotRetry\": true or \"paymentConfirmed\": true, the user has ALREADY been charged. NEVER call pay_api again for the same request. Report the error to the user.\n\nLob (postcards/letters) — MULTI-STEP, NEVER skip:\n1. Generate design image FIRST via fal/fal-ai/flux/dev ($0.03). Show the image to the user as markdown ![design](url).\n2. Ask the user to confirm before mailing (\"Here's the design. Print and mail for $1.00?\").\n3. ONLY after user confirms: call lob/v1/postcards with the image URL in the front HTML (<img src=\"URL\" style=\"width:100%;height:100%;object-fit:cover\"/>).\nAlways use ISO-3166 country codes (GB not UK, US not USA). A return address (\"from\") is added automatically — do not include one.`,\n inputSchema: z.object({\n url: z.string().url(),\n method: z.enum(['GET', 'POST', 'PUT', 'DELETE']).optional(),\n body: z.string().optional(),\n headers: z.record(z.string()).optional(),\n maxPrice: z.number().positive().optional(),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'Full MPP endpoint URL (e.g. https://mpp.t2000.ai/openweather/v1/weather)' },\n method: { type: 'string', description: 'HTTP method (always POST for MPP gateway)' },\n body: { type: 'string', description: 'JSON request body as string' },\n headers: { type: 'object', description: 'Additional HTTP headers' },\n maxPrice: { type: 'number', description: 'Maximum price in USD willing to pay (default: service price)' },\n },\n required: ['url'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true, costAware: true, producesArtifact: true, maxRetries: 1 },\n preflight: (input) => {\n if (!input.url.startsWith(MPP_GATEWAY)) {\n return { valid: false, error: `URL must start with ${MPP_GATEWAY}. Got: \"${input.url}\"` };\n }\n if (input.body) {\n try {\n JSON.parse(input.body);\n } catch {\n return { valid: false, error: 'body must be valid JSON.' };\n }\n if (input.url.includes('lob/')) {\n const body = JSON.parse(input.body) as Record<string, unknown>;\n const to = body.to as Record<string, unknown> | undefined;\n const country = to?.address_country;\n if (typeof country === 'string' && country.length !== 2) {\n return { valid: false, error: `Country must be ISO-3166 2-letter code (got \"${country}\")` };\n }\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.pay({\n url: input.url,\n method: input.method,\n body: input.body,\n headers: input.headers,\n maxPrice: input.maxPrice,\n });\n\n return {\n data: {\n status: result.status,\n body: result.body,\n paid: result.paid,\n cost: result.cost,\n receipt: result.receipt,\n },\n displayText: result.paid\n ? `API call completed — paid $${result.cost?.toFixed(4) ?? '?'} (status: ${result.status})`\n : `API call completed — free (status: ${result.status})`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst MPP_GATEWAY = 'https://mpp.t2000.ai';\nconst CATALOG_URL = `${MPP_GATEWAY}/api/services`;\nconst CACHE_TTL = 120_000;\n\ninterface GatewayEndpoint {\n method: string;\n path: string;\n description: string;\n price: string;\n}\n\ninterface GatewayService {\n id: string;\n name: string;\n serviceUrl: string;\n description: string;\n categories: string[];\n endpoints: GatewayEndpoint[];\n}\n\nlet catalogCache: { data: GatewayService[]; ts: number } | null = null;\n\nasync function fetchCatalog(): Promise<GatewayService[]> {\n if (catalogCache && Date.now() - catalogCache.ts < CACHE_TTL) {\n return catalogCache.data;\n }\n const res = await fetch(CATALOG_URL, { signal: AbortSignal.timeout(10_000) });\n if (!res.ok) throw new Error(`MPP catalog fetch failed: HTTP ${res.status}`);\n const data = (await res.json()) as GatewayService[];\n catalogCache = { data, ts: Date.now() };\n return data;\n}\n\nfunction renderServices(catalog: GatewayService[]) {\n return catalog.map((s) => ({\n id: s.id,\n name: s.name,\n description: s.description,\n categories: s.categories,\n endpoints: s.endpoints.map((e) => ({\n url: `${MPP_GATEWAY}/${s.id}${e.path}`,\n method: e.method,\n description: e.description,\n price: `$${e.price}`,\n })),\n }));\n}\n\nfunction matchesQuery(service: GatewayService, q: string): boolean {\n const lower = q.toLowerCase();\n return (\n service.id.toLowerCase().includes(lower) ||\n service.name.toLowerCase().includes(lower) ||\n service.description.toLowerCase().includes(lower) ||\n service.categories.some((c) => c.toLowerCase().includes(lower)) ||\n service.endpoints.some((e) => e.description.toLowerCase().includes(lower))\n );\n}\n\nexport const mppServicesTool = buildTool({\n name: 'mpp_services',\n description:\n 'Discover available MPP gateway services. Returns service names, descriptions, endpoints with required parameters, and pricing. Use BEFORE calling pay_api. With no args, returns the FULL catalog as a single card (default behavior — covers \"show me available MPP services\", \"what services exist\", \"show me all MPP services\"). Use `query` to keyword-search a specific need (\"translate\", \"weather\", \"postcard\"). Use `category` to filter to one category. Use `mode: \"summary\"` only if you explicitly want a category-counts overview without the full list.',\n inputSchema: z.object({\n query: z\n .string()\n .optional()\n .describe('Filter by keyword (e.g. \"postcard\", \"translate\", \"weather\"). Returns matching services in one card.'),\n category: z\n .string()\n .optional()\n .describe('Filter by category exactly (e.g. \"weather\", \"image\"). Use mode:\"summary\" first if you need to see the category list.'),\n mode: z\n .enum(['summary', 'full'])\n .optional()\n .describe('\"full\" (default) returns the entire catalog in one card. \"summary\" returns category counts only — use this only when the user explicitly asks for a category overview.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Filter by keyword (e.g. \"postcard\", \"translate\", \"weather\").',\n },\n category: {\n type: 'string',\n description: 'Filter by category exactly (e.g. \"weather\", \"image\").',\n },\n mode: {\n type: 'string',\n enum: ['summary', 'full'],\n description: '\"full\" (default) returns the entire catalog in one card. \"summary\" returns category counts only.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v0.46.6] Bumped to fit the full catalog (~40 services) in one\n // shot when `mode: 'full'` is used. The summarizeOnTruncate path\n // still applies if the catalog ever exceeds the budget.\n maxResultSizeChars: 12_000,\n\n async call(input): Promise<{ data: Record<string, unknown>; displayText: string }> {\n const catalog = await fetchCatalog();\n\n // [v0.46.7] Default behavior is now \"return the full catalog as a card.\"\n // Previously no-args returned a `_refine` payload that nudged the model to\n // re-call with a category — but in practice the model often re-called with\n // a category that returned 0 services, leaving an empty card. The full\n // catalog is small (~40 services, ~10KB) and fits comfortably in the\n // result budget, so there's no real cost to making it the default.\n //\n // The \"summary\" path (category counts only) is still available via the\n // explicit `mode:'summary'` opt-in for the rare case the user really wants\n // a category overview rather than the full list.\n if (input.mode !== 'summary' && !input.query && !input.category) {\n const services = renderServices(catalog);\n return {\n data: { services, total: services.length, mode: 'full' },\n displayText: `Full MPP catalog: ${services.length} services.`,\n };\n }\n\n if (input.mode === 'summary' && !input.query && !input.category) {\n const counts = new Map<string, number>();\n for (const svc of catalog) {\n for (const cat of svc.categories) {\n counts.set(cat, (counts.get(cat) ?? 0) + 1);\n }\n }\n const categories = [...counts.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([category, services]) => ({ category, services }));\n return {\n data: {\n _refine: {\n reason: 'Category summary (mode:\"summary\"). Re-call with a category or omit mode for the full catalog.',\n suggestedParams: { category: categories[0]?.category ?? 'weather' },\n allModes: ['summary', 'full'],\n },\n categories,\n totalServices: catalog.length,\n },\n displayText: `${catalog.length} services across ${categories.length} categories.`,\n };\n }\n\n let filtered = catalog;\n if (input.category) {\n const cat = input.category.toLowerCase();\n filtered = filtered.filter((s) => s.categories.some((c) => c.toLowerCase() === cat));\n }\n if (input.query) {\n filtered = filtered.filter((s) => matchesQuery(s, input.query!));\n }\n\n const services = renderServices(filtered);\n\n const filterDesc = [\n input.query ? `query \"${input.query}\"` : null,\n input.category ? `category \"${input.category}\"` : null,\n ].filter(Boolean).join(' + ');\n const summary = `Found ${services.length} service(s) matching ${filterDesc}`;\n\n return {\n data: { services, total: services.length },\n displayText: summary,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const swapExecuteTool = buildTool({\n name: 'swap_execute',\n description:\n 'Swap tokens on Sui via Cetus Aggregator (20+ DEXs). Supports any token pair with liquidity. Use user-friendly names (SUI, USDC, CETUS, DEEP, etc.) or full coin types.',\n inputSchema: z.object({\n from: z.string().describe('Source token (e.g. \"SUI\", \"USDC\", or full coin type)'),\n to: z.string().describe('Target token (e.g. \"USDC\", \"CETUS\", or full coin type)'),\n amount: z.number().positive().describe('Amount to swap'),\n byAmountIn: z.boolean().optional().describe('true = fixed input amount (default), false = fixed output amount'),\n slippage: z.number().min(0.001).max(0.05).optional().describe('Max slippage (default 0.01 = 1%, max 5%)'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n from: { type: 'string', description: 'Source token name or coin type' },\n to: { type: 'string', description: 'Target token name or coin type' },\n amount: { type: 'number', description: 'Amount to swap' },\n byAmountIn: { type: 'boolean', description: 'true = fixed input (default), false = fixed output' },\n slippage: { type: 'number', description: 'Max slippage (0.01 = 1%)' },\n },\n required: ['from', 'to', 'amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n preflight: (input) => {\n if (input.from.toLowerCase() === input.to.toLowerCase()) {\n return { valid: false, error: `Cannot swap ${input.from} to itself.` };\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.swap({\n from: input.from,\n to: input.to,\n amount: input.amount,\n byAmountIn: input.byAmountIn,\n slippage: input.slippage,\n });\n\n return {\n data: {\n tx: result.tx,\n fromToken: result.fromToken,\n toToken: result.toToken,\n fromAmount: result.fromAmount,\n toAmount: result.toAmount,\n priceImpact: result.priceImpact,\n route: result.route,\n gasCost: result.gasCost,\n },\n displayText: `Swapped ${result.fromAmount} ${result.fromToken} for ${result.toAmount.toFixed(4)} ${result.toToken} (tx: ${result.tx.slice(0, 8)}...)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { getSwapQuote } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { getWalletAddress } from './utils.js';\n\nexport const swapQuoteTool = buildTool({\n name: 'swap_quote',\n description:\n 'Get a swap quote without executing. Shows expected output amount, price impact, and route. Use before swap_execute to preview a trade.',\n inputSchema: z.object({\n from: z.string().describe('Source token (e.g. \"SUI\", \"USDC\", or full coin type)'),\n to: z.string().describe('Target token (e.g. \"USDC\", \"CETUS\", or full coin type)'),\n amount: z.number().positive().describe('Amount to swap'),\n byAmountIn: z.boolean().optional().describe('true = fixed input (default), false = fixed output'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n from: { type: 'string', description: 'Source token name or coin type' },\n to: { type: 'string', description: 'Target token name or coin type' },\n amount: { type: 'number', description: 'Amount to swap' },\n byAmountIn: { type: 'boolean', description: 'true = fixed input (default), false = fixed output' },\n },\n required: ['from', 'to', 'amount'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const walletAddress = context.agent\n ? (context.agent as { address(): string }).address()\n : getWalletAddress(context);\n\n const result = await getSwapQuote({\n walletAddress,\n from: input.from,\n to: input.to,\n amount: input.amount,\n byAmountIn: input.byAmountIn,\n });\n\n return {\n data: result,\n displayText: `${result.fromAmount} ${result.fromToken} → ${result.toAmount.toFixed(4)} ${result.toToken} (impact: ${(result.priceImpact * 100).toFixed(2)}%, via ${result.route})`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const voloStakeTool = buildTool({\n name: 'volo_stake',\n description:\n 'Stake SUI for vSUI via VOLO liquid staking. Earn ~3-5% APY. Rewards compound automatically via exchange rate — no claiming needed. Minimum 1 SUI.',\n inputSchema: z.object({\n amount: z.number().min(1).describe('Amount of SUI to stake (minimum 1)'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { type: 'number', description: 'Amount of SUI to stake' },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.stakeVSui({ amount: input.amount });\n\n return {\n data: {\n tx: result.tx,\n amountSui: result.amountSui,\n vSuiReceived: result.vSuiReceived,\n apy: result.apy,\n gasCost: result.gasCost,\n },\n displayText: `Staked ${result.amountSui} SUI for ${result.vSuiReceived.toFixed(4)} vSUI at ${(result.apy * 100).toFixed(2)}% APY (tx: ${result.tx.slice(0, 8)}...)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const voloUnstakeTool = buildTool({\n name: 'volo_unstake',\n description:\n 'Unstake vSUI back to SUI. Returns SUI including accumulated yield. Use amount in vSUI units or \"all\" to unstake entire position.',\n inputSchema: z.object({\n amount: z.union([z.number().positive(), z.literal('all')]).describe('Amount of vSUI to unstake, or \"all\"'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { description: 'Amount of vSUI to unstake, or the string \"all\"' },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.unstakeVSui({ amount: input.amount });\n\n return {\n data: {\n tx: result.tx,\n vSuiAmount: result.vSuiAmount,\n suiReceived: result.suiReceived,\n gasCost: result.gasCost,\n },\n displayText: `Unstaked ${result.vSuiAmount.toFixed(4)} vSUI, received ${result.suiReceived.toFixed(4)} SUI (tx: ${result.tx.slice(0, 8)}...)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst VOLO_STATS_URL = 'https://open-api.naviprotocol.io/api/volo/stats';\n\nexport const voloStatsTool = buildTool({\n name: 'volo_stats',\n description:\n 'Get current VOLO liquid staking stats: vSUI APY, exchange rate, total staked SUI, and total vSUI supply.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {} },\n isReadOnly: true,\n\n async call() {\n const res = await fetch(VOLO_STATS_URL);\n if (!res.ok) throw new Error(`VOLO API returned ${res.status}`);\n\n const json = (await res.json()) as Record<string, unknown>;\n const data = (json.data ?? json) as {\n apy?: number;\n exchange_rate?: number;\n exchangeRate?: number;\n total_staked?: number;\n totalStaked?: number;\n total_vsui?: number;\n totalVSui?: number;\n };\n\n const stats = {\n apy: data.apy ?? 0,\n exchangeRate: data.exchange_rate ?? data.exchangeRate ?? 0,\n totalStaked: data.total_staked ?? data.totalStaked ?? 0,\n totalVSui: data.total_vsui ?? data.totalVSui ?? 0,\n };\n\n return {\n data: stats,\n displayText: `vSUI APY: ${(stats.apy * 100).toFixed(2)}%, Rate: 1 SUI = ${(1 / stats.exchangeRate).toFixed(4)} vSUI, Total staked: ${stats.totalStaked.toLocaleString()} SUI`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nexport const saveContactTool = buildTool({\n name: 'save_contact',\n description:\n 'Save a contact with a friendly name and Sui address so the user can send to them by name later.',\n inputSchema: z.object({\n name: z.string().describe('Friendly name for the contact (e.g. \"Alex\", \"Mom\")'),\n address: z.string().describe('Full Sui address (0x...)'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Friendly name for the contact' },\n address: { type: 'string', description: 'Full Sui address (0x...)' },\n },\n required: ['name', 'address'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n\n async call(input) {\n return {\n data: { saved: true, name: input.name, address: input.address },\n displayText: `Saved contact \"${input.name}\" (${input.address.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst BRAVE_API = 'https://api.search.brave.com/res/v1/web/search';\n\nconst inputSchema = z.object({\n query: z.string().describe('Search query'),\n count: z.number().optional().default(5).describe('Number of results (1-10)'),\n});\n\ninterface SearchResult {\n title: string;\n url: string;\n description: string;\n}\n\ninterface WebSearchData {\n results: SearchResult[];\n error?: string;\n}\n\nexport const webSearchTool = buildTool({\n name: 'web_search',\n description:\n 'Search the web for real-time information. Use for news, token info, project details, protocol documentation, or any question that needs current web data. Free for users.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Search query' },\n count: { type: 'number', description: 'Number of results (1-10)', default: 5 },\n },\n required: ['query'],\n },\n isReadOnly: true,\n maxResultSizeChars: 8_000,\n async call(input, context): Promise<{ data: WebSearchData; displayText: string }> {\n // [PR-B2] Hosts MUST pass `BRAVE_API_KEY` through `ToolContext.env`.\n // Direct `process.env` reads are banned in apps consuming the engine\n // (env-validation-gate.mdc) — the engine respects that contract by\n // routing every external secret through the typed context only.\n const apiKey = context.env?.BRAVE_API_KEY;\n if (!apiKey) {\n return {\n data: { results: [], error: 'Web search not configured' },\n displayText: 'Web search is not available.',\n };\n }\n\n const count = Math.min(Math.max(input.count ?? 5, 1), 10);\n const url = `${BRAVE_API}?q=${encodeURIComponent(input.query)}&count=${count}&text_decorations=false`;\n\n const res = await fetch(url, {\n headers: {\n 'Accept': 'application/json',\n 'Accept-Encoding': 'gzip',\n 'X-Subscription-Token': apiKey,\n },\n signal: AbortSignal.timeout(8_000),\n });\n\n if (!res.ok) {\n throw new Error(`Brave Search API error: HTTP ${res.status}`);\n }\n\n const json = await res.json() as {\n web?: { results?: Array<{ title: string; url: string; description: string }> };\n };\n\n const results: SearchResult[] = (json.web?.results ?? []).slice(0, count).map((r) => ({\n title: r.title,\n url: r.url,\n description: r.description,\n }));\n\n const displayText = results.length > 0\n ? results.map((r, i) => `${i + 1}. ${r.title}\\n ${r.url}\\n ${r.description}`).join('\\n\\n')\n : 'No results found.';\n\n return { data: { results }, displayText };\n },\n});\n","import { z } from 'zod';\nimport { getDecimalsForCoinType, resolveSymbol } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\n\nconst inputSchema = z.object({\n digest: z.string().describe('Sui transaction digest to explain'),\n});\n\ninterface TxEffect {\n type: string;\n description: string;\n}\n\ninterface ExplainedTx {\n digest: string;\n sender: string;\n status: string;\n gasUsed: string;\n timestamp?: string;\n effects: TxEffect[];\n summary: string;\n}\n\nexport const explainTxTool = buildTool({\n name: 'explain_tx',\n description:\n 'Explain a Sui transaction in plain English. Provide a transaction digest and get a human-readable breakdown of what happened — transfers, swaps, deposits, etc.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n digest: { type: 'string', description: 'Sui transaction digest' },\n },\n required: ['digest'],\n },\n isReadOnly: true,\n async call(input, context) {\n const rpcUrl = context.suiRpcUrl ?? 'https://fullnode.mainnet.sui.io:443';\n\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'sui_getTransactionBlock',\n params: [\n input.digest,\n {\n showInput: true,\n showEffects: true,\n showEvents: true,\n showBalanceChanges: true,\n showObjectChanges: true,\n },\n ],\n }),\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!res.ok) throw new Error(`Sui RPC error: HTTP ${res.status}`);\n const json = await res.json() as { result?: Record<string, unknown>; error?: { message: string } };\n\n if (json.error) throw new Error(json.error.message);\n if (!json.result) throw new Error('Transaction not found');\n\n const tx = json.result;\n const txInput = tx.transaction as Record<string, unknown> | undefined;\n const effects = tx.effects as Record<string, unknown> | undefined;\n const balanceChanges = tx.balanceChanges as Array<{ owner: Record<string, string>; coinType: string; amount: string }> | undefined;\n const events = tx.events as Array<{ type: string; parsedJson?: Record<string, unknown> }> | undefined;\n\n const txData = txInput?.data as Record<string, unknown> | undefined;\n const sender = txData?.sender as string ?? 'unknown';\n const gasData = txData?.gasData as Record<string, unknown> | undefined;\n const gasPayer = gasData?.owner as string ?? sender;\n const status = (effects?.status as Record<string, string>)?.status ?? 'unknown';\n const gasUsed = effects?.gasUsed as Record<string, string> | undefined;\n const gasCost = gasUsed\n ? (Number(gasUsed.computationCost ?? 0) + Number(gasUsed.storageCost ?? 0) - Number(gasUsed.storageRebate ?? 0)) / 1e9\n : 0;\n const timestamp = tx.timestampMs ? new Date(Number(tx.timestampMs)).toISOString() : undefined;\n\n const txEffects: TxEffect[] = [];\n\n if (balanceChanges?.length) {\n for (const bc of balanceChanges) {\n const ownerAddr = bc.owner?.AddressOwner ?? bc.owner?.ObjectOwner ?? 'unknown';\n // Use the canonical token registry so user-facing symbols are\n // friendly (e.g. `0x...::cert::CERT` → `vSUI`). Falls back to the\n // last `::` segment when the coin isn't in the registry.\n const symbol = resolveSymbol(bc.coinType);\n const amount = Number(bc.amount);\n const isNegative = amount < 0;\n const decimals = getDecimalsForCoinType(bc.coinType);\n const absHuman = Math.abs(amount / 10 ** decimals);\n\n if (bc.coinType.endsWith('::sui::SUI') && isNegative) {\n if (ownerAddr === gasPayer) {\n const netTransfer = absHuman - gasCost;\n if (netTransfer < 0.0001) continue;\n txEffects.push({\n type: 'send',\n description: `${ownerAddr.slice(0, 8)}...${ownerAddr.slice(-4)} sent ${netTransfer.toFixed(4)} ${symbol}`,\n });\n } else {\n txEffects.push({\n type: 'send',\n description: `${ownerAddr.slice(0, 8)}...${ownerAddr.slice(-4)} sent ${absHuman.toFixed(4)} ${symbol}`,\n });\n }\n continue;\n }\n\n txEffects.push({\n type: isNegative ? 'send' : 'receive',\n description: `${ownerAddr.slice(0, 8)}...${ownerAddr.slice(-4)} ${isNegative ? 'sent' : 'received'} ${absHuman.toFixed(decimals > 6 ? 4 : 2)} ${symbol}`,\n });\n }\n }\n\n if (events?.length) {\n for (const evt of events.slice(0, 5)) {\n const eventParts = evt.type.split('::');\n const eventName = eventParts[eventParts.length - 1] ?? evt.type;\n txEffects.push({\n type: 'event',\n description: `Event: ${eventName}`,\n });\n }\n }\n\n const summary = txEffects.length > 0\n ? txEffects.filter((e) => e.type !== 'event').map((e) => e.description).join('; ')\n : `Transaction ${status}`;\n\n const result: ExplainedTx = {\n digest: input.digest,\n sender,\n status,\n gasUsed: `${gasCost.toFixed(6)} SUI`,\n timestamp,\n effects: txEffects,\n summary,\n };\n\n return {\n data: result,\n displayText: `**Tx ${input.digest.slice(0, 8)}...** (${status})\\nSender: ${sender}\\nGas: ${result.gasUsed}\\n${summary}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport {\n fetchAddressPortfolio,\n fetchAddressDefiPortfolio,\n type AddressPortfolio,\n type DefiSummary,\n} from '../blockvision-prices.js';\nimport { fetchAudricPortfolio } from '../audric-api.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { ServerPositionData } from '../types.js';\n\nconst inputSchema = z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui) to analyze. Defaults to the signed-in wallet when omitted.'),\n});\n\ninterface AssetAllocation {\n symbol: string;\n amount: number;\n usdValue: number;\n percentage: number;\n}\n\ninterface PortfolioInsight {\n type: 'info' | 'warning' | 'suggestion';\n message: string;\n}\n\ninterface WeekChange {\n absoluteUsd: number;\n percentChange: number;\n}\n\ninterface PortfolioResult {\n totalValue: number;\n walletValue: number;\n savingsValue: number;\n /**\n * [Bug — 2026-04-28] Aggregated DeFi value across non-NAVI protocols\n * (Cetus LPs, Bluefin, Suilend, etc.) — same field that's been on\n * `balance_check` since v0.50. Pre-fix this tool ignored DeFi entirely:\n * a wallet with $1,569 in Cetus LPs reported a $228 totalValue\n * (wallet only), under-counting net worth by 87% and prompting the LLM\n * to misclassify the wallet as \"concentrated in FAITH\" when actually\n * the bulk was in liquidity pools. Same SSOT-divergence class the v0.54\n * cache work fixed for FullPortfolioCanvas, manifesting in a different\n * tool that was written before DeFi support was bolted on.\n */\n defiValue: number;\n /** Provenance of the DeFi read — used by the UI card to caveat partial/degraded. */\n defiSource: DefiSummary['source'];\n debtValue: number;\n healthFactor: number | null;\n allocations: AssetAllocation[];\n stablePercentage: number;\n insights: PortfolioInsight[];\n savingsApy?: number;\n dailyEarning?: number;\n weekChange?: WeekChange;\n priceSource: AddressPortfolio['source'];\n /** Resolved on-chain address (post SuiNS normalization). */\n address?: string;\n /** True when the resolved address matches the signed-in wallet. */\n isSelfQuery?: boolean;\n /**\n * Original SuiNS name when the user passed `address: \"alex.sui\"`,\n * otherwise null. Host cards use this to title the result with the\n * human-readable name instead of the truncated 0x address.\n */\n suinsName?: string | null;\n}\n\nconst STABLECOINS = new Set(['USDC', 'USDT', 'USDe', 'USDsui']);\n\nexport const portfolioAnalysisTool = buildTool({\n name: 'portfolio_analysis',\n description:\n 'Analyze portfolio allocation, risk exposure, and yield optimization for the signed-in user OR any public Sui address or SuiNS name. Shows asset breakdown, diversification score, health factor assessment, and actionable suggestions. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to analyze a contact / watched / public wallet.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n async call(input, context) {\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let address: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n address = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n address = context.walletAddress;\n }\n if (!address) {\n throw new Error('No wallet address provided. Sign in first.');\n }\n\n const DUST_USD = 0.01;\n\n // [single-source-of-truth — Apr 2026] Try audric's canonical\n // `/api/portfolio` first. When it returns a snapshot we already have\n // wallet + positions in one call so we skip the parallel BV +\n // positionFetcher fan-out below.\n const audricSnapshot = await fetchAudricPortfolio(\n address,\n context.env,\n context.signal,\n );\n\n // [v1.4 BlockVision] Fan out parallel fetches: BlockVision portfolio\n // (coins + balances + USD prices in one shot), positions (host\n // fetcher), 7-day portfolio history, AND non-NAVI DeFi positions\n // (Cetus/Bluefin/Suilend/etc.). Total wall time is bound by the\n // slowest. Re-uses the per-request portfolio cache so a sibling\n // `balance_check` in the same turn shares the response.\n //\n // [Bug — 2026-04-28] DeFi is now a first-class fetch: the audric\n // snapshot path uses the value the audric host already computed\n // (single source of truth), the standalone path falls back to a\n // direct fetchAddressDefiPortfolio call. This closes the gap where\n // portfolio_analysis ignored the $1,569 in Cetus LPs that\n // balance_check reported correctly.\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n const [portfolio, positions, weekHistResult, defiSummary]: [\n AddressPortfolio,\n ServerPositionData | null,\n { change?: WeekChange } | null,\n DefiSummary,\n ] = await Promise.all([\n audricSnapshot\n ? Promise.resolve(audricSnapshot.portfolio)\n : (async () => {\n if (context.portfolioCache) {\n const hit = context.portfolioCache.get(address);\n if (hit) return hit;\n }\n const fresh = await fetchAddressPortfolio(\n address,\n context.blockvisionApiKey,\n context.suiRpcUrl,\n { retryStats: context.retryStats },\n );\n context.portfolioCache?.set(address, fresh);\n return fresh;\n })().catch((err): AddressPortfolio => {\n console.warn('[portfolio_analysis] portfolio fetch failed:', err);\n return {\n coins: [],\n totalUsd: 0,\n pricedAt: Date.now(),\n source: 'sui-rpc-degraded',\n };\n }),\n audricSnapshot\n ? Promise.resolve(audricSnapshot.positions)\n : context.positionFetcher\n ? context.positionFetcher(address).catch((err) => {\n console.warn('[portfolio_analysis] positionFetcher failed:', err);\n return null;\n })\n : Promise.resolve(null),\n apiUrl\n ? fetch(\n `${apiUrl}/api/analytics/portfolio-history?days=7`,\n { headers: { 'x-sui-address': address }, signal: context.signal },\n )\n .then((res) => (res.ok ? res.json() as Promise<{ change?: WeekChange }> : null))\n .catch(() => null)\n : Promise.resolve(null),\n // DeFi fetch — prefer the audric snapshot's already-computed\n // value, but only when we can trust it. Two trust signals:\n // 1. `source === 'blockvision'` — fully successful fresh read\n // (even if value is 0, that's a confirmed empty position).\n // 2. `defiValueUsd > 0` — any positive value, regardless\n // of source. `partial-stale` with a positive total is fine,\n // `partial` with a positive total is the live equivalent.\n //\n // [Bug — 2026-04-28 round 2] Pre-fix the trust gate was\n // `defiSource !== 'degraded'`, which let `partial + 0` through\n // as authoritative. During a BlockVision 429 burst the audric\n // host's `/api/portfolio` returns `partial + 0` (some protocols\n // failed, the rest reported $0, no sticky-positive available\n // *in that process*) — but the engine's direct fetcher in the\n // chat route may have a sticky-positive in *this* Vercel\n // instance's cache. Trusting audric's $0 silently dropped the\n // DeFi line that `balance_check` (which always calls direct)\n // showed correctly on the same turn — same SSOT-divergence bug\n // class, manifested in a different layer.\n //\n // The new condition routes around audric's $0 in exactly that\n // case. When the direct fetch ALSO returns $0 the answer is\n // consistent across tools (both report degraded), which is the\n // honest UX during a real outage.\n (audricSnapshot &&\n (audricSnapshot.defiSource === 'blockvision' ||\n audricSnapshot.defiValueUsd > 0))\n ? Promise.resolve<DefiSummary>({\n totalUsd: audricSnapshot.defiValueUsd,\n perProtocol: {},\n pricedAt: Date.now(),\n source: audricSnapshot.defiSource,\n })\n : fetchAddressDefiPortfolio(address, context.blockvisionApiKey, {}, { retryStats: context.retryStats }).catch(\n (err): DefiSummary => {\n console.warn('[portfolio_analysis] defi fetch failed:', err);\n return { totalUsd: 0, perProtocol: {}, pricedAt: Date.now(), source: 'degraded' };\n },\n ),\n ]);\n\n let walletValue = 0;\n const allAllocations: AssetAllocation[] = [];\n\n for (const coin of portfolio.coins) {\n const amount = Number(coin.balance) / 10 ** coin.decimals;\n if (!Number.isFinite(amount) || amount <= 0) continue;\n const usdValue = coin.usdValue ?? (coin.price != null ? amount * coin.price : 0);\n walletValue += usdValue;\n allAllocations.push({ symbol: coin.symbol, amount, usdValue, percentage: 0 });\n }\n\n const allocations = allAllocations.filter((a) => a.usdValue >= DUST_USD);\n\n let savingsValue = 0;\n let debtValue = 0;\n let healthFactor: number | null = null;\n let savingsApy: number | undefined;\n let dailyEarning: number | undefined;\n\n if (positions) {\n savingsValue = positions.savings ?? 0;\n debtValue = positions.borrows ?? 0;\n healthFactor = positions.healthFactor ?? null;\n if (typeof positions.savingsRate === 'number' && positions.savingsRate > 0) {\n savingsApy = positions.savingsRate;\n dailyEarning = savingsValue * savingsApy / 365;\n }\n }\n\n let weekChange: WeekChange | undefined;\n if (weekHistResult?.change && weekHistResult.change.absoluteUsd !== 0) {\n weekChange = weekHistResult.change;\n }\n\n // [Bug — 2026-04-28] DeFi must be in totalValue. Pre-fix:\n // totalValue = walletValue + savingsValue\n // → a wallet with $228 wallet + $1,569 in Cetus LPs reported $228\n // total, dropping 87% of the user's actual net worth.\n const defiValue = defiSummary.totalUsd;\n\n // [Bug — 2026-04-28] Synthesize per-protocol DeFi entries as\n // allocations so the pie/MiniBar reflects the true breakdown. Each\n // protocol becomes one row labelled with a `<protocol> DeFi` symbol\n // (e.g. `Cetus DeFi`, `Bluefin DeFi`). `amount: 0` because there's\n // no single underlying token — these positions are LP-pair / staked\n // composites whose unit isn't meaningful at the analysis level.\n // Skipped when defiSource is 'degraded' (per-protocol map is empty).\n if (defiSummary.source !== 'degraded') {\n for (const [protocol, usdValue] of Object.entries(defiSummary.perProtocol)) {\n if (typeof usdValue === 'number' && usdValue >= DUST_USD) {\n // Title-case the protocol name for display: 'cetus' → 'Cetus DeFi'.\n const label = protocol.charAt(0).toUpperCase() + protocol.slice(1) + ' DeFi';\n allocations.push({ symbol: label, amount: 0, usdValue, percentage: 0 });\n }\n }\n } else if (defiValue > 0) {\n // Sticky-positive cache may give us a totalUsd without a protocol\n // breakdown — surface a single aggregate row so the pie still\n // includes DeFi mass even if we can't break it down.\n allocations.push({ symbol: 'DeFi (aggregate)', amount: 0, usdValue: defiValue, percentage: 0 });\n }\n\n const totalValue = walletValue + savingsValue + defiValue;\n\n for (const a of allocations) {\n a.percentage = totalValue > 0 ? (a.usdValue / totalValue) * 100 : 0;\n }\n allocations.sort((a, b) => b.usdValue - a.usdValue);\n\n const stableValue = allocations\n .filter((a) => STABLECOINS.has(a.symbol))\n .reduce((s, a) => s + a.usdValue, 0) + savingsValue;\n const stablePercentage = totalValue > 0 ? (stableValue / totalValue) * 100 : 0;\n\n const insights: PortfolioInsight[] = [];\n\n if (healthFactor !== null && healthFactor < 1.5) {\n insights.push({\n type: 'warning',\n message: `Health factor ${healthFactor.toFixed(2)} is dangerously low. Consider repaying debt or adding collateral.`,\n });\n } else if (healthFactor !== null && healthFactor < 2.5) {\n insights.push({\n type: 'warning',\n message: `Health factor ${healthFactor.toFixed(2)} is moderate. Monitor your positions.`,\n });\n }\n\n if (stablePercentage > 80) {\n insights.push({\n type: 'suggestion',\n message: `${stablePercentage.toFixed(0)}% stablecoins. Consider diversifying into yield-bearing positions.`,\n });\n }\n\n const idleCash = allocations.find((a) => a.symbol === 'USDC');\n if (idleCash && idleCash.usdValue > 10) {\n insights.push({\n type: 'suggestion',\n message: `$${idleCash.usdValue.toFixed(2)} USDC idle in wallet. Deposit into NAVI savings for ~4-5% APY.`,\n });\n }\n\n if (allocations.length === 1) {\n insights.push({\n type: 'info',\n message: 'Portfolio is concentrated in a single asset.',\n });\n }\n\n // [Bug — 2026-04-28] Caveat insight when DeFi was unreachable so the\n // LLM doesn't narrate the partial total as if it were complete.\n if (defiSummary.source === 'degraded') {\n insights.push({\n type: 'warning',\n message: 'DeFi positions could not be loaded — total may under-count any Cetus/Bluefin/Suilend value.',\n });\n } else if (defiSummary.source === 'partial') {\n insights.push({\n type: 'warning',\n message: 'DeFi data is partial — at least one protocol failed; total may under-count.',\n });\n }\n\n const result: PortfolioResult = {\n totalValue,\n walletValue,\n savingsValue,\n defiValue,\n defiSource: defiSummary.source,\n debtValue,\n healthFactor,\n allocations: allocations.slice(0, 10),\n stablePercentage,\n insights,\n savingsApy,\n dailyEarning,\n weekChange,\n priceSource: portfolio.source,\n address,\n isSelfQuery:\n !!context.walletAddress &&\n address.toLowerCase() === context.walletAddress.toLowerCase(),\n suinsName,\n };\n\n const defiSegment = defiValue > 0\n ? ` | DeFi: $${defiValue.toFixed(2)}${defiSummary.source === 'partial' ? ' (partial)' : ''}`\n : '';\n const topLine = `Total: $${totalValue.toFixed(2)} | Wallet: $${walletValue.toFixed(2)} | Savings: $${savingsValue.toFixed(2)}${defiSegment}`;\n const insightLines = insights.map((i) => `${i.type === 'warning' ? '⚠' : '→'} ${i.message}`).join('\\n');\n\n return {\n data: result,\n displayText: `${topLine}\\n${insightLines}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst LLAMA_API = 'https://api.llama.fi';\n\nconst SLUG_ALIASES: Record<string, string> = {\n 'navi': 'navi-lending',\n 'navi-protocol': 'navi-lending',\n 'scallop': 'scallop-lend',\n};\n\nconst inputSchema = z.object({\n protocol: z.string().describe('Protocol slug (e.g. \"navi-lending\", \"cetus\", \"scallop-lend\")'),\n});\n\ninterface ProtocolProfile {\n name: string;\n slug: string;\n category: string;\n chains: string[];\n tvl: number;\n tvlChange1d: number;\n tvlChange7d: number;\n tvlChange30d: number;\n mcap: number | null;\n fees24h: number | null;\n revenue24h: number | null;\n auditCount: number;\n auditLinks: string[];\n url: string;\n twitter: string | null;\n riskFactors: string[];\n safetyScore: string;\n}\n\nfunction extractCurrentTvl(proto: Record<string, unknown>): number {\n const chainTvls = proto.currentChainTvls;\n if (chainTvls && typeof chainTvls === 'object') {\n return Object.values(chainTvls as Record<string, number>)\n .filter((v) => typeof v === 'number' && v > 0)\n .reduce((sum, v) => sum + v, 0);\n }\n if (Array.isArray(proto.tvl) && proto.tvl.length > 0) {\n const last = proto.tvl[proto.tvl.length - 1] as { totalLiquidityUSD?: number };\n return last.totalLiquidityUSD ?? 0;\n }\n if (typeof proto.tvl === 'number') return proto.tvl;\n return 0;\n}\n\nfunction fmtTvl(tvl: number): string {\n if (tvl >= 1e9) return `$${(tvl / 1e9).toFixed(2)}B`;\n if (tvl >= 1e6) return `$${(tvl / 1e6).toFixed(1)}M`;\n if (tvl >= 1e3) return `$${(tvl / 1e3).toFixed(0)}K`;\n return `$${tvl.toFixed(0)}`;\n}\n\nexport const protocolDeepDiveTool = buildTool({\n name: 'protocol_deep_dive',\n description:\n 'Get a comprehensive safety and financial profile of a DeFi protocol. Includes TVL trends, revenue, audit status, and risk assessment. Use when users ask \"is X safe?\" or \"tell me about protocol Y\".',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n protocol: { type: 'string', description: 'Protocol slug (e.g. \"navi-lending\", \"cetus\")' },\n },\n required: ['protocol'],\n },\n isReadOnly: true,\n async call(input) {\n let slug = input.protocol.toLowerCase().replace(/\\s+/g, '-');\n slug = SLUG_ALIASES[slug] ?? slug;\n\n const [protocolRes, feesRes] = await Promise.allSettled([\n fetch(`${LLAMA_API}/protocol/${slug}`, { signal: AbortSignal.timeout(10_000) }).then((r) => {\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.json();\n }),\n fetch(`${LLAMA_API}/summary/fees/${slug}?dataType=dailyFees`, { signal: AbortSignal.timeout(8_000) }).then((r) => {\n if (!r.ok) return null;\n return r.json();\n }),\n ]);\n\n if (protocolRes.status === 'rejected') {\n throw new Error(`Protocol \"${slug}\" not found on DefiLlama.`);\n }\n\n const proto = protocolRes.value as Record<string, unknown>;\n\n const tvl = extractCurrentTvl(proto);\n const tvlChange1d = Number(proto.change_1d ?? 0);\n const tvlChange7d = Number(proto.change_7d ?? 0);\n const tvlChange30d = Number(proto.change_1m ?? 0);\n const chains = Array.isArray(proto.chains) ? (proto.chains as string[]) : [];\n const category = (proto.category ?? 'Unknown') as string;\n\n const auditCount = Number(proto.audits) || 0;\n const auditLinks = Array.isArray(proto.audit_links) ? (proto.audit_links as string[]) : [];\n const hasAudits = auditCount > 0 || auditLinks.length > 0;\n\n let fees24h: number | null = null;\n let revenue24h: number | null = null;\n if (feesRes.status === 'fulfilled' && feesRes.value) {\n const feesData = feesRes.value as Record<string, unknown>;\n fees24h = feesData.total24h != null ? Number(feesData.total24h) : null;\n revenue24h = feesData.totalRevenue24h != null ? Number(feesData.totalRevenue24h) : null;\n }\n\n const riskFactors: string[] = [];\n\n if (tvl < 1_000_000) riskFactors.push('TVL under $1M — low liquidity risk');\n else if (tvl < 10_000_000) riskFactors.push('TVL under $10M — moderate liquidity');\n if (tvlChange7d < -15) riskFactors.push(`TVL dropped ${tvlChange7d.toFixed(1)}% in 7 days`);\n if (chains.length === 1) riskFactors.push('Single-chain deployment');\n if (!hasAudits) riskFactors.push('No published audits found');\n else riskFactors.push(`${auditCount || auditLinks.length} audit(s) on file`);\n\n let safetyScore: string;\n if (tvl > 100_000_000 && hasAudits && tvlChange7d > -10) {\n safetyScore = 'High — established protocol with audits and significant TVL';\n } else if (tvl > 10_000_000 && tvlChange7d > -20) {\n safetyScore = 'Moderate — decent TVL, use with caution';\n } else {\n safetyScore = 'Low — small or declining TVL, proceed carefully';\n }\n\n const result: ProtocolProfile = {\n name: (proto.name ?? slug) as string,\n slug,\n category,\n chains,\n tvl,\n tvlChange1d,\n tvlChange7d,\n tvlChange30d,\n mcap: proto.mcap ? Number(proto.mcap) : null,\n fees24h,\n revenue24h,\n auditCount,\n auditLinks,\n url: (proto.url ?? '') as string,\n twitter: (proto.twitter ?? null) as string | null,\n riskFactors,\n safetyScore,\n };\n\n const feesStr = fees24h != null ? ` | Fees 24h: $${fees24h.toLocaleString()}` : '';\n\n return {\n data: result,\n displayText: `**${result.name}** (${category})\\nTVL: ${fmtTvl(tvl)} (7d: ${tvlChange7d > 0 ? '+' : ''}${tvlChange7d.toFixed(1)}%)${feesStr}\\nChains: ${chains.join(', ')}\\nSafety: ${safetyScore}\\nRisks: ${riskFactors.join('; ')}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst PaymentLinkSchema = z.object({\n amount: z.number().positive().describe('Amount in USDC (required). Ask the user if not specified.'),\n label: z.string().optional().describe('Human-readable label e.g. \"Consulting fee March\"'),\n memo: z.string().optional().describe('Optional note shown to the payer'),\n expiresInHours: z.number().positive().optional().describe('Hours until the link expires. Omit for permanent links.'),\n});\n\nconst InvoiceSchema = z.object({\n amount: z.number().positive().describe('Total invoice amount in USDC'),\n label: z.string().describe('Invoice title e.g. \"Web design — March 2026\"'),\n memo: z.string().optional().describe('Optional note or payment terms'),\n recipientName: z.string().optional().describe('Name of the person or company being invoiced'),\n recipientEmail: z.string().optional().describe('Email address of the recipient'),\n dueDays: z.number().int().positive().optional().describe('Days until payment is due. Omit for no due date.'),\n items: z.array(z.object({\n description: z.string(),\n amount: z.number().positive(),\n })).optional().describe('Line items. If omitted, a single line item matching the total is implied.'),\n});\n\nfunction internalHeaders(context: { walletAddress?: string; env?: Record<string, string | undefined>; signal?: AbortSignal }) {\n const internalKey = context.env?.AUDRIC_INTERNAL_KEY;\n return {\n 'Content-Type': 'application/json',\n 'x-sui-address': context.walletAddress ?? '',\n ...(internalKey ? { 'x-internal-key': internalKey } : {}),\n };\n}\n\nexport const createPaymentLinkTool = buildTool({\n name: 'create_payment_link',\n description:\n 'Create a shareable payment link so someone can send USDC to the user. Amount is required — ask the user for the amount if not specified. Returns a URL the user can share. Payers can connect their wallet, scan a QR code, or send manually. Use when the user says \"create a payment link\", \"generate a payment link\", \"I want to get paid\", or similar.',\n inputSchema: PaymentLinkSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { type: 'number', description: 'Amount in USDC (required). Ask the user if not specified.' },\n label: { type: 'string', description: 'Human-readable label e.g. \"Consulting fee March\"' },\n memo: { type: 'string', description: 'Optional note shown to the payer' },\n expiresInHours: { type: 'number', description: 'Hours until the link expires. Omit for permanent links.' },\n },\n required: ['amount'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Payment link creation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'POST',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ ...input, type: 'link' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to create payment link.' };\n }\n\n const link = await res.json() as {\n slug: string;\n nonce: string;\n url: string;\n amount: number;\n currency: string;\n label: string | null;\n memo: string | null;\n expiresAt: string | null;\n };\n\n const amountStr = `$${link.amount.toFixed(2)} ${link.currency}`;\n return {\n data: link,\n displayText: `Payment link created for ${amountStr}${link.label ? ` — ${link.label}` : ''}. Payers can connect their wallet, scan the QR code, or send manually. Share: ${link.url}`,\n };\n } catch {\n return { data: null, displayText: 'Failed to create payment link.' };\n }\n },\n});\n\nexport const listPaymentLinksTool = buildTool({\n name: 'list_payment_links',\n description:\n 'List the user\\'s payment links — active, paid, expired, and cancelled. Use when the user asks \"show my payment links\", \"what payment links do I have\", or wants to check payment status.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: true,\n\n async call(_input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: { links: [] }, displayText: 'No payment links found.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments?type=link`, {\n signal: context.signal,\n headers: internalHeaders(context),\n });\n\n if (!res.ok) return { data: { links: [] }, displayText: 'Could not fetch payment links.' };\n\n const raw = await res.json() as { payments: unknown[] };\n const links = raw.payments;\n const count = links.length;\n return {\n data: { links },\n displayText: count === 0 ? 'No payment links yet.' : `${count} payment link${count !== 1 ? 's' : ''} found.`,\n };\n } catch {\n return { data: { links: [] }, displayText: 'Could not fetch payment links.' };\n }\n },\n});\n\nexport const createInvoiceTool = buildTool({\n name: 'create_invoice',\n description:\n 'Create a formal invoice that the user can share with a client or customer. Returns a URL for the invoice page. Payers can connect their wallet, scan a QR code, or send manually. Use when the user says \"create an invoice\", \"generate an invoice\", \"bill a client\", or similar.',\n inputSchema: InvoiceSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { type: 'number', description: 'Total invoice amount in USDC' },\n label: { type: 'string', description: 'Invoice title e.g. \"Web design — March 2026\"' },\n memo: { type: 'string', description: 'Optional note or payment terms' },\n recipientName: { type: 'string', description: 'Name of the person or company being invoiced' },\n recipientEmail: { type: 'string', description: 'Email address of the recipient' },\n dueDays: { type: 'number', description: 'Days until payment is due. Omit for no due date.' },\n items: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n description: { type: 'string' },\n amount: { type: 'number' },\n },\n required: ['description', 'amount'],\n },\n description: 'Line items. If omitted, a single line item matching the total is implied.',\n },\n },\n required: ['amount', 'label'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Invoice creation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'POST',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ ...input, type: 'invoice' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to create invoice.' };\n }\n\n const invoice = await res.json() as {\n slug: string;\n nonce: string;\n url: string;\n amount: number;\n currency: string;\n label: string;\n memo: string | null;\n dueDate: string | null;\n };\n\n const dueStr = invoice.dueDate ? ` due ${new Date(invoice.dueDate).toLocaleDateString()}` : '';\n return {\n data: invoice,\n displayText: `Invoice created for $${invoice.amount.toFixed(2)} ${invoice.currency}${dueStr} — ${invoice.label}. Payers can connect their wallet, scan the QR code, or send manually. Share: ${invoice.url}`,\n };\n } catch {\n return { data: null, displayText: 'Failed to create invoice.' };\n }\n },\n});\n\nexport const cancelPaymentLinkTool = buildTool({\n name: 'cancel_payment_link',\n description:\n 'Cancel an active payment link so it can no longer be used. Use when the user says \"cancel my payment link\", \"delete my payment link\", or \"remove the link [slug/label]\". Ask for the slug if ambiguous — use list_payment_links first to find it.',\n inputSchema: z.object({\n slug: z.string().describe('The slug of the payment link to cancel (e.g. \"LzLawhY7\")'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n slug: { type: 'string', description: 'The slug of the payment link to cancel' },\n },\n required: ['slug'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Payment link cancellation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'PATCH',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ slug: input.slug, action: 'cancel' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to cancel payment link.' };\n }\n\n const result = await res.json() as { slug: string; status: string };\n return {\n data: result,\n displayText: `Payment link ${result.slug} cancelled.`,\n };\n } catch {\n return { data: null, displayText: 'Failed to cancel payment link.' };\n }\n },\n});\n\nexport const cancelInvoiceTool = buildTool({\n name: 'cancel_invoice',\n description:\n 'Cancel an invoice that has not yet been paid. Use when the user says \"cancel my invoice\", \"delete invoice\", or refers to a specific invoice slug or label. Use list_invoices first if the slug is not known.',\n inputSchema: z.object({\n slug: z.string().describe('The slug of the invoice to cancel (e.g. \"xFYKBWy5\")'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n slug: { type: 'string', description: 'The slug of the invoice to cancel' },\n },\n required: ['slug'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Invoice cancellation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'PATCH',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ slug: input.slug, action: 'cancel' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to cancel invoice.' };\n }\n\n const result = await res.json() as { slug: string; status: string };\n return {\n data: result,\n displayText: `Invoice ${result.slug} cancelled.`,\n };\n } catch {\n return { data: null, displayText: 'Failed to cancel invoice.' };\n }\n },\n});\n\nexport const listInvoicesTool = buildTool({\n name: 'list_invoices',\n description:\n 'List the user\\'s invoices — pending, overdue, paid, and cancelled. Use when the user asks \"show my invoices\", \"what invoices do I have\", or wants to check invoice status.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: true,\n\n async call(_input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: { invoices: [] }, displayText: 'No invoices found.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments?type=invoice`, {\n signal: context.signal,\n headers: internalHeaders(context),\n });\n\n if (!res.ok) return { data: { invoices: [] }, displayText: 'Could not fetch invoices.' };\n\n const raw = await res.json() as { payments: unknown[] };\n const invoices = raw.payments;\n const count = invoices.length;\n return {\n data: { invoices },\n displayText: count === 0 ? 'No invoices yet.' : `${count} invoice${count !== 1 ? 's' : ''} found.`,\n };\n } catch {\n return { data: { invoices: [] }, displayText: 'Could not fetch invoices.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { ToolResult } from '../types.js';\n\n// ---------------------------------------------------------------------------\n// Template catalogue\n// ---------------------------------------------------------------------------\n\nexport const CANVAS_TEMPLATES = [\n 'activity_heatmap',\n 'portfolio_timeline',\n 'yield_projector',\n 'health_simulator',\n 'dca_planner',\n 'spending_breakdown',\n 'watch_address',\n 'full_portfolio',\n] as const;\n\nexport type CanvasTemplate = (typeof CANVAS_TEMPLATES)[number];\n\n/** Normalize savings rate: if < 1 treat as decimal → multiply by 100, else use as-is. Default 4.5%. */\nfunction normalizeSavingsRate(raw: number | undefined | null, fallback = 4.5): number {\n const r = raw ?? 0;\n if (r > 0 && r < 1) return r * 100;\n if (r > 0) return r;\n return fallback;\n}\n\nconst CANVAS_TITLES: Record<CanvasTemplate, string> = {\n activity_heatmap: 'On-Chain Activity',\n portfolio_timeline: 'Net Worth Over Time',\n yield_projector: 'Yield Projector',\n health_simulator: 'Health Factor Simulator',\n dca_planner: 'Savings Plan',\n spending_breakdown: 'Spending Breakdown',\n watch_address: 'Watch Address',\n full_portfolio: 'Full Portfolio Overview',\n};\n\n// ---------------------------------------------------------------------------\n// render_canvas tool\n// ---------------------------------------------------------------------------\n\nexport const renderCanvasTool = buildTool({\n name: 'render_canvas',\n description: `Renders an interactive financial canvas inline in the chat.\n\nUse when the user asks for a visual chart, simulator, or financial overview. Pick the most relevant template:\n\n- activity_heatmap — on-chain transaction history as a GitHub-style heatmap (WORKS NOW — accepts \\`params.address\\` to inspect any public Sui wallet; defaults to the signed-in user)\n- portfolio_timeline — net worth over time, wallet/savings/debt breakdown (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user)\n- yield_projector — compound yield simulator with amount/APY/period sliders (WORKS NOW — client-side, no address needed)\n- health_simulator — borrow health factor simulator with collateral/debt sliders (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user's current position)\n- dca_planner — savings plan curve for regular monthly deposits (WORKS NOW — client-side, no address needed)\n- spending_breakdown — spending by service category (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user)\n- watch_address — portfolio overview for any public Sui address (WORKS NOW — pass \\`params.address\\`)\n- full_portfolio — 4-panel overview: savings, health, activity, spending (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user)\n\nWhen the user asks to inspect a saved contact or watched address — e.g. \"show funkii's activity heatmap\", \"what's funkii's portfolio look like\", \"spending breakdown for 0x40cd…\", \"give me a full portfolio overview of 0x40cd…\" — pass that wallet's address as \\`params.address\\`. Six of the eight templates (activity_heatmap, portfolio_timeline, spending_breakdown, watch_address, health_simulator, full_portfolio) will scope their data fetch to that address; only the pure client-side simulators (yield_projector, dca_planner) ignore params.address.\n\nAlways prefer the canvas for visualisation requests. After rendering, offer to explain what the user sees.`,\n inputSchema: z.object({\n template: z.enum(CANVAS_TEMPLATES).describe('Which canvas template to render'),\n params: z\n .object({\n period: z.enum(['1m', '3m', '6m', '1y']).optional().describe('Time period for time-based templates'),\n address: z\n .string()\n .optional()\n .describe(\n 'Sui address for the six address-aware templates (activity_heatmap, portfolio_timeline, spending_breakdown, watch_address, health_simulator, full_portfolio). Defaults to the signed-in user; pass an explicit address to inspect a contact, watched wallet, or any other public address.',\n ),\n })\n .optional(),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n template: {\n type: 'string',\n enum: CANVAS_TEMPLATES,\n description: 'Which canvas template to render',\n },\n params: {\n type: 'object',\n properties: {\n period: { type: 'string', enum: ['1m', '3m', '6m', '1y'] },\n address: { type: 'string' },\n },\n },\n },\n required: ['template'],\n },\n isReadOnly: true,\n\n async call(input, context): Promise<ToolResult<unknown>> {\n const { template, params } = input;\n const title = CANVAS_TITLES[template];\n\n /**\n * [v1.2 SuiNS] Pre-resolve `params.address` once at the top of\n * `call()` (instead of inside the per-template branches) so that\n * SuiNS names like \\`alex.sui\\` work for every address-aware\n * template without each branch having to thread normalization\n * through. Templates already index the resolved 0x for any\n * downstream API call; the original SuiNS name is preserved in\n * `suinsName` so the canvas can title itself with the human-readable\n * name (e.g. \"Activity for alex.sui\").\n *\n * SCOPE. Only normalize for the six address-aware templates. The\n * pure simulators (`yield_projector`, `dca_planner`) ignore\n * `params.address` entirely — running the normalizer for them would\n * regress to \"transient SuiNS RPC failure crashes a yield-projector\n * canvas the user didn't even ask to be address-scoped\".\n */\n const ADDRESS_AWARE_TEMPLATES = new Set<CanvasTemplate>([\n 'full_portfolio',\n 'watch_address',\n 'portfolio_timeline',\n 'spending_breakdown',\n 'activity_heatmap',\n 'health_simulator',\n ]);\n let suinsName: string | null = null;\n let resolvedParamAddress: string | null = null;\n if (params?.address && ADDRESS_AWARE_TEMPLATES.has(template)) {\n const normalized = await normalizeAddressInput(params.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n resolvedParamAddress = normalized.address;\n suinsName = normalized.suinsName;\n }\n\n /**\n * [v0.48] Address resolution for the four address-aware templates\n * (activity_heatmap, portfolio_timeline, spending_breakdown,\n * watch_address). Pre-v0.48 only `watch_address` consulted\n * `params.address`; the other three hardcoded `context.walletAddress`\n * which silently masked the watched-address case (the LLM passed\n * the right param, the canvas rendered the user's own data).\n *\n * Falls back to `context.walletAddress` when `params.address` is\n * absent. Returns `null` when neither is present so callers can\n * surface a \"needs an address\" error state.\n *\n * `isSelfRender` lets the result advertise whether the canvas\n * targets the signed-in user — the frontend ActivityHeatmapCanvas\n * uses it so cell clicks produce contextually correct chat prompts\n * (\"Show transactions for 0x40cd…\" vs \"Show my transactions\n * from…\"). Without this flag, a heatmap cell click on a watched\n * address routes back into the user's own transaction history.\n */\n const resolveAddressTarget = (): { address: string | null; isSelfRender: boolean; suinsName: string | null } => {\n const fromParams = resolvedParamAddress;\n const fromContext = context.walletAddress;\n const target = fromParams ?? fromContext ?? null;\n const isSelfRender = !!target && !!fromContext && target.toLowerCase() === fromContext.toLowerCase();\n return { address: target, isSelfRender, suinsName };\n };\n\n /**\n * [v1.2 SuiNS] Prefer the human-readable SuiNS name in titles +\n * narration when present; fall back to the truncated 0x address.\n * Used by every address-aware template's titleSuffix + displayText.\n */\n const formatAddrLabel = (address: string, suins: string | null): string =>\n suins ?? `${address.slice(0, 6)}…${address.slice(-4)}`;\n\n // Full portfolio — 4-panel capstone with live position data\n if (template === 'full_portfolio') {\n /**\n * [v0.49] When `params.address` is present and points to a wallet\n * other than the signed-in user, do NOT seed templateData with\n * `context.serverPositions` (those are the user's own positions\n * and would be misleading for a watched-address overview). The\n * frontend re-fetches per-panel data via the address-aware API\n * routes (`/api/balances`, `/api/savings`, etc.), so we just hand\n * it the address + isSelfRender flag.\n */\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Full Portfolio needs an address.' },\n },\n displayText: 'Full Portfolio requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n const pos = isSelfRender ? context.serverPositions : null;\n const rate = normalizeSavingsRate(pos?.savingsRate);\n const savings = pos?.savings ?? 0;\n const borrows = pos?.borrows ?? 0;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n currentSavings: savings,\n currentDebt: borrows,\n healthFactor: pos?.healthFactor ?? null,\n savingsRate: rate,\n },\n },\n displayText: isSelfRender\n ? `Opened Full Portfolio Overview.`\n : `Opened Full Portfolio Overview for ${addrLabel}.`,\n };\n }\n\n // Watch address — show balances for any public Sui address (or SuiNS name).\n if (template === 'watch_address') {\n // [v1.2 SuiNS] resolvedParamAddress comes from the top-of-call\n // normalization, so a SuiNS name like \"alex.sui\" resolves here.\n const targetAddress = resolvedParamAddress ?? '';\n if (!targetAddress) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Please provide a valid Sui address or SuiNS name to watch.' },\n },\n displayText: 'No valid address provided. Ask the user for a Sui address or SuiNS name.',\n };\n }\n const addrLabel = formatAddrLabel(targetAddress, suinsName);\n return {\n data: {\n __canvas: true,\n template,\n title: `Watch ${addrLabel}`,\n templateData: { available: true, address: targetAddress, suinsName },\n },\n displayText: `Opened Watch Address canvas for ${addrLabel}.`,\n };\n }\n\n // Portfolio timeline — fetches from /api/analytics/portfolio-history\n if (template === 'portfolio_timeline') {\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Portfolio Timeline needs an address.' },\n },\n displayText: 'Portfolio Timeline requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n },\n },\n displayText: isSelfRender\n ? `Opened Portfolio Timeline. Shows your net worth, savings, and debt over time.`\n : `Opened Portfolio Timeline for ${addrLabel}.`,\n };\n }\n\n // Spending breakdown — fetches from /api/analytics/spending\n if (template === 'spending_breakdown') {\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Spending Breakdown needs an address.' },\n },\n displayText: 'Spending Breakdown requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n },\n },\n displayText: isSelfRender\n ? `Opened Spending Breakdown. Shows your service spending by category.`\n : `Opened Spending Breakdown for ${addrLabel}.`,\n };\n }\n\n // Activity heatmap — client-side fetches from /api/analytics/activity-heatmap\n if (template === 'activity_heatmap') {\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Activity Heatmap needs an address.' },\n },\n displayText: 'Activity Heatmap requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n },\n },\n displayText: isSelfRender\n ? `Opened Activity Heatmap for your wallet. Click any day to explore transactions.`\n : `Opened Activity Heatmap for ${addrLabel}. Click any day to explore that address's transactions.`,\n };\n }\n\n // Strategy simulators — client-side, seed with live position data\n const positions = context.serverPositions;\n const savingsRate = normalizeSavingsRate(positions?.savingsRate);\n const healthFactor = positions?.healthFactor ?? null;\n const totalSavings = positions?.savings ?? 0;\n const totalBorrows = positions?.borrows ?? 0;\n\n if (template === 'yield_projector') {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: {\n available: true,\n initialAmount: totalSavings > 0 ? Math.round(totalSavings) : 1000,\n initialApy: savingsRate,\n },\n },\n displayText: `Opened Yield Projector. Current USDC deposit rate: ${savingsRate.toFixed(2)}% APY.`,\n };\n }\n\n if (template === 'health_simulator') {\n /**\n * [v0.49] When the user passes `params.address` for a watched\n * wallet, seed the simulator with neutral defaults instead of the\n * signed-in user's own position. The frontend re-fetches per\n * `address` via `/api/health` to populate the live HF readout,\n * so seeding here is just for the slider initial state.\n */\n const { address: targetAddress, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n const seedFromPos = isSelfRender;\n const seedSavings = seedFromPos ? totalSavings : 0;\n const seedBorrows = seedFromPos ? totalBorrows : 0;\n const seedHf = seedFromPos ? healthFactor : null;\n const roundedDebt = seedBorrows >= 1\n ? Math.round(seedBorrows)\n : (seedBorrows > 0 ? parseFloat(seedBorrows.toFixed(4)) : 0);\n const titleSuffix = !targetAddress || isSelfRender\n ? ''\n : ` — ${formatAddrLabel(targetAddress, resolvedSuins)}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address: targetAddress ?? '',\n isSelfRender,\n suinsName: resolvedSuins,\n initialCollateral: seedSavings > 0 ? Math.round(seedSavings) : 1500,\n initialDebt: roundedDebt > 0 ? roundedDebt : (seedSavings > 0 ? 0 : 500),\n currentHf: seedHf,\n },\n },\n displayText: isSelfRender\n ? `Opened Health Factor Simulator. Current HF: ${healthFactor !== null ? healthFactor.toFixed(2) : 'no active position'}.`\n : `Opened Health Factor Simulator${titleSuffix}. The simulator will fetch the current health factor for that wallet.`,\n };\n }\n\n if (template === 'dca_planner') {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: {\n available: true,\n initialMonthly: 200,\n initialApy: savingsRate,\n },\n },\n displayText: `Opened Savings Plan. Current USDC deposit rate: ${savingsRate.toFixed(2)}% APY.`,\n };\n }\n\n // Fallback — should not reach here given exhaustive template enum\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Unknown template.' },\n },\n displayText: `Canvas template \"${template}\" is not yet available.`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport type { ToolResult } from '../types.js';\n\ninterface SpendingResponse {\n period: string;\n totalSpent: number;\n requestCount: number;\n serviceCount: number;\n byService: unknown[];\n}\n\nexport const spendingAnalyticsTool = buildTool({\n name: 'spending_analytics',\n description:\n 'Returns MPP service spending breakdown for a period. Shows total spent, request count, and breakdown by service/category. Use when the user asks about their API spending, service usage, or costs.',\n inputSchema: z.object({\n period: z\n .enum(['week', 'month', 'year', 'all'])\n .optional()\n .describe('Time period. Defaults to current month.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n period: { type: 'string', enum: ['week', 'month', 'year', 'all'] },\n },\n },\n isReadOnly: true,\n\n async call(input, context): Promise<ToolResult<SpendingResponse>> {\n const period = input.period ?? 'month';\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n const address = context.walletAddress;\n const empty: SpendingResponse = { period, totalSpent: 0, requestCount: 0, serviceCount: 0, byService: [] };\n\n if (!apiUrl || !address) {\n return { data: empty, displayText: 'Spending analytics not available.' };\n }\n\n try {\n const res = await fetch(\n `${apiUrl}/api/analytics/spending?address=${address}&period=${period}`,\n {\n headers: { 'x-sui-address': address },\n signal: context.signal,\n },\n );\n\n if (!res.ok) {\n return { data: empty, displayText: `Could not fetch spending data (HTTP ${res.status}).` };\n }\n\n const data = (await res.json()) as SpendingResponse;\n const total = data.totalSpent ?? 0;\n const count = data.requestCount ?? 0;\n\n return {\n data,\n displayText: total > 0\n ? `You spent $${total.toFixed(2)} across ${count} request${count !== 1 ? 's' : ''} on ${data.serviceCount} service${data.serviceCount !== 1 ? 's' : ''} (${data.period}).`\n : `No service spending recorded for ${data.period}.`,\n };\n } catch {\n return { data: empty, displayText: 'Error fetching spending analytics.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport type { ToolResult } from '../types.js';\n\ninterface YieldSummary {\n today: number;\n thisWeek: number;\n thisMonth: number;\n allTime: number;\n currentApy: number;\n deposited: number;\n projectedYear: number;\n sparkline: number[];\n}\n\nexport const yieldSummaryTool = buildTool({\n name: 'yield_summary',\n description:\n 'Returns yield earnings breakdown: today, this week, this month, all-time, current APY, deposited amount, projected yearly earnings, and a monthly sparkline. Use when the user asks about yield, earnings, or how much they have earned.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: true,\n\n async call(_input, context): Promise<ToolResult<YieldSummary>> {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n const address = context.walletAddress;\n\n const empty: YieldSummary = {\n today: 0, thisWeek: 0, thisMonth: 0, allTime: 0,\n currentApy: 0, deposited: 0, projectedYear: 0, sparkline: [],\n };\n\n if (!apiUrl || !address) {\n return { data: empty, displayText: 'Yield summary not available.' };\n }\n\n try {\n const res = await fetch(\n `${apiUrl}/api/analytics/yield-summary?address=${address}`,\n { headers: { 'x-sui-address': address }, signal: context.signal },\n );\n\n if (!res.ok) {\n return { data: empty, displayText: `Could not fetch yield data (HTTP ${res.status}).` };\n }\n\n const data = (await res.json()) as YieldSummary;\n const apy = data.currentApy ?? 0;\n const apyPct = apy < 1 ? (apy * 100).toFixed(2) : apy.toFixed(2);\n\n return {\n data,\n displayText: data.allTime > 0\n ? `You've earned $${data.allTime.toFixed(2)} all-time ($${data.today.toFixed(4)} today). Current APY: ${apyPct}%. Deposited: $${data.deposited.toFixed(2)}. Projected: $${data.projectedYear.toFixed(2)}/year.`\n : `No yield earnings yet. Deposit USDC to start earning ${apyPct}% APY.`,\n };\n } catch {\n return { data: empty, displayText: 'Error fetching yield summary.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { ToolResult } from '../types.js';\n\ninterface ActionBreakdown {\n action: string;\n count: number;\n totalAmountUsd: number;\n}\n\ninterface ActivitySummary {\n period: string;\n totalTransactions: number;\n byAction: ActionBreakdown[];\n totalMovedUsd: number;\n netSavingsUsd: number;\n yieldEarnedUsd: number;\n address?: string;\n isSelfQuery?: boolean;\n suinsName?: string | null;\n}\n\nexport const activitySummaryTool = buildTool({\n name: 'activity_summary',\n description:\n 'Returns a categorised DeFi activity summary for the signed-in user OR any public Sui address or SuiNS name: transaction count, breakdown by action type (saves, sends, borrows, repayments, swaps, payments), total moved, net savings change, and yield earned. Use when the user asks about activity, transaction history summary, or what someone has done recently. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n period: z\n .enum(['week', 'month', 'year', 'all'])\n .optional()\n .describe('Time period. Defaults to current month.'),\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n period: { type: 'string', enum: ['week', 'month', 'year', 'all'] },\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n },\n isReadOnly: true,\n\n async call(input, context): Promise<ToolResult<ActivitySummary>> {\n const period = input.period ?? 'month';\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n const empty: ActivitySummary = {\n period, totalTransactions: 0, byAction: [],\n totalMovedUsd: 0, netSavingsUsd: 0, yieldEarnedUsd: 0,\n address: targetAddress, isSelfQuery, suinsName,\n };\n\n if (!apiUrl || !targetAddress) {\n return { data: empty, displayText: 'Activity summary not available.' };\n }\n\n try {\n const callerHeader = context.walletAddress ?? targetAddress;\n const res = await fetch(\n `${apiUrl}/api/analytics/activity-summary?address=${targetAddress}&period=${period}`,\n { headers: { 'x-sui-address': callerHeader }, signal: context.signal },\n );\n\n if (!res.ok) {\n return { data: empty, displayText: `Could not fetch activity data (HTTP ${res.status}).` };\n }\n\n const raw = (await res.json()) as ActivitySummary;\n const data: ActivitySummary = { ...raw, address: targetAddress, isSelfQuery, suinsName };\n const sorted = [...(data.byAction ?? [])].sort((a, b) => b.count - a.count);\n const top = sorted\n .slice(0, 3)\n .map((a) => `${a.action} (${a.count})`)\n .join(', ');\n\n const periodLabel = data.period === 'all' ? 'all time' : `this ${data.period}`;\n const subjectLabel = suinsName ?? `${targetAddress.slice(0, 6)}…${targetAddress.slice(-4)}`;\n const subjectPrefix = isSelfQuery ? '' : `${subjectLabel} — `;\n\n return {\n data,\n displayText: data.totalTransactions > 0\n ? `${subjectPrefix}${data.totalTransactions} transactions ${periodLabel}. Top: ${top}. Total moved: $${data.totalMovedUsd.toFixed(2)}. Net savings: $${data.netSavingsUsd.toFixed(2)}.`\n : `${subjectPrefix}No activity recorded for ${periodLabel}.`,\n };\n } catch {\n return { data: empty, displayText: 'Error fetching activity summary.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport {\n resolveSuinsViaRpc,\n resolveAddressToSuinsViaRpc,\n SUI_ADDRESS_REGEX,\n SUINS_NAME_REGEX,\n SuinsRpcError,\n} from '../sui-address.js';\n\n// ---------------------------------------------------------------------------\n// resolve_suins — SuiNS lookup primitive (forward + reverse)\n//\n// The six address-accepting read tools (balance/health/savings/history/\n// activity-summary/portfolio-analysis) call `normalizeAddressInput()`\n// internally so the LLM can pass `address: \"alex.sui\"` and get the\n// resolution for free. This tool is the *explicit* lookup primitive for\n// queries the LLM can't satisfy with another tool — primarily:\n//\n// FORWARD (name → address):\n// \"What's the address of obehi.sui?\" → returns the 0x address\n// \"Is bob.sui registered?\" → returns registered: false\n// \"Who owns alex.sui?\" → returns the address\n//\n// REVERSE (address → name):\n// \"What's the SuiNS for 0xa671..3244?\" → returns \"ossy.sui\"\n// \"Does this address have a SuiNS?\" → returns names[]\n// \"Show me the .sui name for 0x40cd...3e62\" → returns \"funkii.sui\"\n//\n// v1.3 adds the reverse direction (was forward-only in v1.2) so\n// \"what's the suins for 0x...\" stops bouncing the user to SuiScan.\n//\n// Single polymorphic input (`query`) keeps the schema tiny — the tool\n// detects direction by regex (0x prefix → reverse, .sui suffix →\n// forward). Without this tool the LLM was previously trying\n// `web_search` (which can't index SuiNS) or pointing the user at\n// third-party explorers, both of which are the wrong answer.\n// ---------------------------------------------------------------------------\n\nconst inputSchema = z.object({\n query: z\n .string()\n .describe(\n 'Either a SuiNS name (e.g. \"alex.sui\", \"team.alex.sui\") to FORWARD-resolve to its 0x address, ' +\n 'OR a Sui address (0x… 64 hex chars) to REVERSE-resolve to its registered SuiNS name(s). ' +\n 'The engine detects direction by input shape.',\n ),\n});\n\ninterface ResolveSuinsResult {\n /** Direction the lookup ran in. */\n direction: 'forward' | 'reverse';\n /** The original query, lowercased. */\n query: string;\n /** Forward only: the resolved 0x address (null when unregistered). */\n address?: string | null;\n /** Forward only: convenience flag for the LLM. */\n registered?: boolean;\n /** Reverse only: every SuiNS name pointing at this address (sorted by registry). */\n names?: string[];\n /** Reverse only: the first name in `names` (the conventional \"primary\"), or null. */\n primary?: string | null;\n}\n\nexport const resolveSuinsTool = buildTool({\n name: 'resolve_suins',\n description:\n 'Look up SuiNS records on-chain — works in BOTH directions. ' +\n 'FORWARD: pass a SuiNS name (e.g. \"alex.sui\") to get the 0x address it resolves to. ' +\n 'REVERSE: pass a Sui 0x address to get the SuiNS name(s) registered for it (returns the ' +\n 'primary name + the full list). ' +\n '\\n\\nUse this WHENEVER the user mentions a `.sui` name OR asks \"what\\'s the SuiNS for 0x…\", ' +\n '\"does 0x… have a name\", \"who is 0x…\". You MUST call this tool — never guess from saved ' +\n 'contacts (a contact named \"alex\" is NOT the same as the SuiNS name \"alex.sui\"; verify on-chain). ' +\n 'Never use `web_search` for SuiNS — web_search doesn\\'t index the SuiNS registry, but this tool ' +\n 'queries the canonical on-chain RPC. ' +\n '\\n\\nReturns `{ direction, address, registered }` for forward, ' +\n '`{ direction, names, primary }` for reverse. Empty `names: []` means the address has no SuiNS records. ' +\n '\\n\\nNOTE: For money-flow questions about a `.sui` name (\"what\\'s alex.sui\\'s balance / portfolio / ' +\n 'health / transactions\"), call the relevant read tool directly with `address: \"alex.sui\"` — those ' +\n 'tools normalize SuiNS internally, so an explicit `resolve_suins` round-trip is wasted.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description:\n 'A SuiNS name (e.g. \"alex.sui\") for forward resolution, OR a 0x Sui address for reverse resolution.',\n },\n },\n required: ['query'],\n },\n isReadOnly: true,\n // Lookups map to (address|name) pairs on a per-block basis. Cheap and\n // deterministic for a given block — safe to dedupe within a turn.\n cacheable: true,\n preflight: (input) => {\n const trimmed = input.query?.trim().toLowerCase();\n if (!trimmed) {\n return { valid: false, error: 'query is required' };\n }\n const isAddress = SUI_ADDRESS_REGEX.test(trimmed);\n const isName = SUINS_NAME_REGEX.test(trimmed);\n if (!isAddress && !isName) {\n return {\n valid: false,\n error:\n `\"${input.query}\" doesn't look like a SuiNS name or a Sui address. ` +\n `Pass either a name ending in .sui (e.g. alex.sui) or a 0x-prefixed hex address.`,\n };\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const query = input.query.trim().toLowerCase();\n const isAddress = SUI_ADDRESS_REGEX.test(query);\n\n try {\n if (isAddress) {\n const names = await resolveAddressToSuinsViaRpc(query, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n const primary = names[0] ?? null;\n const result: ResolveSuinsResult = {\n direction: 'reverse',\n query,\n names,\n primary,\n };\n return {\n data: result,\n displayText: primary\n ? `\\`${query.slice(0, 10)}…${query.slice(-6)}\\` → ${primary}${names.length > 1 ? ` (+${names.length - 1} more)` : ''}`\n : `\\`${query.slice(0, 10)}…${query.slice(-6)}\\` has no SuiNS name registered.`,\n };\n }\n\n // Forward direction: name → address.\n const address = await resolveSuinsViaRpc(query, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n const result: ResolveSuinsResult = {\n direction: 'forward',\n query,\n address,\n registered: address !== null,\n };\n return {\n data: result,\n displayText: address\n ? `${query} → \\`${address.slice(0, 10)}…${address.slice(-6)}\\``\n : `${query} is not a registered SuiNS name.`,\n };\n } catch (err) {\n // Surface RPC failures as a tool-level error so the LLM can narrate\n // (\"the SuiNS service is temporarily unreachable, try again in a\n // moment\") instead of pretending the lookup returned empty.\n if (err instanceof SuinsRpcError) {\n throw err;\n }\n throw err;\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\n// ---------------------------------------------------------------------------\n// update_todo — persistent per-turn todo list (SPEC 8 v0.5.1, P3.2 slice 2)\n//\n// The LLM calls this tool to declare or update its plan for the current\n// turn. Each call replaces the entire list — the tool is idempotent;\n// later calls overwrite earlier ones.\n//\n// The host renders the list as a sticky timeline block during the turn and\n// collapses it into \"✓ N-step plan completed\" once the turn ends. See\n// `spec/SPEC_8_INTERACTIVE_HARNESS.md` § \"Layer 2 — `update_todo` tool\".\n//\n// ## Why this is a tool and not a system-prompt convention\n//\n// Tools have typed inputs the LLM can't malform. A free-text \"<plan>...\n// </plan>\" convention would lose its shape under truncation, cache\n// invalidation, or model upgrade. Typed input means hosts get a structured\n// payload they can render, persist, or replay without parsing prose.\n//\n// ## Why this is exempt from `maxTurns`\n//\n// Calling `update_todo` documents work; it doesn't advance work. If the\n// LLM fires it 4× during a 5-tool plan, that's 4 of its 10 turns gone to\n// narration before any real action. The exemption (in `engine.ts`\n// agentLoop) detects iterations where every `tool_use` block was\n// `update_todo` and decrements `turns` so the budget stays for actual\n// progress. See engine.ts § \"[SPEC 8 v0.5.1] update_todo maxTurns\n// exemption\".\n//\n// ## Why the tool emits a side-channel `todo_update` event\n//\n// The host needs to render the persistent todo card the moment the tool\n// fires — before the LLM streams its next thought. A regular `tool_result`\n// event renders inline-after-the-stream-tool-block; the side channel lets\n// the host render directly to the timeline's sticky surface. Pattern\n// mirrors the existing `canvas` event (engine.ts ~line 805–816): the tool\n// result carries a magic `__todoUpdate: true` flag and the engine emits\n// the side-channel event in addition to the normal `tool_result`.\n//\n// ## Preflight rules (LLM-facing)\n//\n// - 1–8 items per call (no empty lists; 8 is the spec ceiling)\n// - Each label ≤ 80 chars (forces concision; longer text belongs in chat)\n// - Exactly 1 `in_progress` item (the user must always know \"what's\n// happening now\")\n// - All `id`s unique (host keys re-renders on id stability)\n// - `status` is one of the three known values\n//\n// Failed preflight returns the rule that broke as `error.error`; the LLM\n// re-asks with a corrected payload — same flow as every other write\n// tool's preflight.\n// ---------------------------------------------------------------------------\n\nconst todoStatusSchema = z.enum(['pending', 'in_progress', 'completed']);\n\nconst todoItemSchema = z.object({\n id: z\n .string()\n .min(1, 'id must be a non-empty string')\n .max(40, 'id must be ≤40 chars (use a slug, not a sentence)'),\n label: z\n .string()\n .min(1, 'label must be a non-empty string')\n .max(80, 'label must be ≤80 chars (the whole point of this tool is concision)'),\n status: todoStatusSchema,\n});\n\nconst inputSchema = z.object({\n items: z\n .array(todoItemSchema)\n .min(1, 'items must contain at least 1 entry')\n .max(8, 'items must contain at most 8 entries (SPEC 8 ceiling)'),\n});\n\nexport type TodoItem = z.infer<typeof todoItemSchema>;\nexport type UpdateTodoInput = z.infer<typeof inputSchema>;\n\nexport const updateTodoTool = buildTool({\n name: 'update_todo',\n description:\n \"Declare or replace your plan for the current turn as a structured todo list. \" +\n \"Call this when the user's ask is multi-step (≥3 tools, ≥2 reasoning hops) so \" +\n \"the user can see what you're doing as you do it. Each call replaces the entire \" +\n \"list — the tool is idempotent. \" +\n \"\\n\\nRules: 1–8 items, each label ≤80 chars, exactly 1 item must be `in_progress`. \" +\n \"Use stable `id`s across calls within the same turn so the UI can track item \" +\n \"transitions (e.g. `id: 'check-balance'` first as `pending`, later as `completed`). \" +\n \"\\n\\nDO NOT call this for single-step asks ('balance', 'rate') — it's wasted \" +\n \"tokens. DO call it before kicking off long flows where the user benefits from \" +\n \"seeing the plan unfold ('save my idle USDC' → check balance → check rates → \" +\n \"compute split → propose). \" +\n \"\\n\\nThis call doesn't count against your turn budget — re-narrating the plan \" +\n \"as items move from pending → in_progress → completed is encouraged.\",\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n items: {\n type: 'array',\n minItems: 1,\n maxItems: 8,\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Stable identifier across calls within the same turn (e.g. \"check-balance\"). ≤40 chars.',\n },\n label: {\n type: 'string',\n description: 'What this step is doing, ≤80 chars. Concrete (e.g. \"Check USDC rate\") not abstract (\"Gather data\").',\n },\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'completed'],\n description: 'Lifecycle state. Exactly one item must be `in_progress` per call.',\n },\n },\n required: ['id', 'label', 'status'],\n },\n },\n },\n required: ['items'],\n },\n isReadOnly: true,\n // No I/O, just a pass-through that emits a side-channel event. Skip the\n // turn-read cache — every call is intentionally distinct (ids may match\n // but statuses change).\n cacheable: false,\n preflight: (input) => {\n const items = input.items ?? [];\n if (items.length === 0) {\n return { valid: false, error: 'items must contain at least 1 entry' };\n }\n if (items.length > 8) {\n return { valid: false, error: `items must contain at most 8 entries, got ${items.length}` };\n }\n const seenIds = new Set<string>();\n let inProgressCount = 0;\n for (const item of items) {\n if (!item.id || item.id.trim().length === 0) {\n return { valid: false, error: 'every item must have a non-empty id' };\n }\n if (item.id.length > 40) {\n return { valid: false, error: `item id \"${item.id.slice(0, 30)}…\" exceeds 40 chars` };\n }\n if (seenIds.has(item.id)) {\n return { valid: false, error: `duplicate item id \"${item.id}\" — ids must be unique within a list` };\n }\n seenIds.add(item.id);\n if (!item.label || item.label.trim().length === 0) {\n return { valid: false, error: `item \"${item.id}\" has empty label` };\n }\n if (item.label.length > 80) {\n return { valid: false, error: `item \"${item.id}\" label exceeds 80 chars (got ${item.label.length})` };\n }\n if (item.status === 'in_progress') {\n inProgressCount++;\n }\n }\n if (inProgressCount !== 1) {\n return {\n valid: false,\n error: `exactly 1 item must be in_progress, got ${inProgressCount}`,\n };\n }\n return { valid: true };\n },\n\n async call(input) {\n return {\n // The `__todoUpdate` flag tells the engine's agent loop to emit a\n // `todo_update` side-channel event (mirrors the `__canvas` magic\n // flag pattern). The LLM still gets a normal `tool_result` keyed\n // to its `tool_use_id` so the Anthropic protocol stays satisfied.\n data: {\n __todoUpdate: true,\n items: input.items,\n },\n displayText: `${input.items.length} step${input.items.length === 1 ? '' : 's'}: ${input.items\n .map((i) => `${i.status === 'completed' ? '✓' : i.status === 'in_progress' ? '→' : '·'} ${i.label}`)\n .join(' / ')}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { fetchTokenPrices } from '../blockvision-prices.js';\n\n// ---------------------------------------------------------------------------\n// [v1.4 — Day 2] BlockVision-backed unified price tool.\n//\n// Replaces both deleted DefiLlama tools:\n// * `defillama_token_prices` — multi-token spot price\n// * `defillama_price_change` — single-token price + period change\n//\n// `defillama_price_change` previously supported 1h / 24h / 7d / 30d windows;\n// BlockVision only exposes 24h. Surfacing 24h is enough to answer the hot-\n// path question \"did X move today?\", and the LLM no longer has a tool that\n// silently lies about 7d/30d windows by re-running 24h. Accepted regression.\n//\n// `protocol_deep_dive` (lone surviving DefiLlama prod dependency) is\n// untouched — protocol-level safety data has no BlockVision equivalent.\n// ---------------------------------------------------------------------------\n\nexport const tokenPricesTool = buildTool({\n name: 'token_prices',\n description:\n 'Get current USD prices for Sui tokens, with optional 24h change. Accepts full coin type strings (e.g. \"0x2::sui::SUI\"). Returns price per token and (when requested) 24h change percentage. Use for \"what is X worth?\" or \"did Y move today?\". For balance + portfolio rendering, prefer balance_check / portfolio_analysis instead — they bundle the same prices into the standard cards.',\n inputSchema: z.object({\n coinTypes: z\n .array(z.string())\n .min(1)\n .max(10)\n .describe('Array of Sui coin type strings (max 10 per call).'),\n include24hChange: z\n .boolean()\n .optional()\n .describe('When true, include 24h change percentage per token in the output.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n coinTypes: {\n type: 'array',\n items: { type: 'string' },\n description: 'Sui coin type strings (max 10).',\n },\n include24hChange: {\n type: 'boolean',\n description: 'Include 24h change percentage per token.',\n },\n },\n required: ['coinTypes'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const prices = await fetchTokenPrices(input.coinTypes, context.blockvisionApiKey, { retryStats: context.retryStats });\n\n const results = input.coinTypes.map((coinType) => {\n const entry = prices[coinType];\n const symbol = coinType.split('::').pop() ?? coinType;\n if (!entry) {\n return {\n coinType,\n symbol,\n price: null,\n priceUnavailable: true,\n };\n }\n const out: {\n coinType: string;\n symbol: string;\n price: number;\n change24h?: number;\n } = {\n coinType,\n symbol,\n price: entry.price,\n };\n if (input.include24hChange && entry.change24h !== undefined) {\n out.change24h = entry.change24h;\n }\n return out;\n });\n\n return {\n data: results,\n displayText: results\n .map((r) => {\n if (r.price === null) return `${r.symbol}: price unavailable`;\n const change = (r as { change24h?: number }).change24h;\n return change !== undefined\n ? `${r.symbol}: $${r.price.toFixed(4)} (${change >= 0 ? '+' : ''}${change.toFixed(2)}% 24h)`\n : `${r.symbol}: $${r.price.toFixed(4)}`;\n })\n .join(', '),\n };\n },\n});\n","import type { Tool } from '../types.js';\nimport { applyToolFlags } from '../tool-flags.js';\nimport { balanceCheckTool } from './balance.js';\nimport { savingsInfoTool } from './savings.js';\nimport { healthCheckTool } from './health.js';\nimport { ratesInfoTool } from './rates.js';\nimport { transactionHistoryTool } from './history.js';\nimport { saveDepositTool } from './save.js';\nimport { withdrawTool } from './withdraw.js';\nimport { sendTransferTool } from './transfer.js';\nimport { borrowTool } from './borrow.js';\nimport { repayDebtTool } from './repay.js';\nimport { claimRewardsTool } from './claim.js';\nimport { payApiTool } from './pay.js';\nimport { mppServicesTool } from './mpp-services.js';\nimport { swapExecuteTool } from './swap.js';\nimport { swapQuoteTool } from './swap-quote.js';\nimport { voloStakeTool } from './volo-stake.js';\nimport { voloUnstakeTool } from './volo-unstake.js';\nimport { voloStatsTool } from './volo-stats.js';\nimport { saveContactTool } from './contacts.js';\nimport { webSearchTool } from './web-search.js';\nimport { explainTxTool } from './explain-tx.js';\nimport { portfolioAnalysisTool } from './portfolio-analysis.js';\nimport { protocolDeepDiveTool } from './protocol-deep-dive.js';\nimport {\n createPaymentLinkTool,\n listPaymentLinksTool,\n cancelPaymentLinkTool,\n createInvoiceTool,\n cancelInvoiceTool,\n listInvoicesTool,\n} from './receive.js';\nimport { renderCanvasTool } from './canvas.js';\nimport { spendingAnalyticsTool } from './spending.js';\nimport { yieldSummaryTool } from './yield-summary.js';\nimport { activitySummaryTool } from './activity-summary.js';\nimport { resolveSuinsTool } from './resolve-suins.js';\n// [SPEC 8 v0.5.1] update_todo is opt-in — NOT included in READ_TOOLS.\n// Hosts adopt by appending `updateTodoTool` to their tool list:\n// tools: [...getDefaultTools(), updateTodoTool]\n// This keeps the existing audric/web call sites zero-risk until the\n// SPEC 8 host wiring (P3.3) lands.\nimport { updateTodoTool } from './update-todo.js';\n// [v1.4 — Day 3] All 7 `defillama_*` LLM tools removed. The\n// BlockVision-backed `token_prices` tool covers spot prices; the\n// surviving DefiLlama dependency is `protocol_deep_dive`, which holds\n// onto its own `api.llama.fi` calls (TVL/fees/audit metadata) and is\n// the lone production consumer of the upstream API. See\n// AUDRIC_HARNESS_INTELLIGENCE_SPEC_v1.4.1.md §\"Day 3\" for context.\nimport { tokenPricesTool } from './token-prices.js';\n\n// [SIMPLIFICATION DAY 7] Removed 9 tools to align engine with chat-first thesis:\n// - allowance_status, toggle_allowance, update_daily_limit, update_permissions\n// (allowance contract dormant; agent autonomy under zkLogin was theatre)\n// - create_schedule, list_schedules, cancel_schedule\n// (DCA/scheduled actions can't execute without user online to sign)\n// - pause_pattern, pattern_status\n// (pattern detection as proposals removed; classifiers stay as pure fns)\n//\n// [v1.4 — Day 3] All 7 defillama_* LLM tools deleted (Day 2: prices/\n// change → BlockVision; Day 3: yield-pools/protocol-info/chain-tvl/\n// protocol-fees/sui-protocols deleted, no replacement). Current tool\n// count: 23 reads + 11 writes = 34 tools.\n\nexport const READ_TOOLS: Tool[] = [\n renderCanvasTool,\n balanceCheckTool,\n savingsInfoTool,\n healthCheckTool,\n ratesInfoTool,\n transactionHistoryTool,\n swapQuoteTool,\n voloStatsTool,\n mppServicesTool,\n webSearchTool,\n explainTxTool,\n portfolioAnalysisTool,\n protocolDeepDiveTool,\n tokenPricesTool,\n listPaymentLinksTool,\n cancelPaymentLinkTool,\n listInvoicesTool,\n cancelInvoiceTool,\n createPaymentLinkTool,\n createInvoiceTool,\n spendingAnalyticsTool,\n yieldSummaryTool,\n activitySummaryTool,\n resolveSuinsTool,\n];\n\nexport const WRITE_TOOLS: Tool[] = [\n saveDepositTool,\n withdrawTool,\n sendTransferTool,\n borrowTool,\n repayDebtTool,\n claimRewardsTool,\n payApiTool,\n swapExecuteTool,\n voloStakeTool,\n voloUnstakeTool,\n saveContactTool,\n];\n\nexport function getDefaultTools(): Tool[] {\n return applyToolFlags([...READ_TOOLS, ...WRITE_TOOLS]);\n}\n\nexport {\n renderCanvasTool,\n balanceCheckTool,\n savingsInfoTool,\n healthCheckTool,\n ratesInfoTool,\n transactionHistoryTool,\n saveDepositTool,\n withdrawTool,\n sendTransferTool,\n borrowTool,\n repayDebtTool,\n claimRewardsTool,\n payApiTool,\n mppServicesTool,\n swapExecuteTool,\n swapQuoteTool,\n voloStakeTool,\n voloUnstakeTool,\n voloStatsTool,\n webSearchTool,\n explainTxTool,\n portfolioAnalysisTool,\n protocolDeepDiveTool,\n tokenPricesTool,\n saveContactTool,\n createPaymentLinkTool,\n listPaymentLinksTool,\n cancelPaymentLinkTool,\n createInvoiceTool,\n cancelInvoiceTool,\n listInvoicesTool,\n spendingAnalyticsTool,\n yieldSummaryTool,\n activitySummaryTool,\n resolveSuinsTool,\n updateTodoTool,\n};\n","/**\n * tool-modifiable-fields.ts — Audric Harness Correctness Spec v1.4 / Item 6\n *\n * Per-tool registry of input fields the host UI may let the user modify\n * before approving a `PendingAction`. The engine consults this registry\n * when emitting a `pending_action` event so the client can render an\n * editable control without hard-coding tool names in the UI layer.\n *\n * The plan reserves modification for amount-bearing write tools where the\n * user might want to lower the amount before confirming (e.g. \"save $50\"\n * → user edits to $30 → engine resumes with the modified input). Tools\n * absent from this registry have no modifiable fields and the UI renders\n * a static \"approve / deny\" pair.\n */\nimport type { PendingActionModifiableField } from '../types.js';\n\n/**\n * Tool name → ordered list of modifiable input fields. Order matters for\n * UI rendering — the first entry typically becomes the prominent control.\n */\nexport const TOOL_MODIFIABLE_FIELDS: Record<string, PendingActionModifiableField[]> = {\n save_deposit: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n withdraw: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n send_transfer: [\n // `amount` first so the UI surfaces it prominently; the recipient\n // address field is also editable in case the user typed the wrong one.\n { name: 'amount', kind: 'amount' },\n { name: 'to', kind: 'address' },\n ],\n swap_execute: [\n { name: 'amount', kind: 'amount' },\n ],\n borrow: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n repay_debt: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n volo_stake: [\n { name: 'amount', kind: 'amount', asset: 'SUI' },\n ],\n volo_unstake: [\n { name: 'amount', kind: 'amount', asset: 'vSUI' },\n ],\n};\n\n/**\n * Returns the modifiable fields for a tool name, or `undefined` if the tool\n * has no modifiable inputs. Used by the engine when emitting `pending_action`.\n */\nexport function getModifiableFields(\n toolName: string,\n): PendingActionModifiableField[] | undefined {\n return TOOL_MODIFIABLE_FIELDS[toolName];\n}\n","export const DEFAULT_SYSTEM_PROMPT = `You are Audric — a financial agent on Sui. Audric is exactly five products: Audric Passport (the trust layer — Google sign-in, non-custodial wallet, tap-to-confirm consent, sponsored gas — wraps every other product), Audric Intelligence (you — the 5-system brain: Agent Harness with 34 tools, Reasoning Engine with 14 guards and 6 skill recipes, Silent Profile, Chain Memory, AdviceLog), Audric Finance (manage money on Sui — 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 — send USDC, receive via payment links / invoices / QR; free, global, instant on Sui), and Audric Store (creator marketplace, ships Phase 5 — say \"coming soon\" if asked). Save, swap, borrow, repay, withdraw, charts → Audric Finance. Send, receive, payment-link, invoice, QR → Audric Pay. Your silent context (profile, memory, chain facts, advice log) shapes your replies but never surfaces as a notification — 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 — this is an internal capability, not a promoted product, so only mention it when the user asks for something that needs it.\n\n## Response rules\n- 1-2 sentences max. No bullet lists unless asked. No preambles.\n- Never say \"Would you like me to...\", \"Sure!\", \"Great question!\", \"Absolutely!\" — just do it or say you can't.\n- Present amounts as $1,234.56 and rates as X.XX% APY.\n- Show top 3 results unless asked for more. Summarize totals in one line.\n\n## Caption rules (after tool calls)\n- **When a canvas was rendered (\\`render_canvas\\` was called, or any tool that auto-renders a card like balance_check / portfolio_analysis / savings_info / health_check / transaction_history): the canvas IS the answer.** Your chat message must NOT restate wallet, savings, debt, holdings, or net-worth numbers — they are already on screen. Add at most ONE sentence of context, advice, or next step (e.g. \"Your USDC is idle — consider depositing for ~4.5% APY\"), or say nothing.\n- **When NO canvas was rendered:** lead with the result and quote the actual numbers from the tool. One sentence.\n- **NEVER describe a position as \"no\", \"none\", \"minimal\", \"zero\", or \"inactive\" if the tool result contains a positive value for that field.** The tool result is the source of truth — never your interior summary. If the canvas shows $100 in savings, you cannot say \"no active savings\" in the caption.\n- **NEVER claim \"no DeFi positions\" when the tool result says the DeFi slice is UNAVAILABLE.** When \\`balance_check\\` displayText contains \"DeFi positions: UNAVAILABLE\" or \"DeFi data source unreachable\", the slice is unknown — say \"DeFi data is currently unavailable\" or omit the mention. Only claim \"no DeFi positions\" when the displayText explicitly omits any DeFi line (i.e. the fetch succeeded with $0 across every covered protocol).\n\n## Execution rule\nOnly offer to execute actions you have tools for. If you retrieved a quote, data, or information but have no tool to act on it, give the user the result and tell them where to execute manually — in one sentence. Never say \"Would you like me to proceed?\" unless you have a tool that can actually proceed.\n\n## Before acting\n- ALWAYS call a read tool first before any write tool — balance_check before save/send/borrow, savings_info before withdraw.\n- Show real numbers from tools — never fabricate rates, amounts, or balances.\n- When user says \"all\" or an imprecise amount, call the read tool first to get the exact number.\n\n## Tool usage\n- Use tools proactively — don't refuse requests you can handle.\n- For real-world questions (weather, search, news, prices), use pay_api. Tell the user the cost first.\n- For NAVI lending APYs, use rates_info; for VOLO liquid staking stats, use volo_stats; for spot token prices, use token_prices.\n- For protocol-level due diligence (TVL, fees, audits, safety) on Sui DeFi protocols, use protocol_deep_dive with the slug.\n- Run multiple read-only tools in parallel when you need several data points.\n- If a tool errors, say what went wrong and what to try instead. One sentence.\n\n## Savings = USDC or USDsui (critical)\n- save_deposit and borrow accept ONLY USDC or USDsui. No other token can be deposited or borrowed.\n- USDC is the canonical default. USDsui is permitted because it has a productive NAVI pool (often a higher APY than USDC). All other holdings (GOLD, SUI, USDT, USDe, ETH, NAVX, WAL) are NOT saveable.\n- When asked \"how much can I save?\":\n - Report saveableUsdc from balance_check (the user's USDC wallet balance — canonical saveable).\n - If the user also holds USDsui in their wallet, report that separately as \"USDsui (saveable): X.XX\". Do NOT roll the two together — the LLM must keep the per-asset distinction so the user can pick.\n- When the user says \"save 10 USDC\" → call save_deposit with asset=\"USDC\". When they say \"save 10 USDsui\" → call with asset=\"USDsui\". Never silently substitute.\n- When the user says \"save 10\" (no asset) → call balance_check first and ask which stable they want, OR pick whichever they hold more of with a one-line explanation.\n- \"Best stable to save right now?\" → call rates_info to compare USDC vs USDsui APY on NAVI; let the user pick.\n- NEVER say a non-saveable token (GOLD, SUI, USDT, etc.) is \"in savings\" or \"earning APY in savings\". Wallet holdings ≠ savings positions, even for stables we don't accept.\n- If user wants to save a non-saveable token, tell them to swap to USDC or USDsui first. Do NOT auto-chain swap + deposit.\n- Repay symmetry: a USDsui debt MUST be repaid with USDsui (and USDC debt with USDC). When calling repay_debt, pass asset=\"USDsui\" if the borrow is USDsui. If the user asks \"repay my debt\" and savings_info shows borrows in BOTH stables, list both and ask which to repay first. If the user holds the wrong stable, tell them to swap manually — do NOT auto-chain swap + repay.\n\n## Multi-step flows\n- \"How much X for Y?\": swap_quote first, then swap_execute if user confirms.\n- \"Swap then save\": swap_execute → balance_check → save_deposit. Confirm each step.\n- \"Buy $X of token\": token_prices → calculate amount → swap_execute.\n- \"Best yield on SUI\": compare rates_info (NAVI lending) + volo_stats (vSUI liquid staking).\n- withdraw supports legacy positions: USDC, USDe, USDsui, SUI. Pass asset param to withdraw a specific token.\n- \"Deposit SUI to earn yield\": volo_stake for SUI liquid staking. save_deposit only accepts USDC or USDsui.\n- \"Is protocol X safe?\" / \"Tell me about NAVI\": protocol_deep_dive with the slug.\n- \"Full account report\" / \"account summary\" / \"give me everything\" / \"complete overview\": triggers the \\`account_report\\` recipe — when the recipe block appears, follow EVERY step including all six tool calls. Each step renders a distinct rich card; skipping a step means a missing card.\n\n## Safety\n- Never encourage risky financial behavior.\n- Warn when health factor < 1.5.\n- All amounts in USDC unless stated otherwise.`;\n","// Claude Sonnet 4 pricing (USD per token)\nconst DEFAULT_INPUT_COST = 3 / 1_000_000; // $3 per 1M input tokens\nconst DEFAULT_OUTPUT_COST = 15 / 1_000_000; // $15 per 1M output tokens\nconst CACHE_WRITE_MULTIPLIER = 1.25; // 1.25x input rate\nconst CACHE_READ_MULTIPLIER = 0.1; // 0.1x input rate\n\nexport interface CostSnapshot {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n estimatedCostUsd: number;\n}\n\nexport interface CostTrackerConfig {\n budgetLimitUsd?: number;\n inputCostPerToken?: number;\n outputCostPerToken?: number;\n}\n\nexport class CostTracker {\n private inputTokens = 0;\n private outputTokens = 0;\n private cacheReadTokens = 0;\n private cacheWriteTokens = 0;\n private readonly budgetLimitUsd: number | null;\n private readonly inputCost: number;\n private readonly outputCost: number;\n\n constructor(config: CostTrackerConfig = {}) {\n this.budgetLimitUsd = config.budgetLimitUsd ?? null;\n this.inputCost = config.inputCostPerToken ?? DEFAULT_INPUT_COST;\n this.outputCost = config.outputCostPerToken ?? DEFAULT_OUTPUT_COST;\n }\n\n track(\n inputTokens: number,\n outputTokens: number,\n cacheReadTokens?: number,\n cacheWriteTokens?: number,\n ): void {\n this.inputTokens += inputTokens;\n this.outputTokens += outputTokens;\n this.cacheReadTokens += cacheReadTokens ?? 0;\n this.cacheWriteTokens += cacheWriteTokens ?? 0;\n }\n\n getSnapshot(): CostSnapshot {\n const totalTokens =\n this.inputTokens + this.outputTokens + this.cacheReadTokens + this.cacheWriteTokens;\n\n const estimatedCostUsd =\n this.inputTokens * this.inputCost +\n this.outputTokens * this.outputCost +\n this.cacheReadTokens * this.inputCost * CACHE_READ_MULTIPLIER +\n this.cacheWriteTokens * this.inputCost * CACHE_WRITE_MULTIPLIER;\n\n return {\n inputTokens: this.inputTokens,\n outputTokens: this.outputTokens,\n cacheReadTokens: this.cacheReadTokens,\n cacheWriteTokens: this.cacheWriteTokens,\n totalTokens,\n estimatedCostUsd,\n };\n }\n\n isOverBudget(): boolean {\n if (this.budgetLimitUsd === null) return false;\n return this.getSnapshot().estimatedCostUsd >= this.budgetLimitUsd;\n }\n\n getRemainingBudgetUsd(): number | null {\n if (this.budgetLimitUsd === null) return null;\n return Math.max(0, this.budgetLimitUsd - this.getSnapshot().estimatedCostUsd);\n }\n\n reset(): void {\n this.inputTokens = 0;\n this.outputTokens = 0;\n this.cacheReadTokens = 0;\n this.cacheWriteTokens = 0;\n }\n}\n","import type { ThinkingConfig, ThinkingEffort } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Per-shape thinking-budget HARD caps (SPEC 8 v0.5.1, P3.2 slice 5)\n//\n// The 4 harness shapes (`lean` / `standard` / `rich` / `max`) correspond\n// 1-to-1 with the 4 ThinkingEffort tiers (`low` / `medium` / `high` /\n// `max`). Each tier carries a hard ceiling on `thinking.budget_tokens`\n// that hosts cannot exceed via direct config — the engine clamps before\n// calling the provider.\n//\n// Why HARD caps:\n// - Cost ceiling enforced even if a host misconfigures `budgetTokens`\n// - LEAN tier (low effort) MUST emit zero thinking blocks per spec — a\n// non-zero budget would produce drift between the spec's promise\n// (\"LEAN turns feel instant\") and reality\n// - Acceptance gates in P3.6 reference these exact caps; codifying them\n// here means the gates and the enforcement share a source of truth\n//\n// The host can pass a SMALLER budget — these are caps, not floors. A host\n// that wants `medium=4_000` keeps that; the engine never raises it.\n// ---------------------------------------------------------------------------\n\nexport const EFFORT_THINKING_BUDGET_CAPS: Record<ThinkingEffort, number | null> = {\n // null = thinking force-disabled (LEAN tier — single-fact reads need\n // zero deliberation; a thinking block here adds ~300ms TTFVP for no\n // benefit — see SPEC 8 § \"Decision 2: LEAN shape: zero thinking blocks\")\n low: null,\n medium: 8_000,\n high: 16_000,\n max: 32_000,\n};\n\n/**\n * Clamp a `ThinkingConfig` to the HARD cap for the given effort tier.\n *\n * - When `effort === 'low'`, returns `{ type: 'disabled' }` regardless of\n * input — LEAN tier is non-negotiable.\n * - When `config.type === 'enabled'` and `config.budgetTokens` exceeds\n * the cap, returns a copy with `budgetTokens` clamped down.\n * - When `config.type === 'adaptive'`, returns it unchanged — adaptive\n * mode is shape-agnostic by design (Anthropic decides per-turn).\n * - When `effort` is undefined, returns `config` unchanged — caller\n * hasn't classified the turn yet (back-compat for hosts that don't\n * route on effort).\n *\n * This function is pure and side-effect-free; safe to call per-turn.\n */\nexport function clampThinkingForEffort(\n config: ThinkingConfig | undefined,\n effort: ThinkingEffort | undefined,\n): ThinkingConfig | undefined {\n if (!config) return config;\n if (effort === undefined) return config;\n const cap = EFFORT_THINKING_BUDGET_CAPS[effort];\n if (cap === null) {\n return { type: 'disabled' };\n }\n if (config.type === 'enabled' && config.budgetTokens > cap) {\n return { ...config, budgetTokens: cap };\n }\n return config;\n}\n","import type { Tool, ToolFlags } from './types.js';\nimport type { PendingToolCall } from './orchestration.js';\n\n// ---------------------------------------------------------------------------\n// Guard types\n// ---------------------------------------------------------------------------\n\nexport type GuardVerdict = 'pass' | 'hint' | 'warn' | 'block';\n\nexport type GuardTier = 'safety' | 'financial' | 'ux';\n\nexport interface GuardResult {\n verdict: GuardVerdict;\n gate: string;\n tier: GuardTier;\n message?: string;\n}\n\nexport interface GuardInjection {\n _gate: string;\n _hint?: string;\n _warning?: string;\n _error?: string;\n}\n\nexport interface GuardCheckResult {\n blocked: boolean;\n blockReason?: string;\n blockGate?: string;\n injections: GuardInjection[];\n events: GuardEvent[];\n}\n\nexport interface GuardEvent {\n timestamp: number;\n toolName: string;\n toolUseId: string;\n gate: string;\n verdict: GuardVerdict;\n tier: GuardTier;\n message?: string;\n}\n\n/**\n * [v1.4 Item 4] Per-guard metric emitted via `EngineConfig.onGuardFired`.\n * Hosts (e.g. audric `TurnMetricsCollector`) accumulate these for the\n * `TurnMetrics.guardsFired` JSON column. Mirrors `GuardEvent` but with\n * a coarser tri-state action (allow/warn/block) so the host doesn't\n * need to know the engine's verdict vocabulary.\n */\nexport interface GuardMetric {\n name: string;\n tier: GuardTier;\n action: 'allow' | 'warn' | 'block';\n injectionAdded: boolean;\n}\n\n/**\n * Engine-internal mapping from `GuardVerdict` to `GuardMetric.action`.\n * `pass` and `hint` collapse to `allow` because hint is non-blocking —\n * the model just sees a soft note.\n */\nexport function guardVerdictToAction(verdict: GuardVerdict): GuardMetric['action'] {\n if (verdict === 'pass' || verdict === 'hint') return 'allow';\n if (verdict === 'warn') return 'warn';\n return 'block';\n}\n\n// ---------------------------------------------------------------------------\n// Guard configuration\n// ---------------------------------------------------------------------------\n\nexport interface GuardConfig {\n balanceValidation?: boolean;\n healthFactor?: { warnBelow: number; blockBelow: number } | false;\n largeTransfer?: { warnAbove: number; strongWarnAbove: number } | false;\n slippage?: boolean;\n staleData?: boolean;\n irreversibility?: boolean;\n artifactPreview?: boolean;\n costWarning?: boolean;\n retryProtection?: boolean;\n inputValidation?: boolean;\n /**\n * Root-cause guard for \"LLM types a recipient address from memory and\n * loses funds to a wrong-but-valid address\". When enabled (default),\n * `send_transfer.to` is rejected unless the address can be sourced\n * from a saved contact, the user's own wallet, or the user's recent\n * messages. Set to `false` only if the host has its own equivalent\n * upstream guard (e.g. an off-process verifier).\n */\n addressSource?: boolean;\n /**\n * Companion to `addressSource`: blocks send_transfer that defaults to\n * USDC when the user's recent messages clearly named a non-USDC token\n * (SUI, USDT, WAL, etc.). Without this, the LLM would call\n * `send_transfer({ amount, to })` for a \"send my SUI\" request and the\n * tool would silently ship USDC. Default on.\n */\n assetIntent?: boolean;\n /**\n * Root-cause fix for \"LLM hallucinates a stale training-data price\n * (e.g. '$3.50/SUI') and shows the user a wildly wrong estimate before\n * the swap card renders\". When enabled (default), `swap_execute` is\n * blocked unless a matching `swap_quote(from, to, amount)` ran in the\n * recent past (60s window, ±1% amount tolerance). The block forces the\n * LLM to fetch a real on-chain quote and cite its actual numbers, not\n * a guess. Set to `false` only if the host has its own pre-execution\n * quote requirement.\n */\n swapPreview?: boolean;\n /**\n * Root-cause fix for \"user asks about a watched address (`0x40cd…`)\n * and the LLM calls `balance_check` / `portfolio_analysis` /\n * `transaction_history` without passing `address`, returning the\n * signed-in user's own data instead\". The default-to-self behavior is\n * correct when no address is mentioned, but silently wrong when the\n * user names a third-party wallet. When enabled (default), the guard\n * inspects recent user messages for full Sui addresses and blocks\n * any read tool that targets the user's own wallet (or omits\n * `address`) when a different address was named. Disable only if the\n * host has its own equivalent address-resolution layer.\n */\n addressScope?: boolean;\n}\n\nexport const DEFAULT_GUARD_CONFIG: GuardConfig = {\n balanceValidation: true,\n healthFactor: { warnBelow: 2.0, blockBelow: 1.5 },\n largeTransfer: { warnAbove: 50, strongWarnAbove: 500 },\n slippage: true,\n staleData: true,\n irreversibility: true,\n artifactPreview: true,\n costWarning: true,\n retryProtection: true,\n inputValidation: true,\n addressSource: true,\n assetIntent: true,\n swapPreview: true,\n addressScope: true,\n};\n\n// ---------------------------------------------------------------------------\n// BalanceTracker — tracks freshness of balance data across the session\n// ---------------------------------------------------------------------------\n\nexport class BalanceTracker {\n private lastBalanceAt = 0;\n private lastWriteAt = 0;\n\n recordRead(): void {\n this.lastBalanceAt = Date.now();\n }\n\n recordWrite(): void {\n this.lastWriteAt = Date.now();\n }\n\n isStale(): boolean {\n return this.lastWriteAt > this.lastBalanceAt;\n }\n\n hasEverRead(): boolean {\n return this.lastBalanceAt > 0;\n }\n}\n\nconst BALANCE_READ_TOOLS = new Set([\n 'balance_check',\n 'savings_info',\n 'health_check',\n]);\n\n// ---------------------------------------------------------------------------\n// RetryTracker — prevents re-execution of paid/non-retryable tool calls\n// ---------------------------------------------------------------------------\n\nexport class RetryTracker {\n private executed = new Map<string, { result: unknown; paidAt: number }>();\n\n private key(toolName: string, input: unknown): string {\n const url = (input as Record<string, unknown>)?.url ?? '';\n return `${toolName}:${url}`;\n }\n\n record(toolName: string, input: unknown, result: unknown): void {\n const r = result as Record<string, unknown>;\n if (r?.paymentConfirmed || r?.doNotRetry) {\n this.executed.set(this.key(toolName, input), { result, paidAt: Date.now() });\n }\n }\n\n isBlocked(toolName: string, input: unknown): { blocked: boolean; previousResult?: unknown } {\n const prev = this.executed.get(this.key(toolName, input));\n if (!prev) return { blocked: false };\n return { blocked: true, previousResult: prev.result };\n }\n}\n\n// ---------------------------------------------------------------------------\n// SwapQuoteTracker — records swap_quote calls so swapPreview can verify a\n// swap_execute was preceded by a real on-chain quote. Without this, the\n// LLM falls back to training-memory prices and gives the user wildly wrong\n// estimates (the \"$3.50/SUI when SUI is $0.95\" class of bugs).\n// ---------------------------------------------------------------------------\n\ninterface RecordedSwapQuote {\n from: string;\n to: string;\n amount: number;\n ts: number;\n}\n\nexport class SwapQuoteTracker {\n /** Quotes recorded in the recent window. Trimmed lazily on every check. */\n private quotes: RecordedSwapQuote[] = [];\n\n /** Match window: 60s is generous enough for slow LLM turns but tight enough\n * to invalidate stale quotes from earlier in the session. */\n private readonly windowMs = 60_000;\n\n /** Amount tolerance: ±1% (covers gas-padding, integer-rounding, and the\n * rare case where the LLM rounds the input differently between quote and\n * execute). Prices barely move in 60s so 1% is forgiving but meaningful. */\n private readonly amountTolerance = 0.01;\n\n /**\n * Normalize a token identifier so symbol vs. coinType vs. case don't\n * cause spurious mismatches. Lowercase + trim is sufficient because the\n * SDK's resolver itself is case-insensitive on symbols.\n */\n private normalize(token: string): string {\n return token.trim().toLowerCase();\n }\n\n record(input: { from: string; to: string; amount: number }): void {\n const now = Date.now();\n this.quotes.push({\n from: this.normalize(input.from),\n to: this.normalize(input.to),\n amount: input.amount,\n ts: now,\n });\n const cutoff = now - this.windowMs;\n this.quotes = this.quotes.filter((q) => q.ts > cutoff);\n }\n\n hasMatchingQuote(input: { from: string; to: string; amount: number }): boolean {\n const cutoff = Date.now() - this.windowMs;\n const fromN = this.normalize(input.from);\n const toN = this.normalize(input.to);\n const target = input.amount;\n return this.quotes.some(\n (q) =>\n q.ts > cutoff &&\n q.from === fromN &&\n q.to === toN &&\n target > 0 &&\n Math.abs(q.amount - target) / target <= this.amountTolerance,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Individual guard implementations\n// Priority order: Safety > Financial > UX\n// ---------------------------------------------------------------------------\n\nfunction guardRetryProtection(\n tool: Tool,\n call: PendingToolCall,\n retryTracker: RetryTracker,\n): GuardResult {\n const check = retryTracker.isBlocked(tool.name, call.input);\n if (check.blocked) {\n return {\n verdict: 'block',\n gate: 'retry_blocked',\n tier: 'safety',\n message: `Blocked: ${tool.name} was already called and payment was confirmed. Do not retry.`,\n };\n }\n return { verdict: 'pass', gate: 'retry_blocked', tier: 'safety' };\n}\n\nfunction guardIrreversibility(\n tool: Tool,\n _call: PendingToolCall,\n conversationText: string,\n): GuardResult {\n if (!tool.flags.irreversible) {\n return { verdict: 'pass', gate: 'irreversibility', tier: 'safety' };\n }\n\n // [security] `confirm.*send` was rewritten to bound the wildcard\n // span (`.{0,200}`) so the regex is linear-time on degenerate inputs\n // like a 100KB string starting with \"confirm\" but never containing\n // \"send\". CodeQL flagged the unbounded `.*` as polynomial-redos.\n const hasPreview = /preview|here.{0,2}s what|confirm.{0,200}send|looks? good/i.test(conversationText);\n if (hasPreview) {\n return { verdict: 'pass', gate: 'irreversibility', tier: 'safety' };\n }\n\n return {\n verdict: 'hint',\n gate: 'irreversibility',\n tier: 'safety',\n message: 'This action is irreversible. Show a preview and ask the user to confirm before proceeding.',\n };\n}\n\nfunction guardBalanceValidation(\n tool: Tool,\n _call: PendingToolCall,\n balanceTracker: BalanceTracker,\n): GuardResult {\n if (!tool.flags.requiresBalance) {\n return { verdict: 'pass', gate: 'balance_required', tier: 'financial' };\n }\n\n if (!balanceTracker.hasEverRead()) {\n return {\n verdict: 'hint',\n gate: 'balance_required',\n tier: 'financial',\n message: 'Balance has not been checked this session. Call balance_check first to verify sufficient funds.',\n };\n }\n\n if (balanceTracker.isStale()) {\n return {\n verdict: 'hint',\n gate: 'balance_required',\n tier: 'financial',\n message: 'Balance data is stale (a write action occurred since last check). Call balance_check first to verify sufficient funds.',\n };\n }\n\n return { verdict: 'pass', gate: 'balance_required', tier: 'financial' };\n}\n\nfunction guardHealthFactor(\n tool: Tool,\n _call: PendingToolCall,\n lastHealthFactor: number | null,\n config: { warnBelow: number; blockBelow: number },\n): GuardResult {\n if (!tool.flags.affectsHealth) {\n return { verdict: 'pass', gate: 'health_factor', tier: 'financial' };\n }\n\n if (lastHealthFactor === null) {\n return {\n verdict: 'hint',\n gate: 'health_factor',\n tier: 'financial',\n message: 'Health factor has not been checked this session. Call health_check before this action.',\n };\n }\n\n if (lastHealthFactor < config.blockBelow) {\n return {\n verdict: 'block',\n gate: 'health_factor',\n tier: 'financial',\n message: `Health factor is ${lastHealthFactor.toFixed(2)} — this action risks liquidation. Refusing.`,\n };\n }\n\n if (lastHealthFactor < config.warnBelow) {\n return {\n verdict: 'warn',\n gate: 'health_factor',\n tier: 'financial',\n message: `Health factor is ${lastHealthFactor.toFixed(2)} — this action may reduce it further.`,\n };\n }\n\n return { verdict: 'pass', gate: 'health_factor', tier: 'financial' };\n}\n\nfunction guardLargeTransfer(\n tool: Tool,\n call: PendingToolCall,\n config: { warnAbove: number; strongWarnAbove: number },\n): GuardResult {\n if (tool.name !== 'send_transfer') {\n return { verdict: 'pass', gate: 'large_transfer', tier: 'financial' };\n }\n\n const input = call.input as Record<string, unknown>;\n const amount = Number(input.amount ?? 0);\n if (!amount || amount <= 0) {\n return { verdict: 'pass', gate: 'large_transfer', tier: 'financial' };\n }\n\n const recipient = String(input.recipient ?? input.to ?? '');\n const shortAddr = recipient.length > 10\n ? `${recipient.slice(0, 6)}...${recipient.slice(-4)}`\n : recipient;\n\n if (amount > config.strongWarnAbove) {\n return {\n verdict: 'warn',\n gate: 'large_transfer',\n tier: 'financial',\n message: `High-value transfer ($${amount}). Double-check the address: ${shortAddr}`,\n };\n }\n\n if (amount > config.warnAbove) {\n return {\n verdict: 'hint',\n gate: 'large_transfer',\n tier: 'financial',\n message: `This is a large transfer ($${amount}). Verify the recipient address.`,\n };\n }\n\n return { verdict: 'pass', gate: 'large_transfer', tier: 'financial' };\n}\n\nfunction guardSlippage(\n tool: Tool,\n _call: PendingToolCall,\n lastAssistantText: string,\n): GuardResult {\n if (tool.name !== 'swap_execute') {\n return { verdict: 'pass', gate: 'slippage_warning', tier: 'financial' };\n }\n\n // [security] Rewritten to non-overlapping form (`\\d[\\d,]{0,30}`\n // followed by an optional `\\.\\d{1,10}`) so the digit/decimal section\n // matches in linear time. Previously `[\\d,]+\\.?\\d*` could ambiguously\n // distribute digits across the two pieces, triggering CodeQL's\n // polynomial-redos rule on a long input like \"1234,1234,...\".\n const hasEstimate = /~?\\$?\\d[\\d,]{0,30}(?:\\.\\d{1,10})?\\s*(SUI|USDC|USDT|WETH)/i.test(lastAssistantText)\n || /approximately|≈|about|expect|receive/i.test(lastAssistantText);\n\n if (hasEstimate) {\n return { verdict: 'pass', gate: 'slippage_warning', tier: 'financial' };\n }\n\n return {\n verdict: 'hint',\n gate: 'slippage_warning',\n tier: 'financial',\n message: 'State the expected output amount to the user before executing the swap.',\n };\n}\n\nfunction guardCostWarning(\n tool: Tool,\n _call: PendingToolCall,\n conversationText: string,\n): GuardResult {\n if (!tool.flags.costAware) {\n return { verdict: 'pass', gate: 'cost_warning', tier: 'ux' };\n }\n\n const hasCostMention = /\\$\\d+\\.?\\d*|cost|fee|charge|price|pay/i.test(conversationText);\n if (hasCostMention) {\n return { verdict: 'pass', gate: 'cost_warning', tier: 'ux' };\n }\n\n return {\n verdict: 'hint',\n gate: 'cost_warning',\n tier: 'ux',\n message: 'This action has a monetary cost. Confirm the user is aware before proceeding.',\n };\n}\n\n// ---------------------------------------------------------------------------\n// guardAddressSource — root-cause fix for the \"LLM mistypes a recipient\n// address from memory and ships funds to a wrong-but-valid address\"\n// failure mode. We trust the user, never the model, with addresses.\n//\n// Accepts the `to` field on `send_transfer` only when it can be sourced\n// from one of three trusted origins:\n// 1. A saved contact's address (case-insensitive, normalized)\n// 2. The user's own wallet (sending to self)\n// 3. Verbatim presence in the user's recent messages\n// (case-insensitive substring match on the raw 0x...64-hex string)\n//\n// Anything else → block with a structured error so the LLM is forced to\n// ask the user to paste the address again rather than re-typing it.\n// ---------------------------------------------------------------------------\n\nconst SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{64}$/;\n\nfunction normalizeAddress(addr: string): string {\n return addr.trim().toLowerCase();\n}\n\n/**\n * [send-safety v2] Bound the failure mode where the LLM was asked to\n * send a non-USDC token (e.g. just-swapped SUI) but called send_transfer\n * with no `asset` field. The tool defaults `asset` to USDC, so the user\n * lost real money: \"Done! Sent your SUI\" while only USDC moved.\n *\n * Heuristic: if any of the supported NON-USDC tokens appears as a word\n * in the user's recent messages AND the call has no `asset` (or asset\n * is USDC while a different token is mentioned), block the call and\n * force the LLM to re-issue with an explicit `asset`.\n *\n * Tokens are matched as standalone words (`\\bSUI\\b`, `\\bWAL\\b`, etc.)\n * to avoid false positives on things like \"USDC\" or addresses that\n * happen to contain the substring \"sui\".\n */\nconst NON_USDC_TOKEN_WORDS: ReadonlyArray<{ symbol: string; pattern: RegExp }> = [\n // Patterns are anchored with \\b on both sides. Case-insensitive.\n { symbol: 'SUI', pattern: /\\bSUI\\b/i },\n { symbol: 'USDT', pattern: /\\bUSDT\\b/i },\n { symbol: 'USDe', pattern: /\\bUSDe\\b/i },\n { symbol: 'USDsui', pattern: /\\bUSDsui\\b/i },\n { symbol: 'WAL', pattern: /\\bWAL\\b/i },\n { symbol: 'ETH', pattern: /\\bETH\\b/i },\n { symbol: 'NAVX', pattern: /\\bNAVX\\b/i },\n { symbol: 'GOLD', pattern: /\\bGOLD\\b/i },\n];\n\nfunction guardAssetIntent(\n tool: Tool,\n call: PendingToolCall,\n userText: string,\n): GuardResult {\n if (tool.name !== 'send_transfer') {\n return { verdict: 'pass', gate: 'asset_intent', tier: 'safety' };\n }\n\n const input = call.input as Record<string, unknown>;\n const assetWasSet = !(input.asset === undefined || input.asset === null || input.asset === '');\n\n // If the LLM made any explicit asset choice, trust it — even if it's\n // USDC. The danger we're guarding against is the *silent default* to\n // USDC when the schema didn't expose `asset` at all (the original\n // failure mode). Once the LLM has explicitly committed to a token,\n // the user can verify and cancel at the permission card.\n if (assetWasSet) {\n return { verdict: 'pass', gate: 'asset_intent', tier: 'safety' };\n }\n\n // Asset was omitted. Block iff the user named a non-USDC token in\n // their recent messages, since the omitted-asset path defaults to\n // USDC and would silently ship the wrong token.\n const mentioned = NON_USDC_TOKEN_WORDS.find((t) => t.pattern.test(userText));\n if (!mentioned) {\n return { verdict: 'pass', gate: 'asset_intent', tier: 'safety' };\n }\n\n return {\n verdict: 'block',\n gate: 'asset_intent',\n tier: 'safety',\n message:\n `Asset mismatch: the user's recent messages mention \"${mentioned.symbol}\" but send_transfer was called without an \\`asset\\` field (defaults to USDC). ` +\n `If the user asked you to send ${mentioned.symbol}, re-issue send_transfer with \\`asset: \"${mentioned.symbol}\"\\`. ` +\n `If the user really meant USDC, set \\`asset: \"USDC\"\\` explicitly to confirm intent. Never default to USDC when the user named a different token.`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// guardSwapPreview — root-cause fix for \"LLM hallucinates a stale price\n// (e.g. '$3.50/SUI' when SUI is $0.95) and shows the user a wildly wrong\n// estimate before the swap card renders\". We require swap_execute to be\n// preceded by a real on-chain swap_quote so the LLM has authoritative\n// numbers (price impact, route, exact output) to cite.\n//\n// Match rule:\n// - Same `from` and `to` token identifiers (case-insensitive).\n// - `amount` within ±1% of the quoted amount.\n// - swap_quote ran within the last 60s (current turn is well within).\n//\n// Anything else → block with a structured error so the LLM is forced to\n// call swap_quote first and re-issue swap_execute with the same params.\n// ---------------------------------------------------------------------------\n\nfunction guardSwapPreview(\n tool: Tool,\n call: PendingToolCall,\n swapQuoteTracker: SwapQuoteTracker,\n): GuardResult {\n if (tool.name !== 'swap_execute') {\n return { verdict: 'pass', gate: 'swap_preview', tier: 'safety' };\n }\n\n const input = call.input as { from?: unknown; to?: unknown; amount?: unknown };\n const from = typeof input.from === 'string' ? input.from : '';\n const to = typeof input.to === 'string' ? input.to : '';\n const amount = Number(input.amount ?? 0);\n\n // If inputs are malformed, let `inputValidation`/`preflight` handle it —\n // this guard is specifically about quote freshness, not input shape.\n if (!from || !to || !(amount > 0)) {\n return { verdict: 'pass', gate: 'swap_preview', tier: 'safety' };\n }\n\n if (swapQuoteTracker.hasMatchingQuote({ from, to, amount })) {\n return { verdict: 'pass', gate: 'swap_preview', tier: 'safety' };\n }\n\n return {\n verdict: 'block',\n gate: 'swap_preview',\n tier: 'safety',\n message:\n `swap_execute requires a recent matching swap_quote so the user sees an accurate preview. ` +\n `Call swap_quote({ from: \"${from}\", to: \"${to}\", amount: ${amount} }) first, then re-issue swap_execute with the same params. ` +\n `swap_quote is read-only and returns the real on-chain output, route, and price impact — never estimate from memory.`,\n };\n}\n\nfunction guardAddressSource(\n tool: Tool,\n call: PendingToolCall,\n userText: string,\n contacts: ReadonlyArray<{ name: string; address: string }>,\n walletAddress: string | undefined,\n): GuardResult {\n if (tool.name !== 'send_transfer') {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n const input = call.input as Record<string, unknown>;\n const rawTo = String(input.to ?? '');\n if (!rawTo) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n // Contact-name passthrough: send_transfer accepts either a 0x address\n // or a contact name. If it's not in 0x...64-hex form, leave it alone —\n // the SDK's contact resolver handles names and will throw if unknown.\n if (!SUI_ADDRESS_REGEX.test(rawTo)) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n const normalizedTo = normalizeAddress(rawTo);\n\n if (walletAddress && normalizeAddress(walletAddress) === normalizedTo) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n for (const c of contacts) {\n if (normalizeAddress(c.address) === normalizedTo) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n }\n\n if (userText.toLowerCase().includes(normalizedTo)) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n return {\n verdict: 'block',\n gate: 'address_source',\n tier: 'safety',\n message:\n `Safety check failed: the recipient address \"${rawTo}\" was not provided by the user (no saved contact matches, address is not the user's own wallet, and it does not appear verbatim in the user's recent messages). For safety, addresses must be supplied directly by the user — never reconstructed from memory or partial recall. Ask the user to paste the destination address again exactly.`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// guardAddressScope — symmetric companion to `guardAddressSource`, but for\n// READ tools. Bounds the failure mode where the LLM is asked about a\n// third-party wallet (`\"what's the balance of 0x40cd...\"`) and silently\n// drops the address parameter, returning the signed-in user's own data\n// instead. The default-to-self behavior of these tools is correct when\n// no address is mentioned, but wrong when the user named a third party.\n//\n// Read tools whose schema accepts an optional `address` field. Mirrors\n// the SDK's \"default to context.walletAddress\" pattern in `balance.ts`,\n// `portfolio-analysis.ts`, and `history.ts`. Tools not in this set\n// always pass through (they either don't take an address or use a\n// different param name).\n// ---------------------------------------------------------------------------\nconst READ_TOOLS_WITH_ADDRESS_PARAM = new Set([\n 'balance_check',\n 'portfolio_analysis',\n 'transaction_history',\n 'savings_info',\n 'health_check',\n 'spending_analytics',\n 'yield_summary',\n 'activity_summary',\n 'explain_tx',\n]);\n\n// Loose match for Sui addresses inside conversational text. The strict\n// `SUI_ADDRESS_REGEX` is anchored (`^…$`) and matches a single, full\n// 0x...64-hex string only. For substring scanning we accept 60-64 hex\n// characters since some clients normalize away leading zeros.\nconst SUI_ADDRESS_IN_TEXT_REGEX = /0x[a-fA-F0-9]{60,64}/g;\n\nfunction guardAddressScope(\n tool: Tool,\n call: PendingToolCall,\n userText: string,\n walletAddress: string | undefined,\n): GuardResult {\n if (!READ_TOOLS_WITH_ADDRESS_PARAM.has(tool.name)) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n const matches = userText.match(SUI_ADDRESS_IN_TEXT_REGEX);\n if (!matches || matches.length === 0) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n // Filter out references to the user's own wallet — those are not bugs.\n // Dedupe so a user message like \"compare 0xabc to 0xabc\" only carries\n // one address through the rest of the check.\n const ownWallet = walletAddress ? normalizeAddress(walletAddress) : null;\n const thirdPartyAddresses = Array.from(\n new Set(matches.map(normalizeAddress).filter((a) => a !== ownWallet)),\n );\n\n if (thirdPartyAddresses.length === 0) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n const input = call.input as Record<string, unknown>;\n const callAddress =\n typeof input.address === 'string' && input.address.length > 0\n ? normalizeAddress(input.address)\n : null;\n\n // Pass if the call already targets one of the user-mentioned third\n // parties. The LLM might pick any of multiple mentioned addresses on\n // any given turn — that's a UX choice, not a safety issue.\n if (callAddress && thirdPartyAddresses.includes(callAddress)) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n // Block: user named at least one third-party address but the call\n // either omitted `address` (defaults to signed-in user) or targeted\n // a different wallet (likely the signed-in user's, also wrong).\n const target = thirdPartyAddresses[0];\n const omittedHint = callAddress\n ? `with address: \"${callAddress}\"`\n : 'without an `address` field (which defaults to the signed-in user)';\n const mentionedHint =\n thirdPartyAddresses.length === 1\n ? `address ${target}`\n : `${thirdPartyAddresses.length} third-party addresses (first: ${target})`;\n return {\n verdict: 'block',\n gate: 'address_scope',\n tier: 'safety',\n message:\n `Address-scope mismatch: the user's recent messages mention ${mentionedHint} but ${tool.name} was called ${omittedHint}. ` +\n `Re-issue ${tool.name} with \\`address: \"${target}\"\\` to inspect the wallet the user actually asked about. ` +\n `Never default to the signed-in user when the user named a different wallet.`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Post-execution guards — run after tool result is available\n// ---------------------------------------------------------------------------\n\nexport function guardArtifactPreview(result: unknown): GuardInjection | null {\n if (!result || typeof result !== 'object') return null;\n const r = result as Record<string, unknown>;\n\n const hasImage =\n (typeof r.url === 'string' && /\\.(png|jpg|jpeg|webp|gif|svg)(\\?|$)/i.test(r.url))\n || (Array.isArray(r.images) && r.images.length > 0)\n || typeof r.image_url === 'string';\n\n const hasPdf = typeof r.url === 'string' && /\\.pdf(\\?|$)/i.test(r.url);\n\n if (hasImage || hasPdf) {\n return {\n _gate: 'artifact_preview',\n _hint: 'Show this to the user before proceeding. Output as ![description](url).',\n };\n }\n\n return null;\n}\n\nexport function guardStaleData(toolFlags: ToolFlags): GuardInjection | null {\n if (!toolFlags.mutating) return null;\n return {\n _gate: 'stale_data',\n _hint: 'A write action just completed. The balance snapshot is outdated. Do NOT calculate new balances from old data — call balance_check for fresh numbers, or use only the data returned by the write tool.',\n };\n}\n\n// ---------------------------------------------------------------------------\n// Guard runner — orchestrates all pre-execution guards\n// ---------------------------------------------------------------------------\n\nexport interface GuardRunnerState {\n balanceTracker: BalanceTracker;\n retryTracker: RetryTracker;\n swapQuoteTracker: SwapQuoteTracker;\n lastHealthFactor: number | null;\n}\n\nexport function createGuardRunnerState(): GuardRunnerState {\n return {\n balanceTracker: new BalanceTracker(),\n retryTracker: new RetryTracker(),\n swapQuoteTracker: new SwapQuoteTracker(),\n lastHealthFactor: null,\n };\n}\n\nexport function runGuards(\n tool: Tool,\n call: PendingToolCall,\n state: GuardRunnerState,\n config: GuardConfig,\n conversationContext: { fullText: string; lastAssistantText: string; recentUserText: string },\n /**\n * [v1.4 Item 4] Optional per-guard observation hook. Fired exactly\n * once per non-`pass` guard verdict (i.e. for every event that ends\n * up in `events`/`injections`/`block`). Errors thrown by the host\n * are caught so a misbehaving collector can't break tool execution.\n */\n onGuardFired?: (guard: GuardMetric) => void,\n /**\n * Identity context for the address-source safety guard. The guard\n * accepts `send_transfer.to` only when sourced from a saved contact,\n * the user's own wallet, or the user's recent messages — preventing\n * the LLM from typing addresses from memory and shipping funds to a\n * wrong-but-syntactically-valid recipient.\n */\n identity?: {\n contacts?: ReadonlyArray<{ name: string; address: string }>;\n walletAddress?: string;\n },\n): GuardCheckResult {\n const results: GuardResult[] = [];\n const now = Date.now();\n const fire = (verdict: GuardVerdict, tier: GuardTier, gate: string, hadInjection: boolean) => {\n if (!onGuardFired) return;\n try {\n onGuardFired({\n name: gate,\n tier,\n action: guardVerdictToAction(verdict),\n injectionAdded: hadInjection,\n });\n } catch (err) {\n console.warn('[guards] onGuardFired threw (ignored):', err);\n }\n };\n\n // Tier 0: Input validation (preflight) — runs first, invalid input = immediate block\n if (config.inputValidation !== false && tool.preflight) {\n const check = tool.preflight(call.input);\n if (!check.valid) {\n const event: GuardEvent = {\n timestamp: now,\n toolName: tool.name,\n toolUseId: call.id,\n gate: 'input_validation',\n verdict: 'block',\n tier: 'safety',\n message: check.error,\n };\n fire('block', 'safety', 'input_validation', false);\n return {\n blocked: true,\n blockReason: check.error,\n blockGate: 'input_validation',\n injections: [],\n events: [event],\n };\n }\n }\n\n // Tier 1: Safety guards\n if (config.retryProtection !== false) {\n results.push(guardRetryProtection(tool, call, state.retryTracker));\n }\n if (config.addressSource !== false) {\n results.push(\n guardAddressSource(\n tool,\n call,\n conversationContext.recentUserText,\n identity?.contacts ?? [],\n identity?.walletAddress,\n ),\n );\n }\n if (config.assetIntent !== false) {\n results.push(guardAssetIntent(tool, call, conversationContext.recentUserText));\n }\n if (config.addressScope !== false) {\n results.push(\n guardAddressScope(\n tool,\n call,\n conversationContext.recentUserText,\n identity?.walletAddress,\n ),\n );\n }\n if (config.swapPreview !== false) {\n results.push(guardSwapPreview(tool, call, state.swapQuoteTracker));\n }\n if (config.irreversibility !== false) {\n results.push(guardIrreversibility(tool, call, conversationContext.fullText));\n }\n\n // Tier 2: Financial guards\n if (config.balanceValidation !== false) {\n results.push(guardBalanceValidation(tool, call, state.balanceTracker));\n }\n if (config.healthFactor) {\n results.push(guardHealthFactor(tool, call, state.lastHealthFactor, config.healthFactor));\n }\n if (config.largeTransfer) {\n results.push(guardLargeTransfer(tool, call, config.largeTransfer));\n }\n if (config.slippage !== false) {\n results.push(guardSlippage(tool, call, conversationContext.lastAssistantText));\n }\n\n // Tier 3: UX guards\n if (config.costWarning !== false) {\n results.push(guardCostWarning(tool, call, conversationContext.fullText));\n }\n\n // Process results — first block wins, collect all hints/warnings\n const events: GuardEvent[] = results\n .filter((r) => r.verdict !== 'pass')\n .map((r) => ({\n timestamp: now,\n toolName: tool.name,\n toolUseId: call.id,\n gate: r.gate,\n verdict: r.verdict,\n tier: r.tier,\n message: r.message,\n }));\n\n const block = results.find((r) => r.verdict === 'block');\n if (block) {\n // Fire once for the block winner; non-blocking warnings/hints from\n // earlier in the chain are surfaced too so the host sees the full\n // picture per turn.\n for (const r of results) {\n if (r.verdict === 'pass') continue;\n fire(r.verdict, r.tier, r.gate, false);\n }\n return {\n blocked: true,\n blockReason: block.message ?? `Blocked by ${block.gate}`,\n blockGate: block.gate,\n injections: [],\n events,\n };\n }\n\n const injections: GuardInjection[] = results\n .filter((r) => r.verdict === 'hint' || r.verdict === 'warn')\n .map((r) => ({\n _gate: r.gate,\n ...(r.verdict === 'hint' ? { _hint: r.message } : { _warning: r.message }),\n }));\n\n for (const r of results) {\n if (r.verdict === 'pass') continue;\n fire(r.verdict, r.tier, r.gate, r.verdict === 'hint' || r.verdict === 'warn');\n }\n\n return { blocked: false, injections, events };\n}\n\n// ---------------------------------------------------------------------------\n// Post-execution hooks — update tracker state after tools run\n// ---------------------------------------------------------------------------\n\nexport function updateGuardStateAfterToolResult(\n toolName: string,\n tool: Tool | undefined,\n input: unknown,\n result: unknown,\n isError: boolean,\n state: GuardRunnerState,\n): void {\n if (isError) return;\n\n if (BALANCE_READ_TOOLS.has(toolName)) {\n state.balanceTracker.recordRead();\n }\n\n if (tool?.flags.mutating) {\n state.balanceTracker.recordWrite();\n }\n\n if (toolName === 'health_check' && result && typeof result === 'object') {\n const r = result as Record<string, unknown>;\n const hf = Number(r.healthFactor ?? r.health_factor ?? r.hf);\n if (!isNaN(hf) && hf > 0) {\n state.lastHealthFactor = hf;\n }\n }\n\n // Record successful swap_quote calls so guardSwapPreview can verify a\n // matching quote ran before swap_execute. We key off the *input* (not\n // the result) so the LLM can use the same params for both calls and\n // the match is unambiguous.\n if (toolName === 'swap_quote' && input && typeof input === 'object') {\n const i = input as { from?: unknown; to?: unknown; amount?: unknown };\n const from = typeof i.from === 'string' ? i.from : '';\n const to = typeof i.to === 'string' ? i.to : '';\n const amount = Number(i.amount ?? 0);\n if (from && to && amount > 0) {\n state.swapQuoteTracker.record({ from, to, amount });\n }\n }\n\n state.retryTracker.record(toolName, input, result);\n}\n\n// ---------------------------------------------------------------------------\n// Conversation text extraction (for guard context)\n// ---------------------------------------------------------------------------\n\nexport function extractConversationText(\n messages: Array<{ role: string; content: unknown }>,\n): { fullText: string; lastAssistantText: string; recentUserText: string } {\n const textParts: string[] = [];\n const userParts: string[] = [];\n let lastAssistantText = '';\n\n for (const msg of messages) {\n if (!Array.isArray(msg.content)) continue;\n for (const block of msg.content as Array<Record<string, unknown>>) {\n if (block.type === 'text' && typeof block.text === 'string') {\n textParts.push(block.text);\n if (msg.role === 'assistant') {\n lastAssistantText = block.text;\n } else if (msg.role === 'user') {\n userParts.push(block.text);\n }\n }\n }\n }\n\n // Only the most recent ~10 user turns are considered an authoritative\n // source for `guardAddressSource`. Older addresses fall out of the\n // window so a user can't accidentally re-use a stale address from\n // 50 messages ago without re-pasting it.\n const RECENT_USER_TURN_WINDOW = 10;\n const recentUserParts = userParts.slice(-RECENT_USER_TURN_WINDOW);\n\n // [security] Cap each returned string at ~16KB before guards run any\n // regex over them. A few of the heuristic regexes downstream (e.g.\n // `/preview|...|confirm.*send|.../`, `/[\\d,]+\\.?\\d*\\s*(SUI|USDC|...)/`)\n // backtrack super-linearly on degenerate inputs — bounding the input\n // here keeps CodeQL's polynomial-regex alert at bay AND removes the\n // theoretical ReDoS surface from a maliciously crafted long message.\n // 16KB is comfortably larger than any realistic conversation slice we\n // need for the heuristic checks (which only look for keywords/numbers).\n const MAX_REGEX_INPUT = 16 * 1024;\n const cap = (s: string): string =>\n s.length <= MAX_REGEX_INPUT ? s : s.slice(-MAX_REGEX_INPUT);\n\n return {\n fullText: cap(textParts.join('\\n')),\n lastAssistantText: cap(lastAssistantText),\n recentUserText: cap(recentUserParts.join('\\n')),\n };\n}\n","import type { Message, ContentBlock, Tool } from '../types.js';\n\n/**\n * [v1.4 Item 4] Side-channel return from `microcompact` so callers can\n * count or surface dedup hits without re-walking the message ledger.\n * Backwards-compatible: `microcompact(messages)` still returns the\n * processed `Message[]` (now enriched), and the dedup set lives on the\n * returned array via a non-enumerable `dedupedToolUseIds` accessor that\n * the engine reads in its agent loop.\n */\nexport interface MicrocompactResult extends Array<Message> {\n /**\n * Tool-use IDs whose prior results were replaced with a compact\n * back-reference during this pass. Empty when nothing matched.\n */\n dedupedToolUseIds: Set<string>;\n}\n\n/**\n * Zero-cost deduplication pass: if the same tool was called with identical\n * inputs earlier in the conversation and the result hasn't changed, replace\n * the full prior result with a compact back-reference. Runs before any\n * LLM-based compaction and costs nothing.\n *\n * [v1.5.1] Tools may opt out of dedupe by setting `cacheable: false` on\n * their `Tool` definition. Non-cacheable tools (e.g. `balance_check`,\n * `savings_info`, `health_check`, `transaction_history`) are excluded\n * from the `seen` map entirely, so neither the current call nor any\n * later call with identical inputs gets replaced — necessary because\n * their results depend on mutable on-chain state that writes invalidate.\n *\n * Returns a new array — does not mutate the input. The returned array\n * carries a `dedupedToolUseIds` property listing every tool-use ID whose\n * tool_result block was replaced with a back-reference this pass.\n *\n * @param messages — conversation ledger to compact.\n * @param tools — optional tool registry consulted to resolve the\n * per-tool `cacheable` flag. Omit to dedupe every\n * tool (legacy behavior — back-compat).\n */\nexport function microcompact(\n messages: readonly Message[],\n tools?: readonly Tool[],\n): MicrocompactResult {\n const seen = new Map<string, { turnIndex: number }>();\n let toolUseIndex = 0;\n\n const toolUseInputs = new Map<string, string>();\n // Map tool name → cacheable flag. Default behavior (no entry, or\n // `cacheable === undefined`) is `true` — back-compat with hosts that\n // don't pass a tools array.\n const cacheableByName = new Map<string, boolean>();\n if (tools) {\n for (const t of tools) {\n cacheableByName.set(t.name, t.cacheable ?? true);\n }\n }\n const dedupedToolUseIds = new Set<string>();\n\n // Resolve tool name from a tool_use_id — cached lookup so each result\n // pass stays linear.\n const toolNameById = new Map<string, string>();\n\n for (const msg of messages) {\n for (const block of msg.content) {\n if (block.type === 'tool_use') {\n toolUseInputs.set(block.id, `${block.name}:${stableStringify(block.input)}`);\n toolNameById.set(block.id, block.name);\n }\n }\n }\n\n const out = messages.map((msg) => {\n if (msg.role !== 'user') return { role: msg.role, content: [...msg.content] };\n\n const hasToolResults = msg.content.some((b) => b.type === 'tool_result');\n if (!hasToolResults) return { role: msg.role, content: [...msg.content] };\n\n const newContent: ContentBlock[] = msg.content.map((block) => {\n if (block.type !== 'tool_result') return block;\n\n const key = toolUseInputs.get(block.toolUseId);\n if (!key) return block;\n\n // [v1.5.1] Skip dedupe entirely for tools whose results depend on\n // mutable state. Don't write to `seen` either — otherwise a later\n // *cacheable* call with the same key would erroneously dedupe\n // against this fresh result.\n const toolName = toolNameById.get(block.toolUseId);\n if (toolName && cacheableByName.get(toolName) === false) {\n toolUseIndex++;\n return block;\n }\n\n toolUseIndex++;\n const prior = seen.get(key);\n\n if (prior && !block.isError) {\n dedupedToolUseIds.add(block.toolUseId);\n return {\n ...block,\n content: `[Same result as call #${prior.turnIndex} — ${key.split(':')[0]} with identical inputs. Result unchanged.]`,\n };\n }\n\n if (!block.isError) {\n seen.set(key, { turnIndex: toolUseIndex });\n }\n return block;\n });\n\n return { role: msg.role, content: newContent };\n });\n\n // Attach the side-channel without breaking `Message[]` consumers — the\n // result is structurally compatible with `Message[]`, the extra property\n // is invisible to anything that only reads array semantics or runs deep\n // equality against a plain `Message[]` (vitest, JSON.stringify, …).\n Object.defineProperty(out, 'dedupedToolUseIds', {\n value: dedupedToolUseIds,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n return out as MicrocompactResult;\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return JSON.stringify(value);\n const sorted = Object.keys(value as Record<string, unknown>).sort();\n const obj: Record<string, unknown> = {};\n for (const k of sorted) obj[k] = (value as Record<string, unknown>)[k];\n return JSON.stringify(obj);\n}\n","import type { Message, ContentBlock } from './types.js';\nimport { microcompact } from './compact/microcompact.js';\n\n// Rough token estimation: ~4 chars per token (conservative for English + JSON)\nconst CHARS_PER_TOKEN = 4;\n\n// Default context window for Sonnet 4.6\nconst DEFAULT_CONTEXT_LIMIT = 200_000;\n\n// ---------------------------------------------------------------------------\n// Token estimation\n// ---------------------------------------------------------------------------\n\n/** Rough token count for a message array. */\nexport function estimateTokens(messages: Message[]): number {\n let chars = 0;\n for (const msg of messages) {\n for (const block of msg.content) {\n chars += blockCharCount(block);\n }\n }\n return Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nfunction blockCharCount(block: ContentBlock): number {\n switch (block.type) {\n case 'text':\n return block.text.length;\n case 'thinking':\n return block.thinking.length;\n case 'redacted_thinking':\n return block.data.length;\n case 'tool_use':\n return block.name.length + JSON.stringify(block.input).length;\n case 'tool_result':\n return block.content.length;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message compaction\n// ---------------------------------------------------------------------------\n\nexport interface CompactOptions {\n /** Max token budget for the conversation. Default 100_000. */\n maxTokens?: number;\n /** Number of recent messages to always keep uncompacted. Default 8. */\n keepRecentCount?: number;\n /** System prompt token estimate (subtracted from budget). Default 500. */\n systemPromptTokens?: number;\n /** LLM-based summarizer for old turns. When provided, replaces old turns with a summary. */\n summarizer?: (messages: Message[]) => Promise<string>;\n}\n\n// ---------------------------------------------------------------------------\n// ContextBudget — tracks cumulative token usage and signals compaction\n// ---------------------------------------------------------------------------\n\nexport interface ContextBudgetConfig {\n /** Total context window size in tokens. Default 200_000 (Sonnet 4.6). */\n contextLimit?: number;\n /** Trigger compaction at this fraction of contextLimit. Default 0.85. */\n compactThreshold?: number;\n /** Emit a warning at this fraction of contextLimit. Default 0.70. */\n warnThreshold?: number;\n}\n\nexport class ContextBudget {\n private estimatedTokens = 0;\n private readonly contextLimit: number;\n private readonly compactThreshold: number;\n private readonly warnThreshold: number;\n\n constructor(config: ContextBudgetConfig = {}) {\n this.contextLimit = config.contextLimit ?? DEFAULT_CONTEXT_LIMIT;\n this.compactThreshold = config.compactThreshold ?? 0.85;\n this.warnThreshold = config.warnThreshold ?? 0.70;\n }\n\n /** Update with actual input_tokens from the API usage event. */\n update(inputTokens: number): void {\n this.estimatedTokens = inputTokens;\n }\n\n /** True when the session should be compacted (at 85% of context limit). */\n shouldCompact(): boolean {\n return this.estimatedTokens >= this.contextLimit * this.compactThreshold;\n }\n\n /** True when nearing the limit (at 70% of context limit). */\n shouldWarn(): boolean {\n return this.estimatedTokens >= this.contextLimit * this.warnThreshold;\n }\n\n /** Current token count. */\n get tokens(): number {\n return this.estimatedTokens;\n }\n\n /** Remaining tokens before compaction triggers. */\n get remaining(): number {\n return Math.max(0, Math.floor(this.contextLimit * this.compactThreshold) - this.estimatedTokens);\n }\n\n /** Usage ratio (0..1). */\n get usage(): number {\n return this.estimatedTokens / this.contextLimit;\n }\n\n reset(): void {\n this.estimatedTokens = 0;\n }\n}\n\n/**\n * Compact a conversation that exceeds the token budget.\n *\n * Strategy:\n * 1. Always preserve the most recent `keepRecentCount` messages (the active context).\n * 2. If an LLM `summarizer` is provided, summarize old turns into a brief recap and\n * replace them with a synthetic summary turn pair.\n * 3. For older messages, summarise tool_result content to a brief one-liner.\n * 4. If still over budget, drop the oldest messages (keeping the first user message\n * for context continuity).\n *\n * Returns a new array — does not mutate the input.\n */\nexport async function compactMessages(\n messages: readonly Message[],\n opts: CompactOptions = {},\n): Promise<Message[]> {\n const maxTokens = opts.maxTokens ?? 100_000;\n const keepRecent = opts.keepRecentCount ?? 8;\n const systemTokens = opts.systemPromptTokens ?? 500;\n const budget = maxTokens - systemTokens;\n\n if (messages.length === 0) return [];\n\n // Phase -1: zero-cost deduplication of identical tool calls\n const deduped = microcompact(messages);\n\n const mutable = deduped.map((m) => ({\n role: m.role,\n content: m.content.map((b) => ({ ...b })),\n })) as Message[];\n\n if (estimateTokens(mutable) <= budget) return mutable;\n\n const splitIdx = Math.max(0, mutable.length - keepRecent);\n const oldMessages = mutable.slice(0, splitIdx);\n const recent = mutable.slice(splitIdx);\n\n // Phase 0: If summarizer is provided, try LLM-based summarization of old turns\n if (opts.summarizer && oldMessages.length > 0) {\n const strippedOld = stripThinkingBlocks(oldMessages);\n try {\n const summary = await opts.summarizer(strippedOld);\n const summaryMessages: Message[] = [\n { role: 'user', content: [{ type: 'text', text: `[Session summary: ${summary}]` }] },\n { role: 'assistant', content: [{ type: 'text', text: 'Understood. I have the context from our earlier conversation.' }] },\n ];\n const withSummary = [...summaryMessages, ...recent];\n if (estimateTokens(withSummary) <= budget) return sanitizeMessages(withSummary);\n } catch {\n // Summarizer failed — fall through to truncation strategy\n }\n }\n\n // Phase 1: summarise tool_result blocks in older messages\n for (let i = 0; i < splitIdx; i++) {\n mutable[i].content = mutable[i].content.map((block) => {\n if (block.type === 'tool_result' && block.content.length > 200) {\n return {\n ...block,\n content: truncateToolResult(block.content),\n };\n }\n return block;\n });\n }\n\n // Strip thinking blocks from old messages (they don't aid context continuity)\n for (let i = 0; i < splitIdx; i++) {\n mutable[i].content = mutable[i].content.filter(\n (b) => b.type !== 'thinking' && b.type !== 'redacted_thinking',\n );\n }\n\n if (estimateTokens(mutable) <= budget) return mutable;\n\n // Phase 2: drop old messages from the middle, keep first + recent\n if (splitIdx <= 1) {\n // All messages are recent (or only the first message is \"old\") — skip middle-drop\n return sanitizeMessages(mutable);\n }\n\n const first = mutable[0];\n const recentFromMutable = mutable.slice(splitIdx);\n const oldSection = mutable.slice(1, splitIdx);\n\n while (oldSection.length > 0 && estimateTokens([first, ...oldSection, ...recentFromMutable]) > budget) {\n oldSection.shift();\n }\n\n const compacted = [first, ...oldSection, ...recentFromMutable];\n\n // Phase 3: if still over budget (very long recent section), truncate tool results in recent\n if (estimateTokens(compacted) > budget) {\n for (const msg of compacted) {\n msg.content = msg.content.map((block) => {\n if (block.type === 'tool_result' && block.content.length > 100) {\n return { ...block, content: truncateToolResult(block.content) };\n }\n return block;\n });\n }\n }\n\n return sanitizeMessages(compacted);\n}\n\n/**\n * Strip thinking and redacted_thinking blocks from messages.\n * Used before summarization — thinking blocks don't help the summarizer.\n */\nfunction stripThinkingBlocks(messages: Message[]): Message[] {\n return messages.map((m) => ({\n ...m,\n content: m.content.filter(\n (b) => b.type !== 'thinking' && b.type !== 'redacted_thinking',\n ),\n })).filter((m) => m.content.length > 0);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Remove orphaned tool_use / tool_result blocks that lost their pair\n * during compaction. Anthropic requires every tool_result to match a\n * preceding tool_use and vice versa.\n */\nfunction sanitizeMessages(messages: Message[]): Message[] {\n const toolUseIds = new Set<string>();\n const toolResultIds = new Set<string>();\n\n for (const msg of messages) {\n for (const block of msg.content) {\n if (block.type === 'tool_use') toolUseIds.add(block.id);\n if (block.type === 'tool_result') toolResultIds.add(block.toolUseId);\n }\n }\n\n return messages\n .map((msg) => {\n const filtered = msg.content.filter((block) => {\n if (block.type === 'tool_result') return toolUseIds.has(block.toolUseId);\n if (block.type === 'tool_use') return toolResultIds.has(block.id);\n return true;\n });\n if (filtered.length === 0) return null;\n return { ...msg, content: filtered };\n })\n .filter((m): m is Message => m !== null);\n}\n\nfunction truncateToolResult(content: string): string {\n try {\n const parsed = JSON.parse(content);\n\n if (parsed.error) {\n return JSON.stringify({ error: parsed.error });\n }\n\n // Keep just the top-level keys with truncated values\n if (typeof parsed === 'object' && parsed !== null) {\n const summary: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n summary[key] = value;\n } else if (typeof value === 'string') {\n summary[key] = value.length > 50 ? value.slice(0, 50) + '…' : value;\n } else if (Array.isArray(value)) {\n summary[key] = `[${value.length} items]`;\n } else {\n summary[key] = '{…}';\n }\n }\n return JSON.stringify(summary);\n }\n\n return content.slice(0, 100);\n } catch {\n return content.slice(0, 100);\n }\n}\n","/**\n * USD-aware permission resolution for write tools.\n *\n * Replaces the binary auto/confirm/explicit system with dollar-threshold\n * tiers that resolve at runtime based on the transaction value and\n * per-user configuration.\n */\n\nexport type PermissionOperation =\n | 'save'\n | 'withdraw'\n | 'send'\n | 'borrow'\n | 'repay'\n | 'swap'\n | 'pay';\n\nexport interface PermissionRule {\n operation: PermissionOperation;\n /** Auto-execute if USD amount is below this threshold. */\n autoBelow: number;\n /** Confirm if between autoBelow and this. Explicit for anything above. */\n confirmBetween: number;\n}\n\nexport interface UserPermissionConfig {\n rules: PermissionRule[];\n /** Fallback auto threshold for operations without a specific rule. */\n globalAutoBelow: number;\n /** Max total USD of autonomous actions per day (safety net). */\n autonomousDailyLimit: number;\n}\n\nexport const DEFAULT_PERMISSION_CONFIG: UserPermissionConfig = {\n globalAutoBelow: 10,\n autonomousDailyLimit: 200,\n rules: [\n { operation: 'save', autoBelow: 50, confirmBetween: 1000 },\n { operation: 'send', autoBelow: 10, confirmBetween: 200 },\n { operation: 'borrow', autoBelow: 0, confirmBetween: 500 },\n { operation: 'withdraw', autoBelow: 25, confirmBetween: 500 },\n { operation: 'swap', autoBelow: 25, confirmBetween: 300 },\n { operation: 'pay', autoBelow: 1, confirmBetween: 50 },\n { operation: 'repay', autoBelow: 50, confirmBetween: 1000 },\n ],\n};\n\nexport const PERMISSION_PRESETS = {\n conservative: {\n globalAutoBelow: 5,\n autonomousDailyLimit: 100,\n rules: [\n { operation: 'save' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'send' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'borrow' as const, autoBelow: 0, confirmBetween: 100 },\n { operation: 'withdraw' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'swap' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'pay' as const, autoBelow: 1, confirmBetween: 25 },\n { operation: 'repay' as const, autoBelow: 5, confirmBetween: 100 },\n ],\n },\n balanced: DEFAULT_PERMISSION_CONFIG,\n aggressive: {\n globalAutoBelow: 25,\n autonomousDailyLimit: 500,\n rules: [\n { operation: 'save' as const, autoBelow: 100, confirmBetween: 2000 },\n { operation: 'send' as const, autoBelow: 25, confirmBetween: 500 },\n { operation: 'borrow' as const, autoBelow: 10, confirmBetween: 1000 },\n { operation: 'withdraw' as const, autoBelow: 50, confirmBetween: 1000 },\n { operation: 'swap' as const, autoBelow: 50, confirmBetween: 500 },\n { operation: 'pay' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'repay' as const, autoBelow: 100, confirmBetween: 2000 },\n ],\n },\n} satisfies Record<string, UserPermissionConfig>;\n\n/**\n * True when `to` matches a saved contact's address (case-insensitive,\n * normalized). Used by `resolvePermissionTier` to enforce the\n * \"first-send to a new raw address always confirms\" rule and to keep\n * the engine + client in sync.\n */\nexport function isKnownContactAddress(\n to: string,\n contacts: ReadonlyArray<{ address: string }>,\n): boolean {\n if (!to) return false;\n const normalized = to.trim().toLowerCase();\n return contacts.some((c) => c.address.trim().toLowerCase() === normalized);\n}\n\n/**\n * Resolve the permission tier for a given operation + USD value.\n *\n * [v1.4] When `sessionSpendUsd` is supplied and adding the incoming\n * `amountUsd` would push cumulative session spend over\n * `config.autonomousDailyLimit`, an otherwise-`auto` tier is downgraded to\n * `confirm`. This is the runtime guard for the daily autonomous spend cap.\n * Tiers above `auto` are returned unchanged.\n *\n * Send-safety rule: when `operation === 'send'` and the destination\n * address is a raw `0x...` (i.e. NOT one of the user's saved contacts),\n * an otherwise-`auto` tier is downgraded to `confirm` regardless of\n * amount. This bounds the \"LLM/user typo silently ships funds\" failure\n * mode to a single confirmation per recipient — once saved as a contact,\n * subsequent sends to the same address auto-approve under tier as normal.\n */\nexport function resolvePermissionTier(\n operation: string,\n amountUsd: number,\n config: UserPermissionConfig,\n sessionSpendUsd?: number,\n sendContext?: {\n to?: string;\n contacts?: ReadonlyArray<{ address: string }>;\n },\n): 'auto' | 'confirm' | 'explicit' {\n const rule = config.rules.find((r) => r.operation === operation);\n const autoBelow = rule?.autoBelow ?? config.globalAutoBelow;\n const confirmBetween = rule?.confirmBetween ?? 1000;\n\n let tier: 'auto' | 'confirm' | 'explicit';\n if (amountUsd < autoBelow) tier = 'auto';\n else if (amountUsd < confirmBetween) tier = 'confirm';\n else tier = 'explicit';\n\n if (\n tier === 'auto' &&\n typeof sessionSpendUsd === 'number' &&\n sessionSpendUsd + amountUsd > config.autonomousDailyLimit\n ) {\n tier = 'confirm';\n }\n\n // Send-safety: a *raw* 0x recipient that doesn't match a saved\n // contact forces confirm. Contact names (e.g. `to: \"wallet1\"`) are\n // already trusted — the user explicitly saved that contact — and get\n // resolved to addresses downstream by `effects.resolveContact`. Without\n // the `0x` guard, a contact-name send was incorrectly demoted to\n // confirm because `isKnownContactAddress(\"wallet1\", contacts)` compares\n // the name against contact *addresses* and returns false.\n if (\n tier === 'auto' &&\n operation === 'send' &&\n sendContext?.to &&\n sendContext.to.startsWith('0x') &&\n !isKnownContactAddress(sendContext.to, sendContext.contacts ?? [])\n ) {\n tier = 'confirm';\n }\n\n return tier;\n}\n\nconst TOOL_TO_OPERATION: Record<string, PermissionOperation> = {\n save_deposit: 'save',\n withdraw: 'withdraw',\n send_transfer: 'send',\n borrow: 'borrow',\n repay_debt: 'repay',\n swap_execute: 'swap',\n pay_api: 'pay',\n volo_stake: 'save',\n volo_unstake: 'withdraw',\n};\n\nexport function toolNameToOperation(toolName: string): PermissionOperation | undefined {\n return TOOL_TO_OPERATION[toolName];\n}\n\n/**\n * Resolve the USD value of a tool call from its inputs.\n * USDC-denominated tools return 1:1. Others multiply by the price cache.\n */\nexport function resolveUsdValue(\n toolName: string,\n input: Record<string, unknown>,\n priceCache: Map<string, number>,\n): number {\n switch (toolName) {\n case 'save_deposit':\n case 'withdraw':\n case 'repay_debt':\n case 'borrow':\n return safeNum(input.amount);\n\n case 'send_transfer': {\n const amount = safeNum(input.amount);\n const asset = String(input.asset ?? 'USDC').toUpperCase();\n if (asset === 'USDC' || asset === 'USDT') return amount;\n return amount * (priceCache.get(asset) ?? 0);\n }\n\n case 'swap_execute': {\n const amount = safeNum(input.fromAmount);\n const fromAsset = String(input.fromAsset ?? '').toUpperCase();\n if (fromAsset === 'USDC' || fromAsset === 'USDT') return amount;\n return amount * (priceCache.get(fromAsset) ?? 0);\n }\n\n case 'pay_api':\n return safeNum(input.maxCost ?? input.price);\n\n case 'volo_stake':\n case 'volo_unstake':\n return safeNum(input.amount) * (priceCache.get('SUI') ?? 0);\n\n default:\n return 0;\n }\n}\n\nfunction safeNum(v: unknown): number {\n const n = Number(v);\n return isNaN(n) ? 0 : n;\n}\n","/**\n * [v0.46.8] Intra-turn deduplication of read-only tool calls.\n *\n * # Problem\n * Two independent execution paths can call the same read-only tool within\n * the same user turn:\n * 1. Host pre-dispatch via `engine.invokeReadTool()` (deterministic — runs\n * before the LLM ever sees the message; injects a synthetic\n * `tool_use`+`tool_result` pair into the ledger so the card renders\n * immediately and the LLM has the data).\n * 2. The LLM itself, mid-turn, emitting a `tool_use` block for the same\n * tool (often because the prompt says \"always call balance_check on\n * direct read questions\" and the model doesn't trust the synthetic\n * pair).\n *\n * Both paths emit a `tool_result` SSE event, the host renders BOTH cards,\n * the user sees a duplicate. Coordinating these two paths via prompt rules\n * is probabilistic (\"DO NOT re-call when you see a synthetic pair\") and\n * has empirically shown ~30% miss rate — the LLM still re-calls anyway.\n *\n * # Fix\n * Idempotent intra-turn cache. Within one user turn:\n * - Calling the same read-only tool with the same args twice returns the\n * cached result on the second call.\n * - The second call yields a `tool_result` event with `resultDeduped:true`\n * so hosts can skip rendering a duplicate card while the LLM still gets\n * the data it needs to satisfy its `tool_use` id.\n *\n * # Lifecycle\n * - Cache lives on the `QueryEngine` instance.\n * - Populated by `invokeReadTool` (host pre-dispatch) AND by the agent\n * loop's tool-execution path (LLM-driven calls).\n * - Cleared on `turn_complete` (clean slate for the next user turn).\n * - Cleared whenever a WRITE tool executes successfully (writes mutate\n * on-chain state, so any subsequent read in the same turn must re-fetch\n * for freshness).\n * - Cleared on errors / abort (defensive cleanup).\n *\n * # Why not just extend microcompact?\n * `microcompact` does CROSS-turn dedup, but explicitly excludes\n * `cacheable: false` tools (balance_check, health_check, savings_info,\n * transaction_history) so post-write refreshes always surface fresh data.\n * Within a single turn (pre-write), those same tools are perfectly\n * dedup-able — state can't change. This cache fills that exact gap.\n *\n * # Invariants\n * - Read-only tools only. Write tools never enter the cache.\n * - Errored results are NEVER cached (the next call should retry).\n * - Cache key includes the full input, stably stringified — different\n * filter args (e.g. `transaction_history({minUsd:5})` vs\n * `transaction_history({})`) hit different cache entries.\n */\nexport class TurnReadCache {\n private readonly store = new Map<string, { result: unknown; sourceToolUseId: string }>();\n\n /**\n * Build the cache key for a (toolName, input) pair. Stable across object\n * key ordering so `{a:1,b:2}` and `{b:2,a:1}` map to the same entry.\n */\n static keyFor(toolName: string, input: unknown): string {\n return `${toolName}:${stableStringify(input)}`;\n }\n\n has(key: string): boolean {\n return this.store.has(key);\n }\n\n get(key: string): { result: unknown; sourceToolUseId: string } | undefined {\n return this.store.get(key);\n }\n\n /**\n * Populate the cache. Caller is responsible for ensuring the result was\n * a successful read (no errors). Overwrites any prior entry for the same\n * key — the most recent successful read wins, which is correct under our\n * \"writes invalidate the whole cache\" invariant.\n */\n set(key: string, value: { result: unknown; sourceToolUseId: string }): void {\n this.store.set(key, value);\n }\n\n /**\n * Drop every entry. Called at turn end and after every successful write.\n * Cheap and intentional — the cache is small (a handful of entries per\n * turn at most) and clearing is the correct response to any state mutation.\n */\n clear(): void {\n this.store.clear();\n }\n\n size(): number {\n return this.store.size;\n }\n}\n\n/**\n * Stable JSON.stringify — sorts object keys recursively so semantically\n * equal inputs produce equal cache keys. Mirrors the helper in\n * `compact/microcompact.ts` so dedup keys agree across both layers.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return JSON.stringify(value.map(stableStringifyForObject));\n return stableStringifyForObject(value);\n}\n\nfunction stableStringifyForObject(value: unknown): string {\n if (value === null || value === undefined) return JSON.stringify(value);\n if (typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) {\n return `[${value.map(stableStringifyForObject).join(',')}]`;\n }\n const sorted = Object.keys(value as Record<string, unknown>).sort();\n const parts = sorted.map(\n (k) => `${JSON.stringify(k)}:${stableStringifyForObject((value as Record<string, unknown>)[k])}`,\n );\n return `{${parts.join(',')}}`;\n}\n","/**\n * EarlyToolDispatcher — dispatches read-only tools mid-stream.\n *\n * When the LLM emits `tool_use_done` for a read-only tool, the dispatcher\n * fires it immediately in the background rather than waiting for the full\n * stream to finish. Results are collected in original call order after the\n * stream exits.\n *\n * Write tools are NOT dispatched — they go through the existing permission\n * gate and TxMutex flow.\n */\n\nimport type { EngineEvent, Tool, ToolContext } from './types.js';\nimport { findTool } from './tool.js';\nimport { budgetToolResult, withRetryStats, type PendingToolCall } from './orchestration.js';\nimport { TurnReadCache } from './turn-read-cache.js';\n\ninterface DispatchEntry {\n call: PendingToolCall;\n tool: Tool;\n promise: Promise<{ data: unknown; isError: boolean }>;\n /**\n * [v0.46.8] True when this entry was satisfied from the\n * `TurnReadCache` rather than a fresh tool execution. The\n * `collectResults` stream surfaces these as `resultDeduped: true` so\n * hosts can skip rendering a duplicate card while the LLM still gets\n * the data it needs to answer its `tool_use_id`.\n */\n deduped: boolean;\n /**\n * [SPEC 8 v0.5.1 B3.2] Per-tool HTTP retry counter. Reads back the\n * mutable `retryStats` ref the dispatcher attached to the tool's\n * context — undefined for cached/deduped entries (no fresh execution\n * happened, so no retries to surface).\n */\n readAttemptCount: () => number | undefined;\n}\n\nexport class EarlyToolDispatcher {\n private entries: DispatchEntry[] = [];\n private readonly tools: Tool[];\n private readonly context: ToolContext;\n private readonly turnReadCache: TurnReadCache | undefined;\n private abortController: AbortController;\n\n constructor(tools: Tool[], context: ToolContext, turnReadCache?: TurnReadCache) {\n this.tools = tools;\n this.context = context;\n this.turnReadCache = turnReadCache;\n this.abortController = new AbortController();\n }\n\n /**\n * Attempt to dispatch a tool call. Returns true if the tool was dispatched\n * (read-only + concurrency-safe), false if it should be queued for later.\n *\n * [v0.46.8] Cache-aware: if a `TurnReadCache` was supplied at\n * construction and a prior call this turn already produced a result\n * for the same `(toolName, input)`, the dispatcher returns true (the\n * call IS handled here, not queued for the post-stream loop) but\n * skips the tool execution entirely — `collectResults` will surface\n * the cached value with `resultDeduped: true`. On a cache miss for\n * a successful real execution, the result is written back to the\n * cache so any later call within the same turn dedups too.\n */\n tryDispatch(call: PendingToolCall): boolean {\n const tool = findTool(this.tools, call.name);\n if (!tool || !tool.isReadOnly || !tool.isConcurrencySafe) return false;\n\n if (this.turnReadCache) {\n const cacheKey = TurnReadCache.keyFor(call.name, call.input);\n const cached = this.turnReadCache.get(cacheKey);\n if (cached) {\n this.entries.push({\n call,\n tool,\n promise: Promise.resolve({ data: cached.result, isError: false }),\n deduped: true,\n readAttemptCount: () => undefined,\n });\n return true;\n }\n }\n\n // [SPEC 8 v0.5.1 B3.2] Per-tool retry counter — fresh ref per\n // dispatch so concurrent reads in the early-dispatch batch keep\n // their attempt counts isolated. The signal override on the child\n // context is preserved through the spread.\n const baseChildContext: ToolContext = { ...this.context, signal: this.abortController.signal };\n const { context: childContext, readAttemptCount } = withRetryStats(baseChildContext);\n const promise = executeTool(tool, call, childContext).then((result) => {\n // Populate the cache on a successful, non-cached execution so a\n // later identical call this turn dedups instead of re-running.\n if (!result.isError && this.turnReadCache) {\n const cacheKey = TurnReadCache.keyFor(call.name, call.input);\n this.turnReadCache.set(cacheKey, {\n result: result.data,\n sourceToolUseId: call.id,\n });\n }\n return result;\n });\n\n this.entries.push({ call, tool, promise, deduped: false, readAttemptCount });\n return true;\n }\n\n /** True if any tools have been dispatched. */\n hasPending(): boolean {\n return this.entries.length > 0;\n }\n\n /** List of call IDs that were early-dispatched. */\n dispatchedIds(): Set<string> {\n return new Set(this.entries.map((e) => e.call.id));\n }\n\n /**\n * Look up the original tool input by `tool_use_id`. Used by the engine to\n * feed `updateGuardStateAfterToolResult` (which needs the call input to\n * record swap_quote → swap_execute pairing, etc.) for tools that were\n * dispatched here instead of going through the normal post-stream loop.\n */\n getInputById(toolUseId: string): unknown | undefined {\n return this.entries.find((e) => e.call.id === toolUseId)?.call.input;\n }\n\n /**\n * Collect all results in original dispatch order.\n * Yields `tool_result` events as each promise resolves.\n */\n async *collectResults(): AsyncGenerator<EngineEvent> {\n for (const entry of this.entries) {\n try {\n const result = await entry.promise;\n const budgeted = result.isError\n ? result.data\n : budgetToolResult(result.data, entry.tool);\n\n const attemptCount = entry.readAttemptCount();\n yield {\n type: 'tool_result',\n toolName: entry.call.name,\n toolUseId: entry.call.id,\n result: budgeted,\n isError: result.isError,\n wasEarlyDispatched: true,\n ...(entry.deduped ? { resultDeduped: true } : {}),\n ...(attemptCount !== undefined ? { attemptCount } : {}),\n };\n } catch (err) {\n yield {\n type: 'tool_result',\n toolName: entry.call.name,\n toolUseId: entry.call.id,\n result: { error: err instanceof Error ? err.message : 'Tool execution failed' },\n isError: true,\n wasEarlyDispatched: true,\n };\n }\n }\n }\n\n /** Cancel all in-flight tool calls. */\n abort(): void {\n this.abortController.abort();\n }\n}\n\nasync function executeTool(\n tool: Tool,\n call: PendingToolCall,\n context: ToolContext,\n): Promise<{ data: unknown; isError: boolean }> {\n const parsed = tool.inputSchema.safeParse(call.input);\n if (!parsed.success) {\n return {\n data: { error: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(', ')}` },\n isError: true,\n };\n }\n\n const result = await tool.call(parsed.data, context);\n return { data: result.data, isError: false };\n}\n","import type {\n EngineConfig,\n EngineEvent,\n HarnessShape,\n Message,\n ContentBlock,\n PendingAction,\n SystemPrompt,\n Tool,\n ToolContext,\n PermissionResponse,\n ProviderEvent,\n StopReason,\n} from './types.js';\nimport { toolsToDefinitions, findTool } from './tool.js';\nimport { TxMutex, runTools, withRetryStats, type PendingToolCall } from './orchestration.js';\nimport { getDefaultTools } from './tools/index.js';\nimport { getModifiableFields } from './tools/tool-modifiable-fields.js';\nimport { DEFAULT_SYSTEM_PROMPT } from './prompt.js';\nimport { clearPortfolioCacheFor } from './blockvision-prices.js';\nimport { getTelemetrySink } from './telemetry.js';\nimport { randomUUID } from 'node:crypto';\nimport { CostTracker, type CostSnapshot } from './cost.js';\nimport { estimatePayApiCost } from './tools/pay.js';\nimport { clampThinkingForEffort } from './thinking-budget.js';\nimport {\n type GuardConfig,\n type GuardRunnerState,\n type GuardEvent,\n createGuardRunnerState,\n runGuards,\n updateGuardStateAfterToolResult,\n extractConversationText,\n guardArtifactPreview,\n guardStaleData,\n} from './guards.js';\nimport type { RecipeRegistry, Recipe } from './recipes/index.js';\nimport { ContextBudget, compactMessages } from './context.js';\nimport { microcompact } from './compact/microcompact.js';\nimport { resolvePermissionTier, resolveUsdValue, toolNameToOperation } from './permission-rules.js';\nimport { EarlyToolDispatcher } from './early-dispatcher.js';\nimport { TurnReadCache } from './turn-read-cache.js';\n\nconst DEFAULT_MAX_TURNS = 10;\nconst DEFAULT_MAX_TOKENS = 4096;\n\ninterface TurnAccumulator {\n text: string;\n stopReason: StopReason;\n assistantBlocks: ContentBlock[];\n pendingToolCalls: PendingToolCall[];\n}\n\nexport class QueryEngine {\n private readonly provider: EngineConfig['provider'];\n private readonly tools: Tool[];\n private readonly systemPrompt: SystemPrompt;\n private readonly model: string | undefined;\n private readonly maxTurns: number;\n private readonly maxTokens: number;\n private readonly temperature: number | undefined;\n private readonly toolChoice: EngineConfig['toolChoice'];\n private readonly thinking: EngineConfig['thinking'];\n private readonly outputConfig: EngineConfig['outputConfig'];\n private readonly agent: unknown;\n private readonly mcpManager: unknown;\n private readonly walletAddress: string | undefined;\n private readonly suiRpcUrl: string | undefined;\n private serverPositions: EngineConfig['serverPositions'];\n private readonly positionFetcher: EngineConfig['positionFetcher'];\n private readonly env: Record<string, string> | undefined;\n private readonly txMutex = new TxMutex();\n private readonly costTracker: CostTracker;\n private readonly guardConfig: GuardConfig | undefined;\n private readonly guardState: GuardRunnerState;\n private readonly recipes: RecipeRegistry | undefined;\n private readonly contextBudget: ContextBudget;\n private readonly contextSummarizer: EngineConfig['contextSummarizer'];\n private readonly priceCache: Map<string, number> | undefined;\n private readonly permissionConfig: import('./permission-rules.js').UserPermissionConfig | undefined;\n // Saved contacts — consulted by `guardAddressSource` and the permission\n // tier resolver (sends to non-contact addresses always require confirm).\n private readonly contacts: ReadonlyArray<{ name: string; address: string }>;\n // [v1.4] Session-scoped autonomous spend tracking.\n private readonly sessionSpendUsd: number | undefined;\n private readonly onAutoExecuted: EngineConfig['onAutoExecuted'];\n private readonly onGuardFired: EngineConfig['onGuardFired'];\n // [v1.4 BlockVision] BlockVision Indexer API key + per-request portfolio\n // cache. Forwarded into every `ToolContext` build site so read tools\n // (`balance_check`, `portfolio_analysis`, future `token_prices`) hit the\n // shared host-paid endpoint and dedupe across each other within a turn.\n private readonly blockvisionApiKey: string | undefined;\n private readonly portfolioCache: EngineConfig['portfolioCache'];\n // [v1.5] See `EngineConfig.postWriteRefresh` — drives the post-write\n // synthetic read injection in `resumeWithToolResult`.\n private readonly postWriteRefresh: EngineConfig['postWriteRefresh'];\n private matchedRecipe: Recipe | null = null;\n\n private messages: Message[] = [];\n private abortController: AbortController | null = null;\n private guardEvents: GuardEvent[] = [];\n // [v0.46.8] Intra-turn dedup cache for read-only tool calls. See\n // `turn-read-cache.ts` for the full lifecycle. Key takeaway: the cache\n // lives across the host's pre-dispatch (`invokeReadTool`) and the\n // agent loop's LLM-driven tool execution within ONE user turn, then\n // clears on `turn_complete` or after any successful write.\n private readonly turnReadCache = new TurnReadCache();\n // [v0.46.8] Set to `true` when the agent loop yields `pending_action`\n // and returns (turn is paused awaiting user confirmation). The\n // submitMessage / resumeWithToolResult wrappers consult this flag in\n // their `finally` block so they DON'T clear the cache mid-turn — the\n // pending write may resume, and the cache should survive the pause.\n private turnPaused = false;\n\n constructor(config: EngineConfig) {\n this.provider = config.provider;\n this.agent = config.agent;\n this.mcpManager = config.mcpManager;\n this.walletAddress = config.walletAddress;\n this.suiRpcUrl = config.suiRpcUrl;\n this.serverPositions = config.serverPositions;\n this.positionFetcher = config.positionFetcher;\n this.env = config.env;\n this.model = config.model;\n this.maxTurns = config.maxTurns ?? DEFAULT_MAX_TURNS;\n this.maxTokens = config.maxTokens ?? DEFAULT_MAX_TOKENS;\n this.temperature = config.temperature;\n this.toolChoice = config.toolChoice;\n this.thinking = config.thinking;\n this.outputConfig = config.outputConfig;\n this.systemPrompt = config.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n this.costTracker = new CostTracker(config.costTracker);\n this.guardConfig = config.guards;\n this.guardState = createGuardRunnerState();\n this.recipes = config.recipes;\n this.contextBudget = new ContextBudget(config.contextBudget);\n this.contextSummarizer = config.contextSummarizer;\n this.priceCache = config.priceCache;\n this.permissionConfig = config.permissionConfig;\n this.contacts = config.contacts ?? [];\n this.sessionSpendUsd = config.sessionSpendUsd;\n this.onAutoExecuted = config.onAutoExecuted;\n this.onGuardFired = config.onGuardFired;\n this.postWriteRefresh = config.postWriteRefresh;\n this.blockvisionApiKey = config.blockvisionApiKey;\n this.portfolioCache = config.portfolioCache;\n\n this.tools = config.tools ?? (config.agent ? getDefaultTools() : []);\n }\n\n /**\n * Submit a user message and stream engine events.\n *\n * Read-only tools execute inline. Write tools that need confirmation yield a\n * `pending_action` event and the stream ends — no persistent connection needed.\n * The caller should save messages + pendingAction to the session store, then\n * call `resumeWithToolResult()` after the user approves/denies and executes.\n *\n * [SPEC 8 v0.5.1 B3.2] Optional `options.harnessShape` + `options.harnessRationale`\n * cause a one-shot `harness_shape` event to be yielded BEFORE the agent loop\n * begins. The engine itself doesn't classify — the host calls\n * `classifyEffort()` (host already does this for thinking-budget routing)\n * and maps via `harnessShapeForEffort()` before calling `submitMessage`.\n * Hosts that don't pass `harnessShape` won't see the event (existing\n * pre-SPEC-8 hosts continue to work; their `TurnMetrics.harnessShape`\n * defaults to `'legacy'`).\n */\n async *submitMessage(\n prompt: string,\n options?: {\n harnessShape?: HarnessShape;\n harnessRationale?: string;\n },\n ): AsyncGenerator<EngineEvent> {\n if (this.costTracker.isOverBudget()) {\n yield { type: 'error', error: new Error('Session budget exceeded') };\n return;\n }\n\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n\n // RE-3.1: Match recipe before pushing message\n this.matchedRecipe = this.recipes?.match(prompt) ?? null;\n\n this.messages.push({\n role: 'user',\n content: [{ type: 'text', text: prompt }],\n });\n\n // [SPEC 8 v0.5.1 B3.2] Emit the per-turn harness shape declaration\n // BEFORE agentLoop runs. Single emission per `submitMessage` call;\n // `resumeWithToolResult` does NOT re-emit (resume continues the same\n // turn under the same shape). Empty rationale falls back to the\n // shape name so dashboards always have non-null context.\n if (options?.harnessShape) {\n yield {\n type: 'harness_shape',\n shape: options.harnessShape,\n rationale:\n options.harnessRationale && options.harnessRationale.trim().length > 0\n ? options.harnessRationale\n : `host-classified ${options.harnessShape}`,\n };\n }\n\n // [v0.46.8] Reset the pause flag at turn start. Any cache entries\n // populated by the host's pre-dispatch (`invokeReadTool`) BEFORE\n // this call MUST survive into the agent loop so LLM-driven calls\n // for the same tools dedup. We do NOT clear the cache here.\n this.turnPaused = false;\n try {\n yield* this.agentLoop(prompt, signal);\n } finally {\n // Turn boundary cleanup: drop the cache so the next user turn\n // starts with a clean slate. Skip when the turn was paused via\n // `pending_action` — the cache must survive the pause so the\n // resumed turn (which is the SAME turn) keeps deduping.\n if (!this.turnPaused) {\n this.turnReadCache.clear();\n }\n }\n }\n\n /**\n * Resume the conversation after a pending action is resolved.\n * Called with the user's approval/denial and optional client-side execution result.\n *\n * This is a separate HTTP request — no persistent connection from submitMessage.\n */\n async *resumeWithToolResult(\n action: PendingAction,\n response: PermissionResponse,\n ): AsyncGenerator<EngineEvent> {\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n\n const writeResult: ContentBlock = response.approved\n ? {\n type: 'tool_result',\n toolUseId: action.toolUseId,\n content: JSON.stringify(response.executionResult ?? { success: true }),\n isError: false,\n }\n : {\n type: 'tool_result',\n toolUseId: action.toolUseId,\n content: JSON.stringify({ error: 'User declined this action' }),\n isError: true,\n };\n\n // Reconstruct the full turn atomically:\n // 1. Push the assistant message that was deferred during pending_action\n // 2. Push ALL tool_results (completed reads + write) in one user message\n if (action.assistantContent?.length) {\n this.messages.push({ role: 'assistant', content: action.assistantContent });\n }\n\n const allResults: ContentBlock[] = [\n ...(action.completedResults ?? []).map((r) => ({\n type: 'tool_result' as const,\n toolUseId: r.toolUseId,\n content: r.content,\n isError: r.isError,\n })),\n writeResult,\n ];\n\n this.messages.push({ role: 'user', content: allResults });\n\n yield {\n type: 'tool_result',\n toolName: action.toolName,\n toolUseId: action.toolUseId,\n result: response.approved\n ? (response.executionResult ?? { success: true })\n : { error: 'User declined this action' },\n isError: !response.approved,\n };\n\n if (!response.approved) {\n yield { type: 'turn_complete', stopReason: 'end_turn' };\n // Turn ended (user declined) — drop the cache.\n this.turnReadCache.clear();\n return;\n }\n\n // [v0.46.8] A successful approved write MUTATES on-chain state, so\n // any read-tool result cached during the pre-pause portion of this\n // turn is now stale. Drop it before the post-write refresh fires —\n // refresh tools will re-execute and re-populate with fresh data.\n this.turnReadCache.clear();\n\n // [v1.5] Post-write refresh — eliminate the \"LLM invents a wallet\n // total in the post-write narration\" hallucination class by\n // physically injecting authoritative ground truth into the\n // conversation BEFORE the LLM gets to narrate. Tools are configured\n // per write via `EngineConfig.postWriteRefresh`. Errors are\n // non-fatal: we still advance to agentLoop so the user gets *some*\n // narration even if RPC blips.\n yield* this.runPostWriteRefresh(action, response, signal);\n\n // [v0.46.8] Reset the pause flag and wrap the resumed agentLoop in\n // try/finally for cache cleanup, mirroring submitMessage. The\n // post-write refresh above re-populated the cache with fresh\n // post-write reads; agentLoop may add more during follow-up tool\n // calls; finally clears it at turn end (skipping when paused).\n this.turnPaused = false;\n try {\n yield* this.agentLoop(null, signal, false);\n } finally {\n if (!this.turnPaused) {\n this.turnReadCache.clear();\n }\n }\n }\n\n /**\n * [v1.5] Auto-run configured read tools after a successful write,\n * push their results into the conversation, and yield `tool_result`\n * events so hosts/UI render them in the timeline. See\n * `EngineConfig.postWriteRefresh`.\n *\n * Pure injection — no LLM call here. The next `agentLoop` turn sees\n * the fresh tool results and narrates from them.\n */\n private async *runPostWriteRefresh(\n action: PendingAction,\n response: PermissionResponse,\n signal: AbortSignal,\n ): AsyncGenerator<EngineEvent> {\n const refreshList = this.postWriteRefresh?.[action.toolName];\n if (!refreshList || refreshList.length === 0) return;\n\n // Refresh only on confirmed success. Failed writes leave on-chain\n // state untouched; refreshing would just surface the pre-write\n // snapshot a second time — wasted RPC + zero new info.\n const exec = response.executionResult;\n const writeFailed =\n exec != null &&\n typeof exec === 'object' &&\n 'success' in exec &&\n (exec as { success?: unknown }).success === false;\n if (writeFailed) return;\n\n // Resolve & filter — silently drop unknown / non-readonly entries\n // so config drift between host & engine never breaks resume.\n const refreshTools = refreshList\n .map((name) => findTool(this.tools, name))\n .filter((t): t is Tool =>\n t !== undefined && t.isReadOnly && t.isConcurrencySafe,\n );\n if (refreshTools.length === 0) return;\n\n const context: ToolContext = {\n agent: this.agent,\n mcpManager: this.mcpManager,\n walletAddress: this.walletAddress,\n suiRpcUrl: this.suiRpcUrl,\n serverPositions: this.serverPositions,\n positionFetcher: this.positionFetcher,\n env: this.env,\n signal,\n priceCache: this.priceCache,\n permissionConfig: this.permissionConfig,\n sessionSpendUsd: this.sessionSpendUsd,\n blockvisionApiKey: this.blockvisionApiKey,\n portfolioCache: this.portfolioCache,\n };\n\n // [v1.4 — Day 2.5] Bust both portfolio caches for this address before\n // the 1.5s Sui-RPC-indexer-lag delay. The v1.4 BlockVision swap\n // introduced two caching layers — `ToolContext.portfolioCache`\n // (per-request Map, no TTL) and the module-level cache in\n // `blockvision-prices.ts` (60s TTL). Without explicit invalidation,\n // `runPostWriteRefresh` re-runs `balance_check`, which calls\n // `fetchAddressPortfolio()`, which returns the *cached pre-write\n // snapshot* — defeating the entire point of post-write refresh and\n // resurrecting the v0.46.16-era class of \"I deposited 20 USDC but\n // the agent says my balance didn't change\" bug. Pre-v1.4 the same\n // path called `fetchWalletCoins` (Sui RPC, no cache) so the 1.5s\n // delay alone was sufficient; post-v1.4 we MUST invalidate or no\n // amount of waiting will help.\n //\n // [PR 1 — v0.55] `clearPortfolioCacheFor` is now async (Upstash-backed\n // when Audric injects the store) — MUST be awaited or the next\n // `balance_check` races the Redis delete and refetches the stale\n // pre-write balance. Pre-PR-1 it was a sync Map.delete and\n // fire-and-forget worked; under Redis the network round-trip is\n // load-bearing.\n if (this.walletAddress) {\n this.portfolioCache?.delete(this.walletAddress);\n await clearPortfolioCacheFor(this.walletAddress);\n }\n\n // [v0.46.16] Sui RPC indexer lag — `executeTransactionBlock` returns\n // as soon as the tx is included in a checkpoint, but the public RPC's\n // owned-coin index trails by ~500-1500ms. Without this delay the\n // injected `balance_check` returns the *pre-write* snapshot and the\n // LLM either trusts it (wrong) or has to reason around it (noisy).\n // 1500ms catches ~99% of cases on Sui mainnet; the refresh is async\n // anyway so this doesn't block the UI's pending_action resolution.\n if (!signal.aborted) {\n await new Promise<void>((resolve) => {\n const t = setTimeout(resolve, 1500);\n signal.addEventListener('abort', () => { clearTimeout(t); resolve(); }, { once: true });\n });\n }\n if (signal.aborted) return;\n\n // Run all refreshes in parallel — they're read-only and target\n // different RPC endpoints (wallet, NAVI positions, health). The\n // common case (1-3 tools) finishes well under 1s.\n const idStem = `pwr_${action.toolUseId.slice(-6)}`;\n const refreshes = await Promise.all(\n refreshTools.map(async (tool, idx) => {\n const id = `${idStem}_${idx}_${tool.name}`;\n try {\n const parsed = tool.inputSchema.safeParse({});\n if (!parsed.success) {\n return {\n tool,\n id,\n isError: true as const,\n data: {\n error: `Post-write refresh: invalid input for ${tool.name}`,\n },\n attemptCount: undefined as number | undefined,\n };\n }\n // [SPEC 8 v0.5.1 B3.2] Per-tool retry counter — each refresh\n // gets its own context override so attemptCount doesn't bleed\n // across the parallel batch.\n const { context: toolCtx, readAttemptCount } = withRetryStats(context);\n const result = await tool.call(parsed.data, toolCtx);\n return {\n tool,\n id,\n isError: false as const,\n data: result.data,\n attemptCount: readAttemptCount(),\n };\n } catch (err) {\n return {\n tool,\n id,\n isError: true as const,\n data: {\n error:\n err instanceof Error\n ? err.message\n : 'Post-write refresh failed',\n },\n attemptCount: undefined as number | undefined,\n };\n }\n }),\n );\n\n // Push synthetic conversation pair so the LLM sees:\n // assistant(refresh tool_uses) → user(refresh tool_results)\n // Anthropic accepts back-to-back assistant/user blocks; this is the\n // same shape `buildSyntheticPrefetch` uses at session start.\n const refreshUses: ContentBlock[] = refreshes.map((r) => ({\n type: 'tool_use',\n id: r.id,\n name: r.tool.name,\n input: {},\n }));\n this.messages.push({ role: 'assistant', content: refreshUses });\n\n const refreshResults: ContentBlock[] = refreshes.map((r) => ({\n type: 'tool_result',\n toolUseId: r.id,\n content: typeof r.data === 'string' ? r.data : JSON.stringify(r.data),\n isError: r.isError,\n }));\n this.messages.push({ role: 'user', content: refreshResults });\n\n // Yield events so hosts log them in `TurnMetrics.toolsCalled[]` and\n // the UI renders the refreshed cards in-line. Also populate the\n // intra-turn cache so any LLM-driven `tool_use` for the same\n // (name, input) during the resumed agent loop dedups instead of\n // double-rendering on top of the refresh card.\n for (const r of refreshes) {\n if (!r.isError) {\n this.turnReadCache.set(\n TurnReadCache.keyFor(r.tool.name, {}),\n { result: r.data, sourceToolUseId: r.id },\n );\n }\n yield {\n type: 'tool_result',\n toolName: r.tool.name,\n toolUseId: r.id,\n result: r.data,\n isError: r.isError,\n wasPostWriteRefresh: true,\n ...(r.attemptCount !== undefined ? { attemptCount: r.attemptCount } : {}),\n };\n }\n }\n\n interrupt(): void {\n this.abortController?.abort();\n }\n\n getMessages(): readonly Message[] {\n return this.messages;\n }\n\n getMatchedRecipe(): Recipe | null {\n return this.matchedRecipe;\n }\n\n getContextBudget(): ContextBudget {\n return this.contextBudget;\n }\n\n reset(): void {\n this.messages = [];\n this.costTracker.reset();\n this.contextBudget.reset();\n this.guardEvents = [];\n this.matchedRecipe = null;\n }\n\n getGuardEvents(): readonly GuardEvent[] {\n return this.guardEvents;\n }\n\n loadMessages(messages: Message[]): void {\n this.messages = [...messages];\n }\n\n /**\n * [v0.46.7] Run a read-only tool out-of-band, using the engine's tool\n * registry and ToolContext. Used by hosts to deterministically pre-dispatch\n * tools based on user-message intent (e.g. always call `balance_check` when\n * the user says \"what's my net worth?\", regardless of whether the LLM would\n * have otherwise re-called it).\n *\n * The host is responsible for:\n * - Streaming the synthetic `tool_start` + `tool_result` events to the UI\n * (so cards render as if the LLM had called the tool).\n * - Appending matching `tool_use` + `tool_result` ContentBlocks to the\n * engine's message history via `loadMessages([...getMessages(), ...synth])`\n * BEFORE calling `submitMessage`, so the LLM sees the fresh data and\n * doesn't re-call.\n *\n * Throws if the tool isn't registered, isn't read-only, or fails input\n * validation. Tool execution errors are returned as `{ data, isError: true }`\n * for the caller to handle (typically: skip the injection so the LLM falls\n * back to its normal flow).\n */\n async invokeReadTool(\n toolName: string,\n input: unknown,\n options: { signal?: AbortSignal } = {},\n ): Promise<{ data: unknown; isError: boolean }> {\n const tool = findTool(this.tools, toolName);\n if (!tool) throw new Error(`invokeReadTool: tool not found: ${toolName}`);\n if (!tool.isReadOnly) {\n throw new Error(`invokeReadTool: tool is not read-only: ${toolName} (write tools must go through the permission gate)`);\n }\n\n const parsed = tool.inputSchema.safeParse(input);\n if (!parsed.success) {\n throw new Error(\n `invokeReadTool: invalid input for ${toolName}: ${parsed.error.issues.map((i) => i.message).join(', ')}`,\n );\n }\n\n // [v0.46.8] Intra-turn cache: if the same tool was already invoked\n // (either via a prior `invokeReadTool` call or by the LLM mid-turn),\n // return the cached result without re-fetching. Makes pre-dispatch\n // idempotent — calling `invokeReadTool('balance_check', {})` twice\n // back-to-back hits RPC once, not twice.\n const cacheKey = TurnReadCache.keyFor(toolName, parsed.data);\n const cached = this.turnReadCache.get(cacheKey);\n if (cached) {\n return { data: cached.result, isError: false };\n }\n\n const signal = options.signal ?? new AbortController().signal;\n const context: ToolContext = {\n agent: this.agent,\n mcpManager: this.mcpManager,\n walletAddress: this.walletAddress,\n suiRpcUrl: this.suiRpcUrl,\n serverPositions: this.serverPositions,\n positionFetcher: this.positionFetcher,\n env: this.env,\n signal,\n priceCache: this.priceCache,\n permissionConfig: this.permissionConfig,\n sessionSpendUsd: this.sessionSpendUsd,\n blockvisionApiKey: this.blockvisionApiKey,\n portfolioCache: this.portfolioCache,\n };\n\n try {\n const result = await tool.call(parsed.data, context);\n // Cache the successful result so a subsequent LLM-driven\n // `tool_use` for the same (name, input) hits the dedup path in\n // the agent loop and the host doesn't render a duplicate card.\n this.turnReadCache.set(cacheKey, {\n result: result.data,\n sourceToolUseId: 'invokeReadTool',\n });\n return { data: result.data, isError: false };\n } catch (err) {\n // Errors are NOT cached — the next call should retry, not see a\n // stale failure.\n return {\n data: { error: err instanceof Error ? err.message : 'Tool execution failed' },\n isError: true,\n };\n }\n }\n\n setServerPositions(data: EngineConfig['serverPositions']): void {\n this.serverPositions = data;\n }\n\n getUsage(): CostSnapshot {\n return this.costTracker.getSnapshot();\n }\n\n // ---------------------------------------------------------------------------\n // Core agent loop — shared by submitMessage and resumeWithToolResult\n // ---------------------------------------------------------------------------\n\n /**\n * Run the LLM → tool → LLM loop. When a write tool needs confirmation,\n * yields `pending_action` and returns immediately (stream ends cleanly).\n *\n * @param freshPrompt - The original user prompt (for corrupt-history retry). Null on resume.\n */\n private async *agentLoop(\n freshPrompt: string | null,\n signal: AbortSignal,\n applyToolChoice = true,\n ): AsyncGenerator<EngineEvent> {\n const context: ToolContext = {\n agent: this.agent,\n mcpManager: this.mcpManager,\n walletAddress: this.walletAddress,\n suiRpcUrl: this.suiRpcUrl,\n serverPositions: this.serverPositions,\n positionFetcher: this.positionFetcher,\n env: this.env,\n signal,\n priceCache: this.priceCache,\n permissionConfig: this.permissionConfig,\n sessionSpendUsd: this.sessionSpendUsd,\n blockvisionApiKey: this.blockvisionApiKey,\n portfolioCache: this.portfolioCache,\n };\n\n let turns = 0;\n let hasRetriedWithCleanHistory = false;\n let turnStartMs = Date.now();\n\n while (turns < this.maxTurns) {\n if (signal.aborted) {\n yield { type: 'error', error: new Error('Aborted') };\n return;\n }\n\n turns++;\n turnStartMs = Date.now();\n const toolDefs = toolsToDefinitions(this.tools);\n\n const acc: TurnAccumulator = {\n text: '',\n stopReason: 'end_turn',\n assistantBlocks: [],\n pendingToolCalls: [],\n };\n\n const dispatcher = new EarlyToolDispatcher(this.tools, context, this.turnReadCache);\n\n try {\n // B.3: Zero-cost dedup of identical tool calls every turn.\n // [v1.4 Item 4] Emit a synthetic tool_result event for each\n // deduped prior call so hosts can flip `resultDeduped` on the\n // matching `TurnMetrics.toolsCalled[]` row. Marker shape is\n // explicit so collectors don't double-count emissions.\n // [v1.5.1] Pass the tool registry so microcompact honors per-tool\n // `cacheable` flags. Mutable-state reads (balance_check etc.)\n // never dedupe, so post-write refreshes always surface fresh\n // data instead of a \"[Same result as call #N]\" marker that the\n // LLM previously misread as \"stale snapshot, fall back to math\".\n const microcompacted = microcompact(this.messages, this.tools);\n this.messages = microcompacted;\n for (const dedupedId of microcompacted.dedupedToolUseIds) {\n yield {\n type: 'tool_result',\n toolName: '__deduped__',\n toolUseId: dedupedId,\n result: null,\n isError: false,\n resultDeduped: true,\n };\n }\n\n // RE-3.3: Compact context if budget is exceeded\n if (this.contextBudget.shouldCompact()) {\n this.messages = await compactMessages(this.messages, {\n maxTokens: 100_000,\n keepRecentCount: 8,\n summarizer: this.contextSummarizer,\n });\n // [v1.4 Item 4] Notify hosts that compaction fired this turn.\n // `compactMessages` stays a pure function; the event keeps the\n // signal observable without coupling.\n yield { type: 'compaction' };\n }\n\n this.messages = validateHistory(this.messages);\n\n if (process.env.NODE_ENV !== 'test') {\n const summary = this.messages.map((m, idx) => {\n const blocks = m.content.map((b) => {\n if (b.type === 'text') return `text(${b.text.slice(0, 40)}…)`;\n if (b.type === 'thinking') return `thinking(${b.thinking.length}ch)`;\n if (b.type === 'redacted_thinking') return `redacted_thinking`;\n if (b.type === 'tool_use') return `tool_use:${b.id.slice(-8)}/${b.name}`;\n return `tool_result:${(b as { toolUseId: string }).toolUseId.slice(-8)}`;\n });\n return ` [${idx}] ${m.role}: [${blocks.join(', ')}]`;\n });\n console.log(`[engine] provider.chat turn=${turns} msgs=${this.messages.length}\\n${summary.join('\\n')}`);\n }\n\n const thinkingEnabled = this.thinking && this.thinking.type !== 'disabled';\n // Anthropic requires toolChoice 'auto' (not 'any') when thinking is enabled\n const effectiveToolChoice = thinkingEnabled\n ? ((applyToolChoice && turns === 1) ? 'auto' as const : undefined)\n : ((applyToolChoice && turns === 1) ? this.toolChoice : undefined);\n\n // RE-3.1: Inject matched recipe context into system prompt for this turn\n let effectivePrompt = this.systemPrompt;\n if (this.matchedRecipe && this.recipes) {\n const recipeCtx = this.recipes.toPromptContext(this.matchedRecipe);\n if (typeof effectivePrompt === 'string') {\n effectivePrompt = `${effectivePrompt}\\n\\n${recipeCtx}`;\n } else if (Array.isArray(effectivePrompt)) {\n effectivePrompt = [\n ...effectivePrompt,\n { type: 'text' as const, text: recipeCtx },\n ];\n }\n }\n\n // [SPEC 8 v0.5.1] HARD-cap thinking budget per effort tier.\n // lean=disabled, standard=8k, rich=16k, max=32k. Hosts that pass\n // a smaller budget keep it; the engine only ever clamps DOWN.\n // See thinking-budget.ts for the full rationale.\n const cappedThinking = clampThinkingForEffort(this.thinking, this.outputConfig?.effort);\n\n const stream = this.provider.chat({\n messages: this.messages,\n systemPrompt: effectivePrompt,\n tools: toolDefs,\n model: this.model,\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n toolChoice: effectiveToolChoice,\n thinking: cappedThinking,\n outputConfig: this.outputConfig,\n signal,\n });\n\n for await (const event of stream) {\n yield* this.handleProviderEvent(event, acc, dispatcher);\n }\n } catch (err) {\n if (freshPrompt && !hasRetriedWithCleanHistory && isCorruptHistoryError(err)) {\n hasRetriedWithCleanHistory = true;\n console.warn('[engine] Corrupt session history detected, resetting to fresh conversation');\n this.messages = [\n { role: 'user', content: [{ type: 'text', text: freshPrompt }] },\n ];\n turns--;\n continue;\n }\n throw err;\n }\n\n if (acc.text) {\n acc.assistantBlocks.push({ type: 'text', text: acc.text });\n }\n\n // B.1: Collect results from early-dispatched tools\n const earlyResultBlocks: ContentBlock[] = [];\n if (dispatcher.hasPending()) {\n if (signal.aborted) {\n dispatcher.abort();\n }\n for await (const earlyEvent of dispatcher.collectResults()) {\n if (earlyEvent.type === 'tool_result') {\n if (!earlyEvent.isError) {\n const warning = flagSuspiciousResult(earlyEvent.toolName, earlyEvent.result);\n if (warning) {\n const flagged = {\n ...earlyEvent,\n result: typeof earlyEvent.result === 'object' && earlyEvent.result\n ? { ...earlyEvent.result as Record<string, unknown>, _warning: warning }\n : { data: earlyEvent.result, _warning: warning },\n };\n yield flagged;\n earlyResultBlocks.push({\n type: 'tool_result',\n toolUseId: flagged.toolUseId,\n content: JSON.stringify(flagged.result),\n isError: flagged.isError,\n });\n continue;\n }\n }\n const tool = findTool(this.tools, earlyEvent.toolName);\n // Pull the original input back off the dispatcher so guard state\n // (e.g. SwapQuoteTracker) can key off it. Passing `null` here was\n // a silent regression that made guardSwapPreview block every\n // swap_execute even after a successful early-dispatched\n // swap_quote.\n const earlyInput = dispatcher.getInputById(earlyEvent.toolUseId) ?? null;\n updateGuardStateAfterToolResult(\n earlyEvent.toolName, tool, earlyInput, earlyEvent.result, earlyEvent.isError, this.guardState,\n );\n\n let enrichedResult = earlyEvent.result;\n if (this.guardConfig && !earlyEvent.isError && tool) {\n const artifactInj = this.guardConfig.artifactPreview !== false\n ? guardArtifactPreview(earlyEvent.result)\n : null;\n const staleInj = this.guardConfig.staleData !== false\n ? guardStaleData(tool.flags)\n : null;\n const allInjections = [\n ...(artifactInj ? [artifactInj] : []),\n ...(staleInj ? [staleInj] : []),\n ];\n if (allInjections.length > 0 && typeof enrichedResult === 'object' && enrichedResult) {\n enrichedResult = { ...enrichedResult as Record<string, unknown>, _guards: allInjections };\n }\n }\n\n const finalEvent = enrichedResult !== earlyEvent.result\n ? { ...earlyEvent, result: enrichedResult }\n : earlyEvent;\n\n yield finalEvent;\n\n if (!finalEvent.isError) {\n const r = finalEvent.result as Record<string, unknown> | null;\n if (r && r.__canvas === true) {\n yield {\n type: 'canvas',\n template: String(r.template ?? ''),\n title: String(r.title ?? ''),\n data: r.templateData ?? null,\n toolUseId: finalEvent.toolUseId,\n };\n }\n // [SPEC 8 v0.5.1] Side-channel todo_update event paired to\n // every update_todo tool result. Mirrors the __canvas\n // pattern above; see tools/update-todo.ts for rationale.\n if (r && r.__todoUpdate === true && Array.isArray(r.items)) {\n yield {\n type: 'todo_update',\n items: r.items as { id: string; label: string; status: 'pending' | 'in_progress' | 'completed' }[],\n toolUseId: finalEvent.toolUseId,\n };\n }\n }\n\n earlyResultBlocks.push({\n type: 'tool_result',\n toolUseId: finalEvent.toolUseId,\n content: JSON.stringify(finalEvent.result),\n isError: finalEvent.isError,\n });\n }\n }\n }\n\n const hasEarlyResults = earlyResultBlocks.length > 0;\n const hasRemainingCalls = acc.pendingToolCalls.length > 0;\n\n if (!hasEarlyResults && !hasRemainingCalls) {\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n getTelemetrySink().histogram('anthropic.latency_ms', Date.now() - turnStartMs);\n yield { type: 'turn_complete', stopReason: acc.stopReason };\n return;\n }\n\n if (signal.aborted) {\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n if (hasEarlyResults) {\n this.messages.push({ role: 'user', content: earlyResultBlocks });\n }\n this.addErrorResults(acc.pendingToolCalls, 'Aborted');\n yield { type: 'error', error: new Error('Aborted') };\n return;\n }\n\n // --- Permission gate (only for non-early-dispatched calls) ---\n const approved: PendingToolCall[] = [];\n const toolResultBlocks: ContentBlock[] = [...earlyResultBlocks];\n let pendingWrite: { call: PendingToolCall; tool: Tool } | null = null;\n\n for (const call of acc.pendingToolCalls) {\n const tool = findTool(this.tools, call.name);\n\n // [v0.46.8] Intra-turn dedup for read-only tools. If the host\n // pre-dispatched this tool (via `invokeReadTool`) or the LLM\n // already called it earlier in the same turn, skip execution\n // and emit a deduped `tool_result` so the host can suppress\n // a duplicate card render. The LLM still gets a valid\n // `tool_result` block keyed to ITS `tool_use_id`, satisfying\n // the Anthropic protocol requirement that every `tool_use`\n // be answered by a matching `tool_result`.\n if (tool && tool.isReadOnly) {\n const cacheKey = TurnReadCache.keyFor(call.name, call.input);\n const cached = this.turnReadCache.get(cacheKey);\n if (cached) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: cached.result,\n isError: false,\n resultDeduped: true,\n };\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: call.id,\n content: JSON.stringify(cached.result),\n isError: false,\n });\n continue;\n }\n }\n\n const needsConfirmation = (() => {\n if (!tool || tool.isReadOnly) return false;\n if (tool.permissionLevel === 'explicit') return true;\n // [v0.46.15] Honor `permissionLevel: 'auto'` on write tools even\n // when no agent is present. These are custom tools (e.g. audric's\n // server-owned save_contact / savings_goal_*) that persist via\n // their own data layer (Prisma) and never need on-chain signing.\n // They explicitly opted into auto by setting the permission\n // level — gating them on `context.agent` here silently broke\n // every audric Prisma-backed write tool. Tools that DO need\n // an agent must NOT set permissionLevel: 'auto'.\n if (tool.permissionLevel === 'auto' && !toolNameToOperation(call.name)) {\n return false;\n }\n // Without an agent, write tools can't execute server-side —\n // always require confirmation so the client handles execution.\n if (!context.agent && !tool.isReadOnly) return true;\n if (context.permissionConfig && context.priceCache) {\n const operation = toolNameToOperation(call.name);\n if (operation) {\n const usdValue = resolveUsdValue(call.name, call.input as Record<string, unknown>, context.priceCache);\n const callInput = call.input as Record<string, unknown>;\n // [v1.4] sessionSpendUsd enforces daily cap.\n // Send-safety: a raw 0x recipient with no contact match\n // forces `confirm` regardless of amount (see permission-rules).\n const tier = resolvePermissionTier(\n operation,\n usdValue,\n context.permissionConfig,\n context.sessionSpendUsd,\n operation === 'send'\n ? { to: typeof callInput.to === 'string' ? callInput.to : undefined, contacts: this.contacts }\n : undefined,\n );\n return tier !== 'auto';\n }\n }\n return tool.permissionLevel !== 'auto';\n })();\n\n if (!needsConfirmation) {\n approved.push(call);\n yield { type: 'tool_start', toolName: call.name, toolUseId: call.id, input: call.input };\n continue;\n }\n\n pendingWrite = { call, tool: tool! };\n break;\n }\n\n // --- Guard checks (pre-execution) ---\n const guardedApproved: PendingToolCall[] = [];\n\n if (this.guardConfig) {\n const convCtx = extractConversationText(this.messages);\n\n for (const call of approved) {\n const tool = findTool(this.tools, call.name);\n if (!tool) { guardedApproved.push(call); continue; }\n\n const check = runGuards(\n tool,\n call,\n this.guardState,\n this.guardConfig,\n convCtx,\n this.onGuardFired,\n { contacts: this.contacts, walletAddress: this.walletAddress },\n );\n this.guardEvents.push(...check.events);\n\n if (check.blocked) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: check.blockReason, _gate: check.blockGate },\n isError: true,\n };\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: call.id,\n content: JSON.stringify({ error: check.blockReason, _gate: check.blockGate }),\n isError: true,\n });\n continue;\n }\n\n if (check.injections.length > 0) {\n (call as PendingToolCall & { _guardInjections?: unknown[] })._guardInjections = check.injections;\n }\n guardedApproved.push(call);\n }\n } else {\n guardedApproved.push(...approved);\n }\n\n // Execute auto-approved tool calls (reads) even if a write is pending\n for await (const toolEvent of runTools(guardedApproved, this.tools, context, this.txMutex)) {\n if (toolEvent.type === 'tool_result' && !toolEvent.isError) {\n const warning = flagSuspiciousResult(toolEvent.toolName, toolEvent.result);\n if (warning) {\n const flagged = {\n ...toolEvent,\n result: typeof toolEvent.result === 'object' && toolEvent.result\n ? { ...toolEvent.result as Record<string, unknown>, _warning: warning }\n : { data: toolEvent.result, _warning: warning },\n };\n yield flagged;\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: flagged.toolUseId,\n content: JSON.stringify(flagged.result),\n isError: flagged.isError,\n });\n continue;\n }\n }\n\n // Post-execution: update guard state & apply injections\n if (toolEvent.type === 'tool_result') {\n const tool = findTool(this.tools, toolEvent.toolName);\n const originalCall = guardedApproved.find((c) => c.id === toolEvent.toolUseId);\n updateGuardStateAfterToolResult(\n toolEvent.toolName, tool, originalCall?.input ?? null, toolEvent.result, toolEvent.isError, this.guardState,\n );\n\n let enrichedResult = toolEvent.result;\n\n if (this.guardConfig && !toolEvent.isError && tool) {\n // Post-execution guards: artifact preview, stale data hint\n const artifactInj = this.guardConfig.artifactPreview !== false\n ? guardArtifactPreview(toolEvent.result)\n : null;\n const staleInj = this.guardConfig.staleData !== false\n ? guardStaleData(tool.flags)\n : null;\n\n // Merge pre-execution injections from guard check\n const preInjections =\n (guardedApproved.find((c) => c.id === toolEvent.toolUseId) as\n PendingToolCall & { _guardInjections?: unknown[] })?._guardInjections ?? [];\n\n const allInjections = [\n ...preInjections,\n ...(artifactInj ? [artifactInj] : []),\n ...(staleInj ? [staleInj] : []),\n ];\n\n if (allInjections.length > 0 && typeof enrichedResult === 'object' && enrichedResult) {\n enrichedResult = { ...enrichedResult as Record<string, unknown>, _guards: allInjections };\n }\n }\n\n const finalEvent = enrichedResult !== toolEvent.result\n ? { ...toolEvent, result: enrichedResult }\n : toolEvent;\n\n // [v0.46.8] Maintain the intra-turn read cache:\n // - Successful read → populate so subsequent identical\n // calls within the same turn dedup.\n // - Successful write → invalidate the entire cache; on-chain\n // state has changed, any prior read snapshot is stale.\n // - Errored result → leave cache untouched; retry should\n // re-execute.\n if (!finalEvent.isError && tool) {\n if (tool.isReadOnly) {\n const inputForKey = originalCall?.input ?? {};\n const cacheKey = TurnReadCache.keyFor(finalEvent.toolName, inputForKey);\n this.turnReadCache.set(cacheKey, {\n result: finalEvent.result,\n sourceToolUseId: finalEvent.toolUseId,\n });\n } else {\n this.turnReadCache.clear();\n }\n }\n\n yield finalEvent;\n\n if (finalEvent.type === 'tool_result' && !finalEvent.isError) {\n const r = finalEvent.result as Record<string, unknown> | null;\n if (r && r.__canvas === true) {\n yield {\n type: 'canvas',\n template: String(r.template ?? ''),\n title: String(r.title ?? ''),\n data: r.templateData ?? null,\n toolUseId: finalEvent.toolUseId,\n };\n }\n // [SPEC 8 v0.5.1] Side-channel todo_update event for the\n // late-dispatch path. Mirrors the early-dispatch emission\n // ~250 lines above.\n if (r && r.__todoUpdate === true && Array.isArray(r.items)) {\n yield {\n type: 'todo_update',\n items: r.items as { id: string; label: string; status: 'pending' | 'in_progress' | 'completed' }[],\n toolUseId: finalEvent.toolUseId,\n };\n }\n\n // [v1.4] Fire onAutoExecuted for write tools that auto-executed\n // (non-readonly tools that reach this loop have already passed the\n // auto-tier check). Wrapped in try/catch so any host error never\n // propagates back into the engine — the tool result already shipped.\n if (\n tool && !tool.isReadOnly && this.onAutoExecuted &&\n this.permissionConfig && this.priceCache\n ) {\n const operation = toolNameToOperation(toolEvent.toolName);\n if (operation && originalCall) {\n const usdValue = resolveUsdValue(\n toolEvent.toolName,\n originalCall.input as Record<string, unknown>,\n this.priceCache,\n );\n Promise.resolve()\n .then(() => this.onAutoExecuted!({\n toolName: toolEvent.toolName,\n usdValue,\n walletAddress: this.walletAddress,\n }))\n .catch((err) => {\n console.warn('[engine] onAutoExecuted callback failed:', err);\n });\n }\n }\n }\n\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: finalEvent.toolUseId,\n content: JSON.stringify(finalEvent.result),\n isError: finalEvent.isError,\n });\n continue;\n }\n\n yield toolEvent;\n }\n\n // --- Guard check on pending write tool ---\n if (pendingWrite && this.guardConfig) {\n const convCtx = extractConversationText(this.messages);\n const check = runGuards(\n pendingWrite.tool,\n pendingWrite.call,\n this.guardState,\n this.guardConfig,\n convCtx,\n this.onGuardFired,\n { contacts: this.contacts, walletAddress: this.walletAddress },\n );\n this.guardEvents.push(...check.events);\n\n if (check.blocked) {\n yield {\n type: 'tool_result',\n toolName: pendingWrite.call.name,\n toolUseId: pendingWrite.call.id,\n result: { error: check.blockReason, _gate: check.blockGate },\n isError: true,\n };\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: pendingWrite.call.id,\n content: JSON.stringify({ error: check.blockReason, _gate: check.blockGate }),\n isError: true,\n });\n // Blocked write — don't yield pending_action, feed error back to LLM\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n this.messages.push({ role: 'user', content: toolResultBlocks });\n continue;\n }\n\n if (check.injections.length > 0) {\n (pendingWrite.call as PendingToolCall & { _guardInjections?: unknown[] })._guardInjections = check.injections;\n }\n }\n\n if (pendingWrite) {\n // Do NOT push assistant message to this.messages — session stays clean.\n // The full assistant content is stored in PendingAction so\n // resumeWithToolResult can reconstruct the turn atomically.\n const writeGuardInjections =\n (pendingWrite.call as PendingToolCall & { _guardInjections?: Array<{ _gate: string; _hint?: string; _warning?: string }> })._guardInjections;\n\n // [v1.4 Item 6] Stamp the action with the registry's modifiable\n // fields (UI uses this to render editable controls) and a turnIndex\n // derived from the assistant message count so hosts can update the\n // matching `TurnMetrics` row when the action resolves.\n const modifiableFields = getModifiableFields(pendingWrite.call.name);\n const turnIndex = this.messages.filter((m) => m.role === 'assistant').length;\n // [v1.4.2 — Day 3] Per-yield UUID. Hosts write this onto the\n // `TurnMetrics` row at chat-time and key the resume route's update\n // on it (instead of `(sessionId, turnIndex)`), eliminating the\n // false-resolution path documented in spec §Item 3. Generated at\n // yield rather than at construction so each emission of a write\n // (e.g. user-edited resume that re-runs the agent loop) gets a\n // fresh id and its own `TurnMetrics` row.\n const attemptId = randomUUID();\n\n // [v0.46.8] Mark the turn as paused so the submitMessage /\n // resumeWithToolResult `finally` blocks DON'T clear the cache.\n // The pending write may resume; cache must survive the pause\n // so post-resume execution still benefits from intra-turn dedup.\n this.turnPaused = true;\n yield {\n type: 'pending_action',\n action: {\n toolName: pendingWrite.call.name,\n toolUseId: pendingWrite.call.id,\n input: pendingWrite.call.input,\n description: describeAction(pendingWrite.tool, pendingWrite.call),\n assistantContent: acc.assistantBlocks,\n completedResults: toolResultBlocks.map((b) => ({\n toolUseId: (b as { toolUseId: string }).toolUseId,\n content: (b as { content: string }).content,\n isError: (b as { isError?: boolean }).isError ?? false,\n })),\n ...(writeGuardInjections?.length ? { guardInjections: writeGuardInjections } : {}),\n ...(modifiableFields?.length ? { modifiableFields } : {}),\n turnIndex,\n attemptId,\n },\n };\n return;\n }\n\n // All tools auto-approved — push the complete turn (assistant + results)\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n this.messages.push({ role: 'user', content: toolResultBlocks });\n\n // [SPEC 8 v0.5.1] update_todo maxTurns exemption.\n //\n // Calling update_todo documents work; it doesn't advance work. If the\n // LLM fires it 4× during a 5-tool plan, that's 4 of its 10-turn budget\n // gone to narration before any real action. We exempt iterations\n // whose only tool calls were update_todo by decrementing the counter.\n //\n // The check looks at every `tool_use` block in this iteration's\n // `acc.assistantBlocks` (covers both early-dispatched and late-\n // dispatched calls). If every one was `update_todo`, decrement.\n // Mixed iterations (e.g. balance_check + update_todo) DO count —\n // that's a real piece of work the LLM is doing.\n const toolUseBlocks = acc.assistantBlocks.filter((b) => b.type === 'tool_use') as { name: string }[];\n const allUpdateTodo =\n toolUseBlocks.length > 0 && toolUseBlocks.every((b) => b.name === 'update_todo');\n if (allUpdateTodo) {\n turns--;\n }\n\n if (this.costTracker.isOverBudget()) {\n yield { type: 'error', error: new Error('Session budget exceeded') };\n return;\n }\n }\n\n yield { type: 'turn_complete', stopReason: 'max_turns' };\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n private addErrorResults(pendingCalls: PendingToolCall[], reason: string): void {\n const errorBlocks: ContentBlock[] = pendingCalls.map((call) => ({\n type: 'tool_result' as const,\n toolUseId: call.id,\n content: JSON.stringify({ error: reason }),\n isError: true,\n }));\n if (errorBlocks.length > 0) {\n this.messages.push({ role: 'user', content: errorBlocks });\n }\n }\n\n private *handleProviderEvent(\n event: ProviderEvent,\n acc: TurnAccumulator,\n dispatcher?: EarlyToolDispatcher,\n ): Generator<EngineEvent> {\n switch (event.type) {\n case 'thinking_delta': {\n yield { type: 'thinking_delta', text: event.text, blockIndex: event.blockIndex };\n break;\n }\n\n case 'thinking_done': {\n acc.assistantBlocks.push({\n type: 'thinking',\n thinking: event.thinking,\n signature: event.signature,\n });\n yield {\n type: 'thinking_done',\n blockIndex: event.blockIndex,\n signature: event.signature,\n // [SPEC 8 v0.5.1] forward HowIEvaluated structured fields when\n // the provider parsed an <eval_summary> marker.\n ...(event.summaryMode && event.evaluationItems\n ? { summaryMode: true, evaluationItems: event.evaluationItems }\n : {}),\n };\n break;\n }\n\n case 'redacted_thinking': {\n acc.assistantBlocks.push({\n type: 'redacted_thinking',\n data: event.data,\n });\n break;\n }\n\n case 'text_delta': {\n acc.text += event.text;\n yield { type: 'text_delta', text: event.text };\n break;\n }\n\n case 'tool_use_done': {\n if (acc.text) {\n acc.assistantBlocks.push({ type: 'text', text: acc.text });\n acc.text = '';\n }\n acc.assistantBlocks.push({\n type: 'tool_use',\n id: event.id,\n name: event.name,\n input: event.input,\n });\n\n const call: PendingToolCall = { id: event.id, name: event.name, input: event.input };\n\n // B.1: Try early dispatch for read-only tools mid-stream\n if (dispatcher?.tryDispatch(call)) {\n yield { type: 'tool_start', toolName: call.name, toolUseId: call.id, input: call.input };\n } else {\n acc.pendingToolCalls.push(call);\n }\n break;\n }\n\n case 'usage': {\n this.costTracker.track(\n event.inputTokens,\n event.outputTokens,\n event.cacheReadTokens,\n event.cacheWriteTokens,\n );\n this.contextBudget.update(event.inputTokens);\n const sink = getTelemetrySink();\n if (event.inputTokens) sink.counter('anthropic.tokens', { kind: 'input' }, event.inputTokens);\n if (event.outputTokens) sink.counter('anthropic.tokens', { kind: 'output' }, event.outputTokens);\n if (event.cacheReadTokens) sink.counter('anthropic.tokens', { kind: 'cache_read' }, event.cacheReadTokens);\n if (event.cacheWriteTokens) sink.counter('anthropic.tokens', { kind: 'cache_write' }, event.cacheWriteTokens);\n yield {\n type: 'usage',\n inputTokens: event.inputTokens,\n outputTokens: event.outputTokens,\n cacheReadTokens: event.cacheReadTokens,\n cacheWriteTokens: event.cacheWriteTokens,\n };\n break;\n }\n\n case 'stop': {\n acc.stopReason = event.reason;\n break;\n }\n\n default:\n break;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isCorruptHistoryError(err: unknown): boolean {\n const msg = err instanceof Error ? err.message : String(err);\n return (\n (msg.includes('tool_use') && msg.includes('tool_result')) ||\n msg.includes('roles must alternate') ||\n (msg.includes('400') && msg.includes('invalid_request_error'))\n );\n}\n\n/**\n * Pre-flight validation: ensures message history meets Anthropic's requirements\n * right before every API call. Anthropic requires that every tool_use in an\n * assistant message has a matching tool_result in the IMMEDIATELY NEXT user\n * message — not just anywhere in the history. This function strips any\n * tool_use/tool_result blocks that violate this positional constraint and\n * fixes role alternation. Single point of defense — no corrupt messages can\n * reach the API regardless of how they got into the session.\n */\nexport function validateHistory(messages: Message[]): Message[] {\n const result: Message[] = [];\n let i = 0;\n\n while (i < messages.length) {\n const msg = messages[i];\n\n // For assistant messages with tool_use, verify the next message has ALL results\n const toolUseIds = msg.content\n .filter((b): b is { type: 'tool_use'; id: string; name: string; input: unknown } => b.type === 'tool_use')\n .map((b) => b.id);\n\n if (toolUseIds.length > 0 && msg.role === 'assistant') {\n const next = messages[i + 1];\n const nextResultIds = new Set(\n (next?.content ?? [])\n .filter((b): b is { type: 'tool_result'; toolUseId: string; content: string } => b.type === 'tool_result')\n .map((b) => b.toolUseId),\n );\n\n // Strip tool_use blocks that have no result in the next message\n const cleanAssistant = msg.content.filter((b) => {\n if (b.type === 'tool_use') return nextResultIds.has(b.id);\n return true;\n });\n\n // Strip tool_result blocks from next message whose tool_use was removed\n const keptToolUseIds = new Set(\n cleanAssistant\n .filter((b): b is { type: 'tool_use'; id: string; name: string; input: unknown } => b.type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanNext = next?.content.filter((b) => {\n if (b.type === 'tool_result') return keptToolUseIds.has(b.toolUseId);\n return true;\n });\n\n if (cleanAssistant.length > 0) {\n result.push({ role: msg.role, content: cleanAssistant });\n }\n if (cleanNext && cleanNext.length > 0) {\n result.push({ role: next!.role, content: cleanNext });\n }\n i += 2;\n continue;\n }\n\n // For user messages: strip any tool_result blocks that reference a tool_use\n // not present in the immediately preceding assistant message\n if (msg.role === 'user' && msg.content.some((b) => b.type === 'tool_result')) {\n const prevAssistant = result[result.length - 1];\n const prevToolUseIds = new Set(\n (prevAssistant?.role === 'assistant' ? prevAssistant.content : [])\n .filter((b): b is { type: 'tool_use'; id: string; name: string; input: unknown } => b.type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanContent = msg.content.filter((b) => {\n if (b.type === 'tool_result') return prevToolUseIds.has(b.toolUseId);\n return true;\n });\n if (cleanContent.length > 0) {\n result.push({ role: msg.role, content: cleanContent });\n }\n i++;\n continue;\n }\n\n result.push(msg);\n i++;\n }\n\n // Merge consecutive same-role messages (can happen after stripping)\n const merged: Message[] = [];\n for (const msg of result) {\n const last = merged[merged.length - 1];\n if (last && last.role === msg.role) {\n last.content = [...last.content, ...msg.content];\n } else {\n merged.push({ role: msg.role, content: [...msg.content] });\n }\n }\n\n // First message must be user, AND it must not consist solely of\n // orphan `tool_result` blocks whose matching `tool_use` lived in an\n // assistant turn we're about to shift off. Anthropic rejects any\n // user message containing a tool_result that doesn't reference a\n // preceding assistant tool_use.\n //\n // The most common trigger is host code that seeds the conversation\n // with prefetched tool calls (see audric's `buildSyntheticPrefetch`):\n // `[assistant tool_uses, user tool_results, assistant text]`. After\n // shifting off the leading assistant, the user message's tool_results\n // are now orphaned. Strip them; if that empties the user message,\n // shift it off too — the next message may be assistant, in which\n // case we loop again.\n while (merged.length > 0) {\n if (merged[0].role !== 'user') {\n merged.shift();\n continue;\n }\n const cleaned = merged[0].content.filter((b) => b.type !== 'tool_result');\n if (cleaned.length === 0) {\n merged.shift();\n continue;\n }\n if (cleaned.length !== merged[0].content.length) {\n merged[0] = { role: 'user', content: cleaned };\n }\n break;\n }\n\n return merged;\n}\n\nfunction resolveTokenSymbol(nameOrType: string): string {\n if (!nameOrType.includes('::')) return nameOrType;\n const parts = nameOrType.split('::');\n return parts[parts.length - 1];\n}\n\nfunction describeAction(tool: Tool, call: PendingToolCall): string {\n const input = call.input as Record<string, unknown>;\n switch (tool.name) {\n case 'save_deposit': {\n return `Save ${input.amount} USDC into lending`;\n }\n case 'withdraw': {\n const wAsset = input.asset ?? '';\n return `Withdraw ${input.amount}${wAsset ? ' ' + wAsset : ''} from lending`;\n }\n case 'send_transfer':\n return `Send $${input.amount} to ${input.to}`;\n case 'borrow':\n return `Borrow $${input.amount} against collateral`;\n case 'repay_debt':\n return `Repay $${input.amount} of outstanding debt`;\n case 'claim_rewards':\n return 'Claim all pending protocol rewards';\n case 'pay_api': {\n const url = String(input.url ?? '');\n const cost = estimatePayApiCost(url);\n return `Pay for API call to ${url} (~$${cost})`;\n }\n case 'swap_execute': {\n const from = resolveTokenSymbol(String(input.from ?? '?'));\n const to = resolveTokenSymbol(String(input.to ?? '?'));\n const amt = input.amount ?? '?';\n const slippagePct = ((input.slippage as number) ?? 0.01) * 100;\n return `Swap ${amt} ${from} for ${to} (${slippagePct}% max slippage)`;\n }\n case 'volo_stake':\n return `Stake ${input.amount} SUI for vSUI`;\n case 'volo_unstake':\n return `Unstake ${input.amount === 'all' ? 'all' : input.amount} vSUI`;\n default:\n return `Execute ${tool.name}`;\n }\n}\n\nfunction flagSuspiciousResult(toolName: string, result: unknown): string | null {\n if (!result || typeof result !== 'object') return null;\n const r = result as Record<string, unknown>;\n if (toolName === 'swap_execute') {\n const outAmt = Number(r.toAmount ?? r.outputAmount ?? 0);\n const inAmt = Number(r.fromAmount ?? r.inputAmount ?? 1);\n if (inAmt > 0 && outAmt / inAmt > 1_000_000) {\n return '[Warning: This quote may contain inaccurate data. Verify on-chain before executing.]';\n }\n }\n const apy = Number(r.apy ?? r.APY ?? NaN);\n if (!isNaN(apy) && apy < 0) {\n return '[Warning: Negative APY detected — data may be stale.]';\n }\n return null;\n}\n","import type { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Messages — provider-agnostic conversation format\n// ---------------------------------------------------------------------------\n\nexport type ContentBlock =\n | { type: 'text'; text: string }\n | { type: 'thinking'; thinking: string; signature: string }\n | { type: 'redacted_thinking'; data: string }\n | { type: 'tool_use'; id: string; name: string; input: unknown }\n | {\n type: 'tool_result';\n toolUseId: string;\n content: string;\n isError?: boolean;\n };\n\nexport interface Message {\n role: 'user' | 'assistant';\n content: ContentBlock[];\n}\n\n// ---------------------------------------------------------------------------\n// Engine events — yielded by QueryEngine.submitMessage()\n// ---------------------------------------------------------------------------\n\nexport type EngineEvent =\n /**\n * [SPEC 8 v0.5.1] `blockIndex` identifies which thinking block this delta\n * belongs to. Anthropic streams multi-block thinking with rising indices\n * across each turn (block 0, 1, 2, ...). Hosts use this to render\n * chronologically interleaved thinking accordions instead of flattening\n * every delta into one string. Backwards-compatible: older hosts that\n * ignore the field still see deltas in emission order.\n */\n | { type: 'thinking_delta'; text: string; blockIndex: number }\n /**\n * [SPEC 8 v0.5.1] When the thinking block contained a parseable\n * `<eval_summary>...</eval_summary>` marker, `summaryMode` flips true\n * and `evaluationItems` carries the structured rows. Hosts render the\n * `HowIEvaluatedBlock` (\"✦ HOW I EVALUATED THIS\") trust card from\n * these fields. Both undefined when the block had no marker (every\n * read-only and most write turns).\n */\n | {\n type: 'thinking_done';\n blockIndex: number;\n signature?: string;\n summaryMode?: boolean;\n evaluationItems?: import('./eval-summary.js').EvaluationItem[];\n }\n | { type: 'text_delta'; text: string }\n | { type: 'tool_start'; toolName: string; toolUseId: string; input: unknown }\n | {\n type: 'tool_result';\n toolName: string;\n toolUseId: string;\n result: unknown;\n isError: boolean;\n /**\n * [v1.4 Item 4] True when the tool was executed by `EarlyToolDispatcher`\n * (read tools dispatched concurrently before the LLM yields). Hosts\n * record this in `TurnMetrics.toolsCalled[].wasEarlyDispatched`.\n */\n wasEarlyDispatched?: boolean;\n /**\n * [v1.4 Item 4] True when this result was synthesized from a previous\n * identical tool call by `microcompact` deduplication, instead of\n * actually re-running the tool.\n */\n resultDeduped?: boolean;\n /**\n * [v1.5] True when this result was produced by the engine's\n * post-write refresh mechanism (see `EngineConfig.postWriteRefresh`).\n * The engine auto-runs configured read tools immediately after a\n * successful write so the LLM narrates from fresh on-chain state\n * instead of inferring from a stale snapshot. Hosts should render\n * these like any other tool result; the flag is for analytics and\n * UI affordances (e.g. a subtle \"auto-refreshed\" badge).\n */\n wasPostWriteRefresh?: boolean;\n /**\n * [SPEC 8 v0.5.1 B3.2] Number of HTTP attempts the tool made before\n * succeeding (or returning the final result). Surfaced when the tool\n * went through one or more retries inside its retry wrapper\n * (`fetchBlockVisionWithRetry` and equivalents). Set ONLY when N > 1\n * — a successful first try leaves the field undefined to avoid\n * header noise in the host's `ToolBlockView`. Hosts render\n * \"TOOL · attempt N · 1.4s\" subtitle when present, hidden otherwise.\n *\n * Plumbing: engine sets a per-tool `retryStats: { attemptCount: 1 }`\n * counter on `ToolContext`; the BlockVision retry wrapper increments\n * it on every retry attempt; the engine reads it back after the tool\n * returns and surfaces here when > 1. Tools that don't use a retry\n * wrapper never emit a value.\n */\n attemptCount?: number;\n }\n | {\n type: 'pending_action';\n action: PendingAction;\n }\n | { type: 'turn_complete'; stopReason: StopReason }\n | {\n type: 'usage';\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n }\n | { type: 'error'; error: Error }\n | {\n /** Emitted when a tool result carries a canvas payload (__canvas: true). */\n type: 'canvas';\n template: string;\n data: unknown;\n title: string;\n toolUseId: string;\n }\n /**\n * [v1.4 Item 4] Emitted exactly once per agent turn when context-window\n * compaction fires. Hosts (e.g. audric `TurnMetricsCollector`) flip a\n * boolean for the `TurnMetrics.compactionTriggered` column. Carries no\n * payload — `compactMessages` stays a pure function.\n */\n | { type: 'compaction' }\n /**\n * [SPEC 8 v0.5.1] Side-channel event paired to every `update_todo` tool\n * call. Hosts render the persistent todo card from this event (NOT from\n * the tool_result — see `tools/update-todo.ts` § \"side-channel\" for\n * rationale). Carries the full items array so the host can\n * unconditionally replace its rendered list (the tool is idempotent —\n * each call replaces the previous state). `toolUseId` lets the host\n * key the render cell to the originating tool call.\n */\n | { type: 'todo_update'; items: TodoItem[]; toolUseId: string }\n /**\n * [SPEC 8 v0.5.1] Mid-execution progress signal from a long-running tool\n * (Cetus swap_execute 2-5s, protocol_deep_dive 3-8s, portfolio_analysis\n * 1-2s). Tools opt in by calling `context.progress?.(msg, pct?)` from\n * inside their `call` implementation. Hosts render the message + bar\n * inside the corresponding tool block's spinner — kills the dead-air\n * static-spinner UX that's the explicit SPEC 8 v0.3 fix target.\n *\n * Engine wiring (queue-and-yield in the dispatcher) lands with the\n * Cetus integration in a follow-on slice. SPEC 8 v0.5.1 reserves the\n * event type now so hosts can pre-wire the renderer.\n *\n * `pct` is 0–100 when the tool can express progress quantitatively,\n * undefined otherwise (free-text status only).\n */\n | { type: 'tool_progress'; toolUseId: string; toolName: string; message: string; pct?: number }\n /**\n * [SPEC 8 v0.5.1, D2] Inline-form structured input event reserved for\n * SPEC 9 v0.1.2 (`pending_input` form primitive). The engine does NOT\n * emit this event under SPEC 8 — the type is reserved so legacy hosts\n * can add a no-op handler now and avoid crashing when SPEC 9 ships\n * `pending_input` emission. See SPEC 8 § \"v0.5 cross-spec coupling\n * fixes\" — gap D2 — for the forward-compat rationale.\n */\n | {\n type: 'pending_input';\n /** Form schema (shape locked in SPEC 9 v0.1.2; engine treats it opaquely). */\n schema: unknown;\n /** Engine round-trip identifier — host posts the answer back keyed on this. */\n inputId: string;\n /** Optional human-readable prompt the LLM wants the host to display above the form. */\n prompt?: string;\n }\n /**\n * [SPEC 8 v0.5.1 B3.2] One-shot per-turn declaration of which adaptive\n * harness shape this turn is running under. Emitted at the start of\n * `submitMessage` BEFORE `agentLoop` begins (not on `resumeWithToolResult`\n * — resume is a continuation of the same turn, not a new shape decision).\n *\n * Derived from `classifyEffort()` on the host side: `low → 'lean'`,\n * `medium → 'standard'`, `high → 'rich'`, `max → 'max'`. Hosts use it\n * to (a) pre-allocate UI affordances (todo surface for `rich+`),\n * (b) stamp `TurnMetrics.harnessShape` for dashboard segmentation,\n * and (c) gate optional features (e.g. forbid `update_todo` rendering\n * on `lean` even if a misbehaving LLM emits one).\n *\n * If absent, hosts MUST default to `'legacy'` for telemetry purposes\n * (existing engines that don't emit this event are pre-SPEC-8). The\n * engine emits it ONLY when the host passes `harnessShape` into\n * `submitMessage` options; hosts that don't classify won't see this\n * event.\n */\n | {\n type: 'harness_shape';\n shape: HarnessShape;\n /**\n * 1-line human-readable explanation of why this shape was picked.\n * Examples: \"matched recipe portfolio_rebalance → max\",\n * \"session has prior writes + 'borrow' keyword → rich\",\n * \"single-fact lookup → lean\". Forwarded into telemetry verbatim.\n */\n rationale: string;\n };\n\n/**\n * [SPEC 8 v0.5.1 B3.2] Adaptive harness shape — driven by `classifyEffort()`,\n * pinned per-turn at turn start. Each shape implies a different\n * `thinking.budget_tokens` cap, soft block limit, and `update_todo`\n * permission. See SPEC 8 § \"Adaptive thresholds: harness shape gate\"\n * for the canonical mapping.\n */\nexport type HarnessShape = 'lean' | 'standard' | 'rich' | 'max';\n\n/**\n * [SPEC 8 v0.5.1 B3.2] Maps the engine's `ThinkingEffort` to the host-facing\n * harness shape. Single source of truth for the `low → lean`, `medium →\n * standard`, `high → rich`, `max → max` mapping. Exported so hosts (and\n * tests) get the mapping for free without re-implementing it.\n */\nexport function harnessShapeForEffort(effort: ThinkingEffort): HarnessShape {\n switch (effort) {\n case 'low':\n return 'lean';\n case 'medium':\n return 'standard';\n case 'high':\n return 'rich';\n case 'max':\n return 'max';\n }\n}\n\n/**\n * [SPEC 8 v0.5.1] One row in an `update_todo` payload. Mirrored from\n * `packages/engine/src/tools/update-todo.ts`. Kept here so hosts that\n * consume `EngineEvent` don't need to depend on the tool module.\n */\nexport interface TodoItem {\n id: string;\n label: string;\n status: 'pending' | 'in_progress' | 'completed';\n}\n\nexport type StopReason = 'end_turn' | 'tool_use' | 'max_tokens' | 'max_turns' | 'error';\n\n/**\n * [v1.4 Item 6] Describes a single input field on a `PendingAction` that\n * the host UI may let the user modify before approving. Carried on the\n * `pending_action` event so clients can render editable controls without\n * hard-coding per-tool field metadata. See\n * `packages/engine/src/tools/tool-modifiable-fields.ts` for the registry.\n */\nexport interface PendingActionModifiableField {\n /** Input key on the `PendingAction.input` object (e.g. \"amount\", \"to\"). */\n name: string;\n /**\n * UI hint for which control to render.\n * - `amount` — numeric input; UI shows a \"~Max\" hint when balance is known.\n * - `address` — Sui address input with paste/scan affordance.\n */\n kind: 'amount' | 'address';\n /** Optional asset symbol (e.g. \"USDC\", \"SUI\", \"vSUI\") for amount fields. */\n asset?: string;\n}\n\n/**\n * Serializable description of a write tool that needs user approval.\n * Stored in the session so the client can act on it in a separate request.\n */\nexport interface PendingAction {\n toolName: string;\n toolUseId: string;\n input: unknown;\n description: string;\n /** Full assistant message content from the LLM turn that triggered this action. */\n assistantContent: ContentBlock[];\n /** Results from auto-approved tools in the same LLM turn (e.g. balance_check). */\n completedResults?: Array<{ toolUseId: string; content: string; isError: boolean }>;\n /** Guard injections (hints/warnings) from pre-execution checks. */\n guardInjections?: Array<{ _gate: string; _hint?: string; _warning?: string }>;\n /**\n * [v1.4 Item 6] Fields the host UI may let the user modify before\n * approving. Sourced from `tool-modifiable-fields.ts`. Absent (or\n * empty) means the action is approve-or-deny only.\n */\n modifiableFields?: PendingActionModifiableField[];\n /**\n * [v1.4 Item 6] Monotonic turn index (assistant message count) at the\n * point this pending action was emitted. Hosts use it to update the\n * matching `TurnMetrics` row when the action resolves — see\n * `apps/web/app/api/engine/resume/route.ts` `updateMany` clause.\n */\n turnIndex: number;\n /**\n * [v1.4.2 — Day 3 / Spec Item 3] Per-yield random identifier (UUID v4)\n * stamped at the moment the engine emits this `pending_action`. Hosts\n * persist it on the `TurnMetrics` row at chat-time and key the resume\n * route's `updateMany` on it instead of `(sessionId, turnIndex)` — that\n * pair is ambiguous when the same turn yields a second pending action\n * (e.g. user edits → re-yield) or when a backfill leaves multiple rows\n * matching the pair, which is exactly the false-resolution bug Item 3\n * exists to kill. Also survives session persistence so the resume call\n * can read it back from the rehydrated `PendingAction`.\n */\n attemptId: string;\n}\n\n/**\n * Response from the client when resolving a pending action.\n * - `approved: false` → tool is declined, LLM is told \"user declined\"\n * - `approved: true` with `executionResult` → engine uses the client-provided result\n */\nexport interface PermissionResponse {\n approved: boolean;\n executionResult?: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Tool types\n// ---------------------------------------------------------------------------\n\nexport type PermissionLevel = 'auto' | 'confirm' | 'explicit';\n\nexport interface ToolResult<T = unknown> {\n data: T;\n displayText?: string;\n}\n\nexport interface ToolContext {\n agent?: unknown; // T2000 instance — typed loosely to avoid circular dep at type level\n mcpManager?: unknown; // McpClientManager — typed loosely to avoid circular dep\n walletAddress?: string; // User's Sui wallet address (required for MCP reads)\n suiRpcUrl?: string; // Sui JSON-RPC URL for direct chain queries\n serverPositions?: ServerPositionData; // Pre-fetched positions from the server (avoids stale MCP data)\n /** Fresh on-chain position reader — bypasses MCP caching. If provided, read tools prefer this. */\n positionFetcher?: (address: string) => Promise<ServerPositionData>;\n /** Environment variables passed to tools (e.g. API keys not in process.env) */\n env?: Record<string, string>;\n signal?: AbortSignal;\n /** Token symbol → USD price map for USD-aware permission resolution (B.4). */\n priceCache?: Map<string, number>;\n /** Per-user permission config for USD-threshold write tool gating (B.4). */\n permissionConfig?: import('./permission-rules.js').UserPermissionConfig;\n /**\n * [v1.4] Cumulative USD already auto-executed in the current session.\n * Used by `resolvePermissionTier` to enforce `autonomousDailyLimit` —\n * downgrades `auto` to `confirm` when adding the incoming tool's USD\n * value would exceed the limit. Optional; omitted = unbounded.\n */\n sessionSpendUsd?: number;\n /**\n * [v1.4 BlockVision] Server-only BlockVision Indexer API key. Threaded\n * through from the host (`audric/apps/web` reads\n * `process.env.BLOCKVISION_API_KEY`). Forwarded to\n * `fetchAddressPortfolio` / `fetchTokenPrices` in `blockvision-prices.ts`.\n * When undefined / empty the price feed degrades to Sui RPC + the\n * hardcoded stable allow-list — wallets still render but non-stable\n * USD values are reported as `null`.\n */\n blockvisionApiKey?: string;\n /**\n * [v1.4 BlockVision] Per-request memoization of the BlockVision portfolio\n * response. Keyed by Sui address. Multiple read tools (`balance_check`,\n * `portfolio_analysis`) inside the same chat turn re-hit the same address;\n * sharing this Map across them avoids a second 200–500ms BlockVision RTT.\n * The `blockvision-prices` module also has its own TTL cache, so this is\n * primarily a fast-path optimisation rather than a correctness primitive.\n */\n portfolioCache?: Map<string, import('./blockvision-prices.js').AddressPortfolio>;\n /**\n * [SPEC 8 v0.5.1 B3.2] Per-tool-invocation HTTP attempt counter. The\n * engine's tool dispatcher attaches a fresh `{ attemptCount: 1 }` to\n * the context before calling each tool; retry wrappers\n * (`fetchBlockVisionWithRetry` and equivalents) bump\n * `retryStats.attemptCount` on every retry beyond the first attempt;\n * the dispatcher reads the final value back and surfaces it on the\n * `tool_result` event (only when > 1). Tools that don't use a retry\n * wrapper never observe a non-default value.\n *\n * The mutable-ref shape is deliberate — it lets retry wrappers deep\n * in the call stack record state without changing every caller's\n * return type.\n */\n retryStats?: { attemptCount: number };\n}\n\nexport interface ServerPositionData {\n savings: number;\n borrows: number;\n savingsRate: number;\n healthFactor: number | null;\n maxBorrow: number;\n pendingRewards: number;\n supplies: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n borrows_detail: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n}\n\nexport interface ToolJsonSchema {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n}\n\nexport interface ToolFlags {\n mutating?: boolean;\n requiresBalance?: boolean;\n affectsHealth?: boolean;\n irreversible?: boolean;\n producesArtifact?: boolean;\n costAware?: boolean;\n maxRetries?: number;\n}\n\nexport type PreflightResult =\n | { valid: true }\n | { valid: false; error: string };\n\nexport interface Tool<TInput = unknown, TOutput = unknown> {\n name: string;\n description: string;\n inputSchema: z.ZodType<TInput>;\n jsonSchema: ToolJsonSchema;\n call(input: TInput, context: ToolContext): Promise<ToolResult<TOutput>>;\n isConcurrencySafe: boolean;\n isReadOnly: boolean;\n permissionLevel: PermissionLevel;\n flags: ToolFlags;\n preflight?: (input: unknown) => PreflightResult;\n /** Max chars for the serialized tool result. Truncated with a re-call hint when exceeded. */\n maxResultSizeChars?: number;\n /** Custom truncation strategy. Falls back to generic slice + hint when omitted. */\n summarizeOnTruncate?: (result: string, maxChars: number) => string;\n /**\n * [v1.5.1] Whether `microcompact` may dedupe this tool's results across\n * multiple calls with identical input. Default `true` — most tools are\n * effectively pure within a session (price lookups, protocol info,\n * yield pools). Set to `false` for tools whose result depends on\n * mutable on-chain state and therefore changes after writes\n * (`balance_check`, `savings_info`, `health_check`,\n * `transaction_history`). Non-cacheable tools are excluded from the\n * `seen` map entirely, so neither this call nor any later call with\n * the same input gets replaced with a \"[Same result …]\" back-reference.\n */\n cacheable?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Thinking configuration (Anthropic extended thinking / adaptive)\n// ---------------------------------------------------------------------------\n\nexport type ThinkingEffort = 'low' | 'medium' | 'high' | 'max';\n\nexport type ThinkingConfig =\n | { type: 'disabled' }\n | { type: 'adaptive'; display?: 'summarized' | 'omitted' }\n | { type: 'enabled'; budgetTokens: number; display?: 'summarized' | 'omitted' };\n\nexport interface OutputConfig {\n effort?: ThinkingEffort;\n}\n\nexport interface SystemBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n}\n\nexport type SystemPrompt = string | SystemBlock[];\n\n// ---------------------------------------------------------------------------\n// Engine configuration\n// ---------------------------------------------------------------------------\n\nexport interface EngineConfig {\n provider: LLMProvider;\n agent?: unknown; // T2000 instance\n mcpManager?: unknown; // McpClientManager for MCP-based reads\n walletAddress?: string; // User's Sui wallet address (required for MCP reads)\n suiRpcUrl?: string; // Sui JSON-RPC URL for direct chain queries (wallet coins, etc.)\n serverPositions?: ServerPositionData; // Pre-fetched positions from the host app\n /** Fresh on-chain position reader — called per tool invocation, bypasses MCP caching. */\n positionFetcher?: (address: string) => Promise<ServerPositionData>;\n tools?: Tool[];\n systemPrompt?: SystemPrompt;\n model?: string;\n maxTurns?: number;\n maxTokens?: number;\n temperature?: number;\n /** Force tool usage on the first LLM turn (prevents text-only refusals). */\n toolChoice?: ToolChoice;\n thinking?: ThinkingConfig;\n outputConfig?: OutputConfig;\n /** Environment variables forwarded to tool context (API keys, URLs). */\n env?: Record<string, string>;\n costTracker?: {\n budgetLimitUsd?: number;\n inputCostPerToken?: number;\n outputCostPerToken?: number;\n };\n /** Guard runner configuration (RE-2.2). Omit to disable guards. */\n guards?: import('./guards.js').GuardConfig;\n /** Recipe registry for multi-step workflow guidance (RE-3.1). */\n recipes?: import('./recipes/index.js').RecipeRegistry;\n /** Context budget tracking configuration (RE-3.3). */\n contextBudget?: import('./context.js').ContextBudgetConfig;\n /** LLM-based summarizer for context compaction (RE-3.3). */\n contextSummarizer?: (messages: import('./types.js').Message[]) => Promise<string>;\n /** Token symbol → USD price map for USD-aware permission resolution (B.4). */\n priceCache?: Map<string, number>;\n /** Per-user permission config for USD-threshold write tool gating (B.4). */\n permissionConfig?: import('./permission-rules.js').UserPermissionConfig;\n /**\n * Saved contacts for the current user. Used by `guardAddressSource`\n * (a saved contact's address is considered a trusted source for\n * `send_transfer.to`) and by `permission-rules.resolvePermissionTier`\n * (sends to non-contact addresses always require confirmation,\n * regardless of amount). Hosts SHOULD also surface these in the\n * dynamic system prompt block so the LLM can resolve \"send to <name>\".\n */\n contacts?: ReadonlyArray<{ name: string; address: string }>;\n /**\n * [v1.4] Cumulative USD already auto-executed in the current session.\n * Forwarded to `ToolContext` and consulted by `resolvePermissionTier` to\n * enforce `autonomousDailyLimit`.\n */\n sessionSpendUsd?: number;\n /**\n * [v1.4 BlockVision] Server-only BlockVision Indexer API key. Forwarded\n * verbatim into `ToolContext.blockvisionApiKey` for read tools that hit\n * `api.blockvision.org` (`balance_check`, `portfolio_analysis`,\n * `token_prices`). When omitted, those tools degrade gracefully to a\n * Sui-RPC + hardcoded-stable fallback — see `blockvision-prices.ts`.\n */\n blockvisionApiKey?: string;\n /**\n * [v1.4 BlockVision] Per-request portfolio cache shared across read\n * tools in the same chat turn. Forwarded into `ToolContext.portfolioCache`.\n */\n portfolioCache?: Map<string, import('./blockvision-prices.js').AddressPortfolio>;\n /**\n * [v1.4] Fired after a write tool successfully auto-executes (no\n * confirmation required). Hosts use this to persist cumulative spend in\n * Redis and (post-v1.4 BlockVision swap) invalidate cross-session caches\n * keyed by the user's wallet address. Errors are caught — the tool\n * result is never blocked by a failure here.\n *\n * The `walletAddress` field is populated from the engine's\n * `config.walletAddress`; it's absent only on unauthenticated engines\n * (which never auto-execute a real write).\n */\n onAutoExecuted?: (info: {\n toolName: string;\n usdValue: number;\n walletAddress?: string;\n }) => void | Promise<void>;\n /**\n * [v1.4 Item 4] Per-guard observation hook. Forwarded to `runGuards`\n * and fired once per non-`pass` verdict so hosts can record guard\n * behaviour in `TurnMetrics.guardsFired` without re-implementing the\n * verdict→action mapping. Errors thrown by the host are caught.\n */\n onGuardFired?: (guard: import('./guards.js').GuardMetric) => void;\n /**\n * [v1.5] Map of write tool name → list of read tool names whose state\n * the write invalidates. After a successful write resumes via\n * `resumeWithToolResult`, the engine auto-runs each configured read\n * tool with empty input, pushes synthetic `tool_use` + `tool_result`\n * messages into the conversation, and yields `tool_result` events\n * with `wasPostWriteRefresh: true` BEFORE handing control back to the\n * LLM for narration.\n *\n * Why: writes change on-chain state. Without a fresh read, the LLM\n * narrates from the pre-write snapshot and frequently invents balance\n * totals. Auto-injecting fresh reads makes the hallucination class\n * physically impossible — the model has authoritative ground truth in\n * its context before generating the post-write sentence.\n *\n * Constraints:\n * - Refresh tools MUST be `isReadOnly` and `isConcurrencySafe`.\n * - Refresh runs only when the write succeeded (executionResult is\n * not `{ success: false }`); failed writes leave state unchanged\n * and refreshing would be misleading.\n * - Tools are invoked with empty input; refresh tools should accept\n * an empty object schema (e.g. `balance_check`, `savings_info`).\n * - Errors during refresh are non-fatal — a tool_result with\n * `isError: true` is still pushed so the LLM knows refresh failed.\n *\n * Example:\n * ```\n * {\n * save_deposit: ['balance_check', 'savings_info'],\n * send_transfer: ['balance_check'],\n * borrow: ['balance_check', 'savings_info', 'health_check'],\n * }\n * ```\n *\n * Omit (undefined / empty map) to disable post-write refresh entirely.\n */\n postWriteRefresh?: Record<string, string[]>;\n}\n\n// ---------------------------------------------------------------------------\n// LLM Provider interface (re-exported from providers/types for convenience)\n// ---------------------------------------------------------------------------\n\nexport interface LLMProvider {\n chat(params: ChatParams): AsyncGenerator<ProviderEvent>;\n}\n\nexport type ToolChoice = 'auto' | 'any' | { type: 'tool'; name: string };\n\nexport interface ChatParams {\n messages: Message[];\n systemPrompt: SystemPrompt;\n tools: ToolDefinition[];\n model?: string;\n maxTokens?: number;\n temperature?: number;\n toolChoice?: ToolChoice;\n thinking?: ThinkingConfig;\n outputConfig?: OutputConfig;\n signal?: AbortSignal;\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n input_schema: ToolJsonSchema;\n}\n\nexport type ProviderEvent =\n | { type: 'thinking_delta'; text: string; blockIndex: number }\n | {\n type: 'thinking_done';\n blockIndex: number;\n thinking: string;\n signature: string;\n // [SPEC 8 v0.5.1] populated by the provider when a parseable\n // <eval_summary> marker was found in the thinking text.\n summaryMode?: boolean;\n evaluationItems?: import('./eval-summary.js').EvaluationItem[];\n }\n | { type: 'redacted_thinking'; data: string }\n | { type: 'text_delta'; text: string }\n | { type: 'tool_use_start'; id: string; name: string }\n | { type: 'tool_use_delta'; id: string; partialJson: string }\n | { type: 'tool_use_done'; id: string; name: string; input: unknown }\n | {\n type: 'message_start';\n messageId: string;\n model: string;\n }\n | {\n type: 'usage';\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n }\n | { type: 'stop'; reason: StopReason };\n","import type { EngineEvent, HarnessShape, PendingAction, StopReason, TodoItem } from './types.js';\nimport type { EvaluationItem } from './eval-summary.js';\n\n// ---------------------------------------------------------------------------\n// SSE event format — serialisable subset of EngineEvent\n// ---------------------------------------------------------------------------\n\nexport type SSEEvent =\n // [SPEC 8 v0.5.1] blockIndex identifies the thinking block this delta belongs to.\n | { type: 'thinking_delta'; text: string; blockIndex: number }\n | {\n type: 'thinking_done';\n blockIndex: number;\n signature?: string;\n // [SPEC 8 v0.5.1] HowIEvaluated block fields — populated when the\n // thinking text contained a parseable <eval_summary> marker.\n summaryMode?: boolean;\n evaluationItems?: EvaluationItem[];\n }\n | { type: 'text_delta'; text: string }\n | { type: 'tool_start'; toolName: string; toolUseId: string; input: unknown }\n | {\n type: 'tool_result';\n toolName: string;\n toolUseId: string;\n result: unknown;\n isError: boolean;\n // [v1.4] flags carried through unchanged from EngineEvent.tool_result\n wasEarlyDispatched?: boolean;\n resultDeduped?: boolean;\n // [v1.5] true when injected by the engine's post-write refresh\n // (see EngineConfig.postWriteRefresh)\n wasPostWriteRefresh?: boolean;\n // [SPEC 8 v0.5.1 B3.2] HTTP attempt count — set only when > 1 so\n // hosts can render \"TOOL · attempt N · 1.4s\" without header noise\n // on the common single-attempt path.\n attemptCount?: number;\n }\n | { type: 'pending_action'; action: PendingAction }\n | { type: 'turn_complete'; stopReason: StopReason }\n | { type: 'usage'; inputTokens: number; outputTokens: number; cacheReadTokens?: number; cacheWriteTokens?: number }\n | { type: 'error'; message: string }\n | { type: 'canvas'; template: string; data: unknown; title: string; toolUseId: string }\n // [SPEC 8 v0.5.1] todo_update side-channel event paired to every\n // update_todo tool call. Mirrors EngineEvent.todo_update.\n | { type: 'todo_update'; items: TodoItem[]; toolUseId: string }\n // [SPEC 8 v0.5.1] tool_progress mid-execution signal from long-running\n // tools (Cetus swap_execute, protocol_deep_dive, portfolio_analysis).\n // Engine wiring lands with the Cetus integration in a follow-on slice.\n | { type: 'tool_progress'; toolUseId: string; toolName: string; message: string; pct?: number }\n // [SPEC 8 v0.5.1, D2] pending_input reserved for SPEC 9 v0.1.2 inline\n // forms. Engine doesn't emit under SPEC 8; reservation is forward-compat.\n | { type: 'pending_input'; schema: unknown; inputId: string; prompt?: string }\n // [SPEC 8 v0.5.1 B3.2] One-shot per-turn harness shape declaration.\n // Mirrors EngineEvent.harness_shape — see types.ts for full contract.\n | { type: 'harness_shape'; shape: HarnessShape; rationale: string };\n\n// ---------------------------------------------------------------------------\n// Serialise: SSEEvent → SSE text\n// ---------------------------------------------------------------------------\n\nexport function serializeSSE(event: SSEEvent): string {\n const data = JSON.stringify(event);\n return `event: ${event.type}\\ndata: ${data}\\n\\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Deserialise: SSE text → SSEEvent\n// ---------------------------------------------------------------------------\n\nexport function parseSSE(raw: string): SSEEvent | null {\n const dataLine = raw.split('\\n').find((l) => l.startsWith('data: '));\n if (!dataLine) return null;\n try {\n return JSON.parse(dataLine.slice(6)) as SSEEvent;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stream adapter: engine async generator → SSE text stream\n// ---------------------------------------------------------------------------\n\nexport async function* engineToSSE(\n events: AsyncGenerator<EngineEvent>,\n): AsyncGenerator<string> {\n for await (const event of events) {\n if (event.type === 'error') {\n yield serializeSSE({ type: 'error', message: event.error.message });\n } else {\n yield serializeSSE(event as SSEEvent);\n }\n }\n}\n","import type { Message, PendingAction } from './types.js';\nimport type { CostSnapshot } from './cost.js';\n\n// ---------------------------------------------------------------------------\n// Session data\n// ---------------------------------------------------------------------------\n\nexport interface SessionData {\n id: string;\n messages: Message[];\n usage: CostSnapshot;\n createdAt: number;\n updatedAt: number;\n /** Set when the engine is paused waiting for user approval of a write action. */\n pendingAction?: PendingAction | null;\n metadata?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Session store interface — implement for different backends\n// ---------------------------------------------------------------------------\n\nexport interface SessionStore {\n /** Load a session by ID. Returns null if not found or expired. */\n get(sessionId: string): Promise<SessionData | null>;\n\n /** Save or update a session. */\n set(session: SessionData): Promise<void>;\n\n /** Delete a session. */\n delete(sessionId: string): Promise<void>;\n\n /** Check if a session exists. */\n exists(sessionId: string): Promise<boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// MemorySessionStore — for development and testing\n// ---------------------------------------------------------------------------\n\nexport class MemorySessionStore implements SessionStore {\n private store = new Map<string, { data: SessionData; expiresAt: number }>();\n private readonly ttlMs: number;\n\n constructor(opts?: { ttlMs?: number }) {\n this.ttlMs = opts?.ttlMs ?? 24 * 60 * 60 * 1000; // 24h default\n }\n\n async get(sessionId: string): Promise<SessionData | null> {\n const entry = this.store.get(sessionId);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return null;\n }\n return structuredClone(entry.data);\n }\n\n async set(session: SessionData): Promise<void> {\n this.store.set(session.id, {\n data: structuredClone(session),\n expiresAt: Date.now() + this.ttlMs,\n });\n }\n\n async delete(sessionId: string): Promise<void> {\n this.store.delete(sessionId);\n }\n\n async exists(sessionId: string): Promise<boolean> {\n const entry = this.store.get(sessionId);\n if (!entry) return false;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return false;\n }\n return true;\n }\n\n /** For testing: number of active (non-expired) sessions. */\n get size(): number {\n this.evictExpired();\n return this.store.size;\n }\n\n private evictExpired(): void {\n const now = Date.now();\n for (const [id, entry] of this.store) {\n if (now > entry.expiresAt) this.store.delete(id);\n }\n }\n}\n","import { readFileSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport yaml from 'js-yaml';\nimport { z } from 'zod';\nimport type { Recipe, RecipeStep } from './types.js';\n\nconst StepRequirementSchema = z.object({\n step: z.string().optional(),\n field: z.string().optional(),\n confirmation: z.boolean().optional(),\n});\n\nconst OnErrorSchema = z.object({\n action: z.enum(['abort', 'refuse', 'report', 'retry']),\n message: z.string(),\n suggest: z.string().optional(),\n});\n\nconst StepSchema: z.ZodType<RecipeStep> = z.object({\n name: z.string().min(1),\n tool: z.string().optional(),\n service: z.string().optional(),\n purpose: z.string().min(1),\n cost: z.string().optional(),\n output: z.object({ type: z.string(), key: z.string() }).optional(),\n gate: z.enum(['none', 'preview', 'review', 'estimate']).optional(),\n gate_prompt: z.string().optional(),\n requires: z.array(StepRequirementSchema).optional(),\n rules: z.array(z.string()).optional(),\n condition: z.string().optional(),\n notes: z.string().optional(),\n flags: z.record(z.unknown()).optional() as z.ZodType<RecipeStep['flags']>,\n on_error: OnErrorSchema.optional(),\n input_template: z.record(z.string()).optional(),\n cost_per_unit: z.string().optional(),\n});\n\nconst RecipeSchema = z.object({\n name: z.string().min(1),\n description: z.string().min(1),\n triggers: z.array(z.string().min(1)).min(1),\n services: z.array(z.string()).optional(),\n prerequisites: z.array(z.object({ field: z.string(), prompt: z.string() })).optional(),\n steps: z.array(StepSchema).min(1),\n}).refine(\n (r) => {\n const names = r.steps.map((s) => s.name);\n return new Set(names).size === names.length;\n },\n { message: 'Step names must be unique within a recipe' },\n);\n\n/**\n * Load all recipe YAML files from a directory.\n * Throws on validation errors — recipes should fail at load time, not runtime.\n */\nexport function loadRecipes(yamlDir: string): Recipe[] {\n const files = readdirSync(yamlDir).filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'));\n const recipes: Recipe[] = [];\n\n for (const file of files) {\n const content = readFileSync(join(yamlDir, file), 'utf-8');\n const raw = yaml.load(content);\n const parsed = RecipeSchema.parse(raw);\n recipes.push(parsed as Recipe);\n }\n\n return recipes;\n}\n\n/**\n * Parse a single recipe from a YAML string (useful for embedded/bundled recipes).\n */\nexport function parseRecipe(yamlContent: string): Recipe {\n const raw = yaml.load(yamlContent);\n return RecipeSchema.parse(raw) as Recipe;\n}\n","import type { Recipe } from './types.js';\nimport { loadRecipes, parseRecipe } from './loader.js';\n\n/**\n * Stores loaded recipes and matches user messages to the most specific recipe\n * using longest-trigger-match-wins.\n */\nexport class RecipeRegistry {\n private recipes: Recipe[] = [];\n\n /** Load all recipes from a directory of YAML files. */\n loadDir(yamlDir: string): void {\n this.recipes.push(...loadRecipes(yamlDir));\n }\n\n /** Register a single recipe from a YAML string. */\n loadYaml(yamlContent: string): void {\n this.recipes.push(parseRecipe(yamlContent));\n }\n\n /** Register a pre-parsed Recipe object. */\n register(recipe: Recipe): void {\n this.recipes.push(recipe);\n }\n\n /** All loaded recipes. */\n all(): readonly Recipe[] {\n return this.recipes;\n }\n\n /**\n * Match a user message to the most specific recipe.\n * Longest trigger phrase match wins. Returns null if no match.\n */\n match(userMessage: string): Recipe | null {\n const normalized = userMessage.toLowerCase().trim();\n let best: Recipe | null = null;\n let bestLength = 0;\n\n for (const recipe of this.recipes) {\n for (const trigger of recipe.triggers) {\n const triggerLower = trigger.toLowerCase();\n if (normalized.includes(triggerLower) && triggerLower.length > bestLength) {\n best = recipe;\n bestLength = triggerLower.length;\n }\n }\n }\n\n return best;\n }\n\n /**\n * Format a matched recipe as a compact context block for the system prompt.\n * Injected dynamically — only when the recipe matches.\n */\n toPromptContext(recipe: Recipe): string {\n const lines: string[] = [\n `## Active Recipe: ${recipe.name}`,\n recipe.description,\n 'Follow these steps:',\n ];\n\n for (let i = 0; i < recipe.steps.length; i++) {\n const step = recipe.steps[i];\n const num = i + 1;\n const toolNote = step.tool ? ` → ${step.tool}` : '';\n const serviceNote = step.service ? ` (${step.service})` : '';\n const costNote = step.cost ? ` — ${step.cost}` : '';\n const gateNote = step.gate && step.gate !== 'none'\n ? ` [GATE: ${step.gate}]`\n : '';\n\n let line = `${num}. ${step.name}${toolNote}${serviceNote}${costNote}${gateNote}`;\n\n if (step.gate_prompt) {\n line += ` — \"${step.gate_prompt}\"`;\n }\n\n lines.push(line);\n\n if (step.rules?.length) {\n for (const rule of step.rules) {\n lines.push(` - ${rule}`);\n }\n }\n\n if (step.notes) {\n lines.push(` Note: ${step.notes}`);\n }\n\n if (step.on_error) {\n lines.push(` On error: ${step.on_error.action} — ${step.on_error.message}`);\n }\n\n if (step.condition) {\n lines.push(` Condition: ${step.condition}`);\n }\n }\n\n if (recipe.prerequisites?.length) {\n lines.push('Prerequisites (ask before starting):');\n for (const pre of recipe.prerequisites) {\n lines.push(`- ${pre.field}: \"${pre.prompt}\"`);\n }\n }\n\n return lines.join('\\n');\n }\n}\n","import type { ThinkingEffort } from './types.js';\nimport type { Recipe } from './recipes/index.js';\n\n/**\n * Routes each turn to the appropriate thinking effort level based on\n * message content, matched recipe, and session write history.\n *\n * Heuristics only — no LLM call. Cost per session becomes proportional\n * to actual query complexity rather than a fixed budget.\n */\nexport function classifyEffort(\n model: string,\n userMessage: string,\n matchedRecipe: Recipe | null,\n sessionWriteCount: number,\n): ThinkingEffort {\n const supportsMax = model.includes('opus-4-6');\n const msg = userMessage.toLowerCase();\n\n if (supportsMax) {\n if (matchedRecipe?.name === 'portfolio_rebalance') return 'max';\n if (matchedRecipe?.name === 'emergency_withdraw') return 'max';\n if (/rebalance|reallocate|dca setup|close.*position/i.test(msg)) return 'max';\n }\n\n if (matchedRecipe && matchedRecipe.steps.length >= 3) return 'high';\n if (matchedRecipe?.name === 'safe_borrow' || matchedRecipe?.name === 'bulk_mail') return 'high';\n if (sessionWriteCount > 0 && /borrow|withdraw|send|swap/i.test(msg)) return 'high';\n\n // Any matched recipe means multi-step tool work — never route to Haiku\n // regardless of message wording. Haiku struggles with the synthesis these\n // recipes require and ends up looping through more tool rounds than Sonnet,\n // costing more in practice. (Confirmed by 0.46.x TurnMetrics baseline:\n // low-effort Haiku turns averaged $0.040 vs $0.017 for medium-effort Sonnet.)\n if (matchedRecipe) return 'medium';\n\n // Pure simple lookups — single-fact questions Haiku handles well.\n // Explicitly excludes `show|history|all|list|everything` which imply\n // multi-record synthesis (the original regex sent these to Haiku and\n // they bottomed out the cost/latency curves).\n if (/\\b(balance|rate|how much|what is|check|price|apy|hf)\\b/i.test(msg)) return 'low';\n if (!/\\b(deposit|send|swap|borrow|withdraw|save|pay|transfer|show|history|all|list|everything|report|summary|breakdown)\\b/i.test(msg)) return 'low';\n\n return 'medium';\n}\n","// ---------------------------------------------------------------------------\n// <eval_summary> marker parser (SPEC 8 v0.5.1, P3.2 slice 7)\n//\n// The system prompt teaches the LLM to emit a single `<eval_summary>...\n// </eval_summary>` block inside its final thinking burst on\n// write-recommendation turns. The block carries structured rows the host\n// renders as the \"✦ HOW I EVALUATED THIS\" trust card (the highest-impact\n// UX in `audric/audric_demos_v2/demos/01-save-50.html`).\n//\n// Format taught to the LLM:\n//\n// <eval_summary>\n// {\n// \"items\": [\n// { \"label\": \"Health Factor\", \"status\": \"good\", \"note\": \"1.85 → 1.62, above 1.20 threshold\" },\n// { \"label\": \"Slippage cap\", \"status\": \"good\", \"note\": \"0.5% on 100 USDC → max $0.50 loss\" },\n// { \"label\": \"Daily spend\", \"status\": \"warning\", \"note\": \"$8 of $50 daily cap used\" }\n// ]\n// }\n// </eval_summary>\n//\n// Parser behavior:\n// - Returns null when no marker is present (no extra cost on every turn).\n// - Extracts the FIRST marker only — multiple in one block is a violation\n// logged at the engine telemetry level via `evalSummaryViolationsCount`.\n// - Returns null when the inner JSON is malformed — the LLM saw a render\n// mistake; the host falls back to standard ThinkingBlock rendering.\n// - Tolerates whitespace and newlines around the JSON payload.\n//\n// The engine wires this in `providers/anthropic.ts` at the\n// `content_block_stop` handler for thinking blocks, populating the new\n// `summaryMode` + `evaluationItems` fields on `thinking_done` events.\n// ---------------------------------------------------------------------------\n\nexport type EvaluationStatus = 'good' | 'warning' | 'critical' | 'info';\n\nexport interface EvaluationItem {\n label: string;\n status: EvaluationStatus;\n note?: string;\n}\n\nexport interface EvalSummaryParseResult {\n /** Always true when this object is returned (vs null when absent). */\n summaryMode: true;\n /** The structured rows the host renders inside the trust card. */\n evaluationItems: EvaluationItem[];\n /** Count of markers detected — >1 indicates an LLM compliance violation. */\n markerCount: number;\n}\n\nconst MARKER_REGEX = /<eval_summary>([\\s\\S]*?)<\\/eval_summary>/g;\nconst VALID_STATUSES: ReadonlySet<EvaluationStatus> = new Set([\n 'good',\n 'warning',\n 'critical',\n 'info',\n]);\n\n/**\n * Scan a thinking-block text for one or more `<eval_summary>` markers.\n *\n * - Returns null when no marker is present, or when the first marker's\n * JSON is malformed (host falls back to standard rendering).\n * - Returns a parsed result when at least one marker contains valid JSON.\n * `markerCount` reflects the total number of markers seen so the\n * engine can emit a `evalSummaryViolationsCount` telemetry counter\n * when N > 1 (LLM is supposed to emit at most one per turn).\n *\n * The function is pure — safe to call per-thinking-block.\n */\nexport function parseEvalSummary(thinkingText: string): EvalSummaryParseResult | null {\n if (!thinkingText.includes('<eval_summary>')) return null;\n\n const matches: string[] = [];\n for (const match of thinkingText.matchAll(MARKER_REGEX)) {\n matches.push(match[1] ?? '');\n }\n\n if (matches.length === 0) return null;\n\n const firstPayload = matches[0].trim();\n let parsed: unknown;\n try {\n parsed = JSON.parse(firstPayload);\n } catch {\n return null;\n }\n\n if (!parsed || typeof parsed !== 'object') return null;\n const items = (parsed as { items?: unknown }).items;\n if (!Array.isArray(items)) return null;\n\n const evaluationItems: EvaluationItem[] = [];\n for (const item of items) {\n if (!item || typeof item !== 'object') continue;\n const i = item as Record<string, unknown>;\n if (typeof i.label !== 'string' || i.label.trim().length === 0) continue;\n if (typeof i.status !== 'string' || !VALID_STATUSES.has(i.status as EvaluationStatus)) continue;\n const out: EvaluationItem = {\n label: i.label,\n status: i.status as EvaluationStatus,\n };\n if (typeof i.note === 'string' && i.note.length > 0) {\n out.note = i.note;\n }\n evaluationItems.push(out);\n }\n\n if (evaluationItems.length === 0) return null;\n\n return {\n summaryMode: true,\n evaluationItems,\n markerCount: matches.length,\n };\n}\n","import type { SystemBlock } from './types.js';\n\n/**\n * Build a cacheable system prompt array from static and dynamic parts.\n *\n * Anthropic caches system prompt blocks marked with `cache_control: { type: 'ephemeral' }`.\n * Static blocks (identity, tool descriptions) are cached across turns. Dynamic blocks\n * (user profile, positions, state) change per-turn and are NOT cached.\n *\n * Cache breakpoints are placed at the end of each static block — Anthropic caches\n * from the start of the prompt up to the last cache_control marker.\n */\nexport function buildCachedSystemPrompt(\n staticParts: string[],\n dynamicPart?: string,\n): SystemBlock[] {\n const blocks: SystemBlock[] = staticParts.map((text, i) => ({\n type: 'text' as const,\n text,\n ...(i === staticParts.length - 1 && { cache_control: { type: 'ephemeral' as const } }),\n }));\n\n if (dynamicPart) {\n blocks.push({ type: 'text', text: dynamicPart });\n }\n\n return blocks;\n}\n","/**\n * Intelligence Layer prompt builders (F1, F2, F5).\n * Pure functions — no DB or Redis dependencies.\n * Consumed by the host app's dynamic context assembly.\n */\n\n// ---------------------------------------------------------------------------\n// F1: User Financial Profile types + context builder\n// ---------------------------------------------------------------------------\n\nexport interface UserFinancialProfile {\n userId: string;\n riskAppetite: 'conservative' | 'moderate' | 'aggressive';\n financialLiteracy: 'novice' | 'intermediate' | 'advanced';\n prefersBriefResponses: boolean;\n prefersExplainers: boolean;\n currencyFraming: 'usdc' | 'fiat';\n primaryGoals: string[];\n knownPatterns: string[];\n riskConfidence: number;\n literacyConfidence: number;\n lastInferredAt: Date | null;\n}\n\n/**\n * Build system prompt context from a user's financial profile.\n * Returns empty string if profile is absent or confidence is too low.\n * Takes the profile object directly — no DB query.\n */\nexport function buildProfileContext(profile: UserFinancialProfile | null): string {\n if (!profile || profile.riskConfidence < 0.3) return '';\n\n const lines: string[] = ['User financial profile (inferred from conversation history):'];\n\n if (profile.riskConfidence >= 0.5) {\n lines.push(`- Risk appetite: ${profile.riskAppetite}`);\n }\n if (profile.literacyConfidence >= 0.5) {\n lines.push(`- Financial literacy: ${profile.financialLiteracy}`);\n if (profile.financialLiteracy === 'advanced') {\n lines.push(' → Skip basic DeFi explanations (health factor, APY, etc). User knows these.');\n }\n if (profile.financialLiteracy === 'novice') {\n lines.push(' → Always explain DeFi concepts in plain language.');\n }\n }\n if (profile.currencyFraming === 'fiat') {\n lines.push('- Frame amounts as dollars (e.g. \"$50\" not \"50 USDC\")');\n }\n if (profile.prefersBriefResponses) {\n lines.push('- Prefers brief responses — be concise');\n }\n if (profile.primaryGoals.length > 0) {\n lines.push(`- Stated goals: ${profile.primaryGoals.join(', ')}`);\n }\n if (profile.knownPatterns.length > 0) {\n lines.push(`- Behavioural patterns: ${profile.knownPatterns.join(', ')}`);\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// F2: In-Session Proactive Awareness\n// ---------------------------------------------------------------------------\n\nexport function buildProactivenessInstructions(profile: UserFinancialProfile | null): string {\n const brevityGuidance = profile?.prefersBriefResponses\n ? 'This user prefers brevity — only surface context if urgent or directly actionable.'\n : 'Surface relevant context when criteria are met.';\n\n const styleGuidance = profile?.financialLiteracy === 'novice'\n ? 'Frame observations in plain English, no DeFi jargon.'\n : 'Technical framing is fine.';\n\n return `Proactive awareness:\nAfter completing the user's request, consider whether ONE additional piece of financial\ncontext is worth mentioning. ${brevityGuidance}\n\n✓ Mention if:\n- Their savings goal is materially off-track (>20% behind pace)\n- Yield rate changed significantly since last session (>0.5%)\n- They have idle USDC >$50 sitting for >48h\n- An action they just took interacts with an active goal or debt position\n- A pattern would materially benefit from their attention\n\n✗ Do NOT mention if:\n- Tangentially related but not actionable\n- Already surfaced this session\n- Requires more explanation than the original answer\n- Would seem pushy or sales-y\n\n${styleGuidance}\nFormat: One sentence maximum, after main response, separated by a line break.\nFrame as observation, not advice: \"Your Tokyo goal is $80 behind pace.\" — not \"You should deposit more.\"`;\n}\n\n// ---------------------------------------------------------------------------\n// F5: Post-Action Self-Evaluation\n// ---------------------------------------------------------------------------\n\nexport function buildSelfEvaluationInstruction(): string {\n return `Self-evaluation (apply silently before composing your response):\n\n1. ACCURACY — Quote exact values from tool results, not estimates or rounded figures.\n Never combine post-action tool results with pre-action snapshot numbers.\n If the tool returned an error, label it as an error — do not paraphrase it as success.\n\n2. STATE CONSISTENCY — Describe the actual outcome of all steps.\n Partial success (swap ok, deposit failed): describe both clearly.\n Never describe a failed action as if it succeeded.\n\n3. COMPLETENESS — If the user asked multiple things, answer all of them.\n If you couldn't complete something, explain why and what the current state is.\n\n4. TONE — Match tone to outcome.\n Success: confirming and forward-looking.\n Failure: clear about what failed, unchanged, and what to do next.\n Warning: specific risk, not generic caution.\n\nIf any check fails, rewrite before outputting.`;\n}\n","/**\n * Conversation State Machine — F4 of the Intelligence Layer.\n *\n * Types, pure context builder, and a generic state manager interface.\n * The Redis implementation lives in the host app (audric) since it depends on @upstash/redis.\n */\n\n// ---------------------------------------------------------------------------\n// State definitions\n// ---------------------------------------------------------------------------\n\nexport type ConversationState =\n | { type: 'idle' }\n\n | {\n type: 'mid_recipe';\n recipeName: string;\n currentStep: number;\n totalSteps: number;\n completedStepOutputs: Record<string, Record<string, string | number>>;\n startedAt: number;\n }\n\n | {\n type: 'awaiting_confirmation';\n action: string;\n amount?: number;\n recipient?: string;\n proposedAt: number;\n expiresAt: number;\n }\n\n | {\n type: 'post_error';\n failedAction: string;\n errorMessage: string;\n occurredAt: number;\n partialState?: string;\n }\n\n | {\n type: 'post_liquidation_warning';\n healthFactor: number;\n warnedAt: number;\n }\n\n | {\n type: 'onboarding';\n sessionNumber: number;\n hasBalance: boolean;\n hasSavedBefore: boolean;\n };\n\nexport type StateType = ConversationState['type'];\n\n// ---------------------------------------------------------------------------\n// State manager interface (host app provides the implementation)\n// ---------------------------------------------------------------------------\n\nexport interface ConversationStateStore {\n get(): Promise<ConversationState>;\n set(state: ConversationState): Promise<void>;\n transition(to: ConversationState): Promise<void>;\n reset(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Context builder — pure function, no I/O\n// ---------------------------------------------------------------------------\n\nexport function buildStateContext(state: ConversationState): string {\n switch (state.type) {\n case 'idle':\n return '';\n\n case 'mid_recipe': {\n const elapsed = Math.round((Date.now() - state.startedAt) / 60_000);\n const outputs = JSON.stringify(state.completedStepOutputs);\n return [\n `Conversation state: MID-RECIPE`,\n `Active recipe: ${state.recipeName} (step ${state.currentStep + 1} of ${state.totalSteps})`,\n `Started: ${elapsed} minutes ago`,\n `Completed step key outputs: ${outputs}`,\n `If the user asks an unrelated question: answer briefly, then offer to continue the ${state.recipeName} flow.`,\n `If the user says \"cancel\" or \"stop\": confirm you have abandoned the recipe and return to idle.`,\n ].join('\\n');\n }\n\n case 'awaiting_confirmation': {\n const expiryMins = Math.max(0, Math.round((state.expiresAt - Date.now()) / 60_000));\n const expired = state.expiresAt < Date.now();\n return [\n `Conversation state: AWAITING CONFIRMATION`,\n `Proposed action: ${state.action}${state.amount ? ` for $${state.amount}` : ''}${state.recipient ? ` to ${state.recipient}` : ''}`,\n expired\n ? `Status: EXPIRED — ask if user still wants to proceed`\n : `Expires in: ${expiryMins} minutes`,\n `\"yes/confirm/do it\" → execute. \"no/cancel/wait\" → abort, reset to idle.`,\n ].join('\\n');\n }\n\n case 'post_error':\n return [\n `Conversation state: POST-ERROR`,\n `Failed action: ${state.failedAction}`,\n `Error: ${state.errorMessage}`,\n state.partialState ? `Partial state: ${state.partialState}` : '',\n `Acknowledge failure clearly. Offer a specific recovery path if one exists.`,\n `This state clears automatically on the next successful action.`,\n ].filter(Boolean).join('\\n');\n\n case 'post_liquidation_warning':\n return [\n `Conversation state: LIQUIDATION WARNING ACTIVE`,\n `Health factor: ${state.healthFactor.toFixed(2)} — below safe threshold`,\n `Prioritise debt repayment or collateral deposit.`,\n `Do not proceed with any action that would further reduce health factor.`,\n ].join('\\n');\n\n case 'onboarding':\n return [\n `Conversation state: ONBOARDING (session ${state.sessionNumber})`,\n state.sessionNumber === 1\n ? 'First session — introduce capabilities through context, not a feature list.'\n : `Returning user — ${state.hasSavedBefore ? 'has saved before' : 'has not saved yet'}.`,\n ].join('\\n');\n\n default:\n return '';\n }\n}\n","import type { Tool, ToolContext } from './types.js';\nimport { getDefaultTools } from './tools/index.js';\n\n// ---------------------------------------------------------------------------\n// MCP tool descriptor — the shape MCP servers need to register tools\n// ---------------------------------------------------------------------------\n\nexport interface McpToolDescriptor {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n handler: (args: Record<string, unknown>) => Promise<{\n content: Array<{ type: 'text'; text: string }>;\n isError?: boolean;\n }>;\n}\n\n// ---------------------------------------------------------------------------\n// Convert engine tools → MCP tool descriptors\n// ---------------------------------------------------------------------------\n\n/**\n * Builds MCP-compatible tool descriptors from engine tools.\n * Each tool's `call()` is wrapped to return the MCP response format.\n *\n * Usage with @modelcontextprotocol/sdk:\n * ```\n * const descriptors = buildMcpTools(context);\n * for (const desc of descriptors) {\n * server.tool(desc.name, desc.description, desc.inputSchema, desc.handler);\n * }\n * ```\n */\nexport function buildMcpTools(\n context: ToolContext,\n tools?: Tool[],\n): McpToolDescriptor[] {\n const engineTools = tools ?? getDefaultTools();\n\n return engineTools.map((tool) => ({\n name: `audric_${tool.name}`,\n description: tool.description,\n inputSchema: tool.jsonSchema as unknown as Record<string, unknown>,\n\n async handler(args: Record<string, unknown>) {\n try {\n const parsed = tool.inputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n error: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(', ')}`,\n }),\n }],\n isError: true,\n };\n }\n\n const result = await tool.call(parsed.data, context);\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(result.data),\n }],\n };\n } catch (err) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n error: err instanceof Error ? err.message : 'Tool execution failed',\n }),\n }],\n isError: true,\n };\n }\n },\n }));\n}\n\n/**\n * Register all engine tools with an MCP server instance.\n * Convenience wrapper for the common pattern.\n */\nexport function registerEngineTools(\n server: { tool: (name: string, description: string, schema: Record<string, unknown>, handler: (args: Record<string, unknown>) => Promise<unknown>) => void },\n context: ToolContext,\n tools?: Tool[],\n): void {\n const descriptors = buildMcpTools(context, tools);\n for (const desc of descriptors) {\n server.tool(desc.name, desc.description, desc.inputSchema, desc.handler);\n }\n}\n","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type { Tool as McpToolDef } from '@modelcontextprotocol/sdk/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface McpServerConfig {\n /** Human-readable server name, used as tool namespace prefix. */\n name: string;\n /** MCP server URL (Streamable HTTP or SSE endpoint). */\n url: string;\n /** Transport type. Defaults to 'streamable-http'. */\n transport?: 'streamable-http' | 'sse';\n /** Response cache TTL in ms. Default 30_000 (30s). */\n cacheTtlMs?: number;\n /** Whether all tools from this server are read-only. Default true. */\n readOnly?: boolean;\n}\n\nexport interface McpServerConnection {\n config: McpServerConfig;\n client: Client;\n transport: Transport;\n tools: McpToolDef[];\n status: 'connected' | 'disconnected' | 'error';\n lastError?: string;\n}\n\nexport interface McpCallResult {\n content: Array<{ type: string; text?: string; [key: string]: unknown }>;\n isError?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Response cache\n// ---------------------------------------------------------------------------\n\ninterface CacheEntry {\n result: McpCallResult;\n expiresAt: number;\n}\n\nexport class McpResponseCache {\n private cache = new Map<string, CacheEntry>();\n private readonly defaultTtlMs: number;\n\n constructor(defaultTtlMs = 30_000) {\n this.defaultTtlMs = defaultTtlMs;\n }\n\n private key(serverName: string, toolName: string, args: unknown): string {\n return `${serverName}::${toolName}::${JSON.stringify(args)}`;\n }\n\n get(serverName: string, toolName: string, args: unknown): McpCallResult | null {\n const k = this.key(serverName, toolName, args);\n const entry = this.cache.get(k);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(k);\n return null;\n }\n return entry.result;\n }\n\n set(serverName: string, toolName: string, args: unknown, result: McpCallResult, ttlMs?: number): void {\n const k = this.key(serverName, toolName, args);\n this.cache.set(k, {\n result,\n expiresAt: Date.now() + (ttlMs ?? this.defaultTtlMs),\n });\n }\n\n invalidate(serverName?: string): void {\n if (!serverName) {\n this.cache.clear();\n return;\n }\n for (const key of this.cache.keys()) {\n if (key.startsWith(`${serverName}::`)) {\n this.cache.delete(key);\n }\n }\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n\n// ---------------------------------------------------------------------------\n// McpClientManager — multi-server connection registry\n// ---------------------------------------------------------------------------\n\nexport class McpClientManager {\n private connections = new Map<string, McpServerConnection>();\n private readonly responseCache: McpResponseCache;\n\n constructor(opts?: { cacheTtlMs?: number }) {\n this.responseCache = new McpResponseCache(opts?.cacheTtlMs ?? 30_000);\n }\n\n /**\n * Connect to an MCP server and discover its tools.\n * If already connected to a server with this name, disconnects first.\n */\n async connect(config: McpServerConfig): Promise<McpServerConnection> {\n if (this.connections.has(config.name)) {\n await this.disconnect(config.name);\n }\n\n const client = new Client(\n { name: 'audric-engine', version: '0.1.0' },\n { capabilities: {} },\n );\n\n const transportType = config.transport ?? 'streamable-http';\n const url = new URL(config.url);\n\n const transport = transportType === 'sse'\n ? new SSEClientTransport(url)\n : new StreamableHTTPClientTransport(url, {\n reconnectionOptions: {\n maxReconnectionDelay: 30_000,\n initialReconnectionDelay: 1_000,\n reconnectionDelayGrowFactor: 1.5,\n maxRetries: 3,\n },\n });\n\n const conn: McpServerConnection = {\n config,\n client,\n transport,\n tools: [],\n status: 'disconnected',\n };\n\n try {\n await client.connect(transport);\n conn.status = 'connected';\n\n const { tools } = await client.listTools();\n conn.tools = tools;\n } catch (err) {\n try { await client.close(); } catch { /* best-effort */ }\n throw err;\n }\n\n this.connections.set(config.name, conn);\n return conn;\n }\n\n /** Disconnect from a server by name. */\n async disconnect(name: string): Promise<void> {\n const conn = this.connections.get(name);\n if (!conn) return;\n try {\n await conn.client.close();\n } catch { /* best-effort */ }\n conn.status = 'disconnected';\n conn.tools = [];\n this.connections.delete(name);\n this.responseCache.invalidate(name);\n }\n\n /** Disconnect from all servers. */\n async disconnectAll(): Promise<void> {\n const names = [...this.connections.keys()];\n await Promise.allSettled(names.map((n) => this.disconnect(n)));\n }\n\n /** Get a connection by server name. */\n getConnection(name: string): McpServerConnection | undefined {\n return this.connections.get(name);\n }\n\n /** Check if a server is connected. */\n isConnected(name: string): boolean {\n return this.connections.get(name)?.status === 'connected';\n }\n\n /** List all tool definitions across all connected servers. */\n listAllTools(): Array<{ serverName: string; tool: McpToolDef }> {\n const result: Array<{ serverName: string; tool: McpToolDef }> = [];\n for (const [name, conn] of this.connections) {\n if (conn.status !== 'connected') continue;\n for (const tool of conn.tools) {\n result.push({ serverName: name, tool });\n }\n }\n return result;\n }\n\n /**\n * Call a tool on a specific server.\n * Uses response cache for read-only servers.\n */\n async callTool(\n serverName: string,\n toolName: string,\n args: Record<string, unknown> = {},\n ): Promise<McpCallResult> {\n const conn = this.connections.get(serverName);\n if (!conn) throw new Error(`MCP server \"${serverName}\" not connected`);\n if (conn.status !== 'connected') throw new Error(`MCP server \"${serverName}\" is ${conn.status}`);\n\n const cacheTtl = conn.config.cacheTtlMs ?? 30_000;\n if (conn.config.readOnly !== false && cacheTtl > 0) {\n const cached = this.responseCache.get(serverName, toolName, args);\n if (cached) return cached;\n }\n\n const result = await conn.client.callTool({ name: toolName, arguments: args });\n\n const callResult: McpCallResult = {\n content: (result.content ?? []) as McpCallResult['content'],\n isError: result.isError as boolean | undefined,\n };\n\n if (conn.config.readOnly !== false && cacheTtl > 0) {\n this.responseCache.set(serverName, toolName, args, callResult, cacheTtl);\n }\n\n return callResult;\n }\n\n /** Get the response cache (for testing / manual invalidation). */\n get cache(): McpResponseCache {\n return this.responseCache;\n }\n\n /** Number of connected servers. */\n get serverCount(): number {\n let count = 0;\n for (const conn of this.connections.values()) {\n if (conn.status === 'connected') count++;\n }\n return count;\n }\n\n /** All server names. */\n get serverNames(): string[] {\n return [...this.connections.keys()];\n }\n}\n","import { z } from 'zod';\nimport type { Tool as McpToolDef } from '@modelcontextprotocol/sdk/types.js';\nimport type { Tool, ToolJsonSchema, PermissionLevel } from './types.js';\nimport type { McpClientManager } from './mcp-client.js';\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\nexport interface McpToolAdapterConfig {\n /** The McpClientManager to route calls through. */\n manager: McpClientManager;\n /** Server name this tool belongs to. */\n serverName: string;\n /** Override permission level for all tools from this server. */\n permissionLevel?: PermissionLevel;\n /** Override isReadOnly for all tools from this server. */\n isReadOnly?: boolean;\n /** Per-tool overrides keyed by MCP tool name. */\n toolOverrides?: Record<string, {\n permissionLevel?: PermissionLevel;\n isReadOnly?: boolean;\n description?: string;\n }>;\n}\n\n// ---------------------------------------------------------------------------\n// Adapter: single MCP tool → engine Tool\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a single MCP tool definition into an engine Tool.\n * The tool name is namespaced as `{serverName}_{mcpToolName}`.\n */\nexport function adaptMcpTool(\n mcpTool: McpToolDef,\n config: McpToolAdapterConfig,\n): Tool {\n const overrides = config.toolOverrides?.[mcpTool.name];\n const isReadOnly = overrides?.isReadOnly ?? config.isReadOnly ?? true;\n const permissionLevel = overrides?.permissionLevel ?? config.permissionLevel ?? 'auto';\n const namespacedName = `${config.serverName}_${mcpTool.name}`;\n\n const jsonSchema: ToolJsonSchema = (mcpTool.inputSchema ?? {\n type: 'object',\n properties: {},\n }) as ToolJsonSchema;\n\n return {\n name: namespacedName,\n description: overrides?.description ?? mcpTool.description ?? `MCP tool: ${mcpTool.name}`,\n inputSchema: z.record(z.unknown()),\n jsonSchema,\n isReadOnly,\n isConcurrencySafe: isReadOnly,\n permissionLevel,\n flags: {},\n\n async call(input, _context) {\n const result = await config.manager.callTool(\n config.serverName,\n mcpTool.name,\n input as Record<string, unknown>,\n );\n\n const textContent = result.content\n .filter((c) => c.type === 'text' && c.text)\n .map((c) => c.text!)\n .join('\\n');\n\n let data: unknown;\n try {\n data = JSON.parse(textContent);\n } catch {\n data = textContent || result.content;\n }\n\n if (result.isError) {\n return { data: { error: data } };\n }\n\n return { data };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Batch adapter: all tools from a server → engine Tools\n// ---------------------------------------------------------------------------\n\n/**\n * Convert all discovered tools from an MCP server into engine Tools.\n * Call this after `manager.connect(config)` completes successfully.\n */\nexport function adaptAllMcpTools(config: McpToolAdapterConfig): Tool[] {\n const conn = config.manager.getConnection(config.serverName);\n if (!conn || conn.status !== 'connected') {\n return [];\n }\n return conn.tools.map((t) => adaptMcpTool(t, config));\n}\n\n/**\n * Convenience: adapt tools from all connected servers.\n * Returns a flat array of engine Tools, namespaced by server name.\n */\nexport function adaptAllServerTools(\n manager: McpClientManager,\n serverConfigs?: Record<string, Omit<McpToolAdapterConfig, 'manager' | 'serverName'>>,\n): Tool[] {\n const allTools: Tool[] = [];\n\n for (const { serverName, tool } of manager.listAllTools()) {\n const serverOpts = serverConfigs?.[serverName] ?? {};\n allTools.push(adaptMcpTool(tool, {\n manager,\n serverName,\n ...serverOpts,\n }));\n }\n\n return allTools;\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport type {\n ChatParams,\n LLMProvider,\n Message,\n ProviderEvent,\n StopReason,\n SystemPrompt,\n ThinkingConfig,\n ToolDefinition,\n} from '../types.js';\nimport { parseEvalSummary } from '../eval-summary.js';\n\nconst DEFAULT_MODEL = 'claude-sonnet-4-20250514';\nconst DEFAULT_MAX_TOKENS = 4096;\n\n// Anthropic occasionally returns 529 overloaded_error or 429 rate_limit_error\n// when their infrastructure is over capacity. The SDK does NOT auto-retry\n// streaming requests once the connection opens, so we wrap the stream call\n// ourselves: if the stream errors before yielding any events, we retry with\n// exponential backoff. Once tokens have started flowing we propagate, because\n// retrying mid-stream would corrupt engine state (double-counted tokens, etc.).\nconst DEFAULT_MAX_RETRIES = 3;\nconst RETRY_BASE_DELAY_MS = 1000;\nconst RETRY_MAX_DELAY_MS = 8000;\n\nexport interface AnthropicProviderConfig {\n apiKey: string;\n defaultModel?: string;\n defaultMaxTokens?: number;\n /** Max retry attempts for retriable errors (overloaded, rate-limited, network). Default 3. */\n maxRetries?: number;\n}\n\nexport class AnthropicProvider implements LLMProvider {\n private client: Anthropic;\n private defaultModel: string;\n private defaultMaxTokens: number;\n private maxRetries: number;\n\n constructor(config: AnthropicProviderConfig) {\n this.client = new Anthropic({ apiKey: config.apiKey });\n this.defaultModel = config.defaultModel ?? DEFAULT_MODEL;\n this.defaultMaxTokens = config.defaultMaxTokens ?? DEFAULT_MAX_TOKENS;\n this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n }\n\n async *chat(params: ChatParams): AsyncGenerator<ProviderEvent> {\n let attempt = 0;\n while (true) {\n let yieldedAnything = false;\n const inner = this.streamOnce(params);\n try {\n for (;;) {\n const next = await inner.next();\n if (next.done) return;\n yieldedAnything = true;\n yield next.value;\n }\n } catch (err) {\n // Best-effort: tell the inner generator to release the underlying stream.\n try { await inner.return?.(undefined); } catch { /* noop */ }\n\n if (!yieldedAnything && isRetriableError(err) && attempt < this.maxRetries) {\n attempt++;\n const delayMs = computeBackoffMs(attempt);\n console.warn(\n `[anthropic] retriable error (attempt ${attempt}/${this.maxRetries}, retrying in ${delayMs}ms): ${rawErrorMessage(err)}`,\n );\n await sleep(delayMs);\n continue;\n }\n throw new Error(friendlyErrorMessage(err));\n }\n }\n }\n\n private async *streamOnce(params: ChatParams): AsyncGenerator<ProviderEvent> {\n const messages = sanitizeAnthropicMessages(\n params.messages.map(toAnthropicMessage),\n );\n const tools = params.tools.map(toAnthropicTool);\n\n let toolChoice: Anthropic.Messages.MessageCreateParams['tool_choice'] | undefined;\n if (params.toolChoice && tools.length > 0) {\n if (params.toolChoice === 'any') {\n toolChoice = { type: 'any' };\n } else if (params.toolChoice === 'auto') {\n toolChoice = { type: 'auto' };\n } else if (typeof params.toolChoice === 'object') {\n toolChoice = { type: 'tool', name: params.toolChoice.name };\n }\n }\n\n const thinkingParam = toAnthropicThinking(params.thinking);\n\n const systemParam = toAnthropicSystem(params.systemPrompt);\n\n const baseParams: Anthropic.Messages.MessageCreateParamsStreaming = {\n model: params.model ?? this.defaultModel,\n max_tokens: params.maxTokens ?? this.defaultMaxTokens,\n system: systemParam,\n messages,\n stream: true as const,\n tools: tools.length > 0 ? tools : undefined,\n ...(!thinkingParam && params.temperature !== undefined && { temperature: params.temperature }),\n ...(toolChoice && { tool_choice: toolChoice }),\n };\n\n const streamParams = {\n ...baseParams,\n ...(thinkingParam && { thinking: thinkingParam }),\n ...(params.outputConfig?.effort && { output_config: { effort: params.outputConfig.effort } }),\n };\n\n // Cast to satisfy SDK types — thinking/output_config may not be in the type defs yet\n const stream = params.signal\n ? this.client.messages.stream(streamParams as Anthropic.Messages.MessageCreateParamsStreaming, { signal: params.signal })\n : this.client.messages.stream(streamParams as Anthropic.Messages.MessageCreateParamsStreaming);\n\n const toolInputBuffers = new Map<number, { id: string; name: string; json: string }>();\n const thinkingBuffers = new Map<number, { type: 'thinking'; text: string; signature: string } | { type: 'redacted_thinking'; data: string }>();\n let outputTokensFromStart = 0;\n\n try {\n for await (const event of stream) {\n switch (event.type) {\n case 'message_start': {\n const msg = event.message;\n yield {\n type: 'message_start',\n messageId: msg.id,\n model: msg.model,\n };\n if (msg.usage) {\n const u = msg.usage as unknown as Record<string, number>;\n outputTokensFromStart = msg.usage.output_tokens;\n yield {\n type: 'usage',\n inputTokens: msg.usage.input_tokens,\n outputTokens: msg.usage.output_tokens,\n cacheReadTokens: u.cache_read_input_tokens,\n cacheWriteTokens: u.cache_creation_input_tokens,\n };\n }\n break;\n }\n\n case 'content_block_start': {\n const block = event.content_block as { type: string; id?: string; name?: string; data?: string };\n if (block.type === 'tool_use') {\n toolInputBuffers.set(event.index, {\n id: block.id!,\n name: block.name!,\n json: '',\n });\n yield {\n type: 'tool_use_start',\n id: block.id!,\n name: block.name!,\n };\n } else if (block.type === 'thinking') {\n thinkingBuffers.set(event.index, { type: 'thinking', text: '', signature: '' });\n } else if (block.type === 'redacted_thinking') {\n thinkingBuffers.set(event.index, { type: 'redacted_thinking', data: block.data ?? '' });\n }\n break;\n }\n\n case 'content_block_delta': {\n const delta = event.delta as { type: string; text?: string; partial_json?: string; thinking?: string; signature?: string };\n if (delta.type === 'text_delta') {\n yield { type: 'text_delta', text: delta.text! };\n } else if (delta.type === 'input_json_delta') {\n const buf = toolInputBuffers.get(event.index);\n if (buf) {\n buf.json += delta.partial_json!;\n yield {\n type: 'tool_use_delta',\n id: buf.id,\n partialJson: delta.partial_json!,\n };\n }\n } else if (delta.type === 'thinking_delta') {\n const buf = thinkingBuffers.get(event.index);\n if (buf?.type === 'thinking') buf.text += delta.thinking ?? '';\n yield { type: 'thinking_delta', text: delta.thinking ?? '', blockIndex: event.index };\n } else if (delta.type === 'signature_delta') {\n const buf = thinkingBuffers.get(event.index);\n if (buf?.type === 'thinking') buf.signature = delta.signature ?? '';\n }\n break;\n }\n\n case 'content_block_stop': {\n const toolBuf = toolInputBuffers.get(event.index);\n if (toolBuf) {\n let input: unknown = {};\n try {\n input = JSON.parse(toolBuf.json || '{}');\n } catch {\n input = {};\n }\n yield {\n type: 'tool_use_done',\n id: toolBuf.id,\n name: toolBuf.name,\n input,\n };\n toolInputBuffers.delete(event.index);\n }\n const thinkBuf = thinkingBuffers.get(event.index);\n if (thinkBuf?.type === 'thinking') {\n // [SPEC 8 v0.5.1] Detect <eval_summary> marker in the\n // thinking buffer. When present + parseable, populate the\n // structured fields the host renders as HowIEvaluatedBlock.\n const summary = parseEvalSummary(thinkBuf.text);\n yield {\n type: 'thinking_done',\n blockIndex: event.index,\n thinking: thinkBuf.text,\n signature: thinkBuf.signature,\n ...(summary\n ? { summaryMode: true, evaluationItems: summary.evaluationItems }\n : {}),\n };\n thinkingBuffers.delete(event.index);\n } else if (thinkBuf?.type === 'redacted_thinking') {\n yield { type: 'redacted_thinking', data: thinkBuf.data };\n thinkingBuffers.delete(event.index);\n }\n break;\n }\n\n case 'message_delta': {\n const delta = event.delta as { stop_reason?: string };\n const usage = event.usage as { output_tokens?: number } | undefined;\n // message_delta.usage.output_tokens is cumulative — emit only the delta\n if (usage?.output_tokens && usage.output_tokens > outputTokensFromStart) {\n const increment = usage.output_tokens - outputTokensFromStart;\n outputTokensFromStart = usage.output_tokens;\n yield {\n type: 'usage',\n inputTokens: 0,\n outputTokens: increment,\n };\n }\n if (delta.stop_reason) {\n yield {\n type: 'stop',\n reason: mapStopReason(delta.stop_reason),\n };\n }\n break;\n }\n }\n }\n } finally {\n stream.abort();\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error classification + retry helpers\n// ---------------------------------------------------------------------------\n\n// Exported for testing. Not part of the public provider API.\nexport const _internal = {\n isRetriableError: (err: unknown) => isRetriableError(err),\n friendlyErrorMessage: (err: unknown) => friendlyErrorMessage(err),\n computeBackoffMs: (attempt: number) => computeBackoffMs(attempt),\n};\n\nfunction isRetriableError(err: unknown): boolean {\n if (!err) return false;\n\n // Anthropic SDK error classes (status-based)\n if (err instanceof Anthropic.APIError) {\n // 529 overloaded, 408 timeout, 502/503/504 transient\n if (err.status === 529 || err.status === 408) return true;\n if (err.status === 502 || err.status === 503 || err.status === 504) return true;\n // 429 rate-limited — retry but the user may need to slow down regardless\n if (err.status === 429) return true;\n return false;\n }\n\n // Sometimes streaming errors arrive as plain Error with the JSON message\n // baked into err.message (e.g. {\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",...}})\n const msg = rawErrorMessage(err).toLowerCase();\n if (\n msg.includes('overloaded_error') ||\n msg.includes('\"overloaded\"') ||\n msg.includes('rate_limit_error') ||\n msg.includes('econnreset') ||\n msg.includes('etimedout') ||\n msg.includes('socket hang up') ||\n msg.includes('fetch failed') ||\n msg.includes('network error')\n ) {\n return true;\n }\n\n return false;\n}\n\nfunction rawErrorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n if (typeof err === 'string') return err;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n}\n\n/**\n * Map a raw provider error to a clean, user-facing message.\n *\n * Most users see this as the chat error bubble — never leak raw JSON or\n * stack traces. Any string returned here is safe to render verbatim in UI.\n */\nfunction friendlyErrorMessage(err: unknown): string {\n const msg = rawErrorMessage(err).toLowerCase();\n\n if (\n msg.includes('overloaded_error') ||\n msg.includes('\"overloaded\"') ||\n (err instanceof Anthropic.APIError && err.status === 529)\n ) {\n return \"Anthropic's servers are over capacity right now. Please try again in 30 seconds.\";\n }\n if (\n msg.includes('rate_limit_error') ||\n (err instanceof Anthropic.APIError && err.status === 429)\n ) {\n return 'Too many requests in a short window. Please wait a moment and try again.';\n }\n if (\n msg.includes('econnreset') ||\n msg.includes('etimedout') ||\n msg.includes('socket hang up') ||\n msg.includes('fetch failed') ||\n msg.includes('network error')\n ) {\n return \"Couldn't reach Anthropic. Check your connection and try again.\";\n }\n if (err instanceof Anthropic.APIError && err.status === 401) {\n return 'Authentication failed. Please check the Anthropic API key configuration.';\n }\n if (err instanceof Anthropic.APIError && err.status === 400) {\n return 'The request was rejected by Anthropic. This is likely a bug — please retry, and if it persists, contact support.';\n }\n if (err instanceof Anthropic.APIError && err.status >= 500) {\n return 'Anthropic returned a server error. Please try again in a moment.';\n }\n\n return 'Something went wrong. Please try again.';\n}\n\nfunction computeBackoffMs(attempt: number): number {\n const base = Math.min(RETRY_BASE_DELAY_MS * 2 ** (attempt - 1), RETRY_MAX_DELAY_MS);\n const jitter = Math.floor(Math.random() * 250);\n return base + jitter;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ---------------------------------------------------------------------------\n// Conversion helpers\n// ---------------------------------------------------------------------------\n\nfunction toAnthropicSystem(prompt: SystemPrompt): string | Anthropic.Messages.TextBlockParam[] {\n if (typeof prompt === 'string') return prompt;\n return prompt.map((block) => ({\n type: 'text' as const,\n text: block.text,\n ...(block.cache_control && { cache_control: block.cache_control }),\n }));\n}\n\nfunction toAnthropicThinking(config?: ThinkingConfig): Record<string, unknown> | undefined {\n if (!config || config.type === 'disabled') return undefined;\n if (config.type === 'adaptive') return { type: 'adaptive' };\n return { type: 'enabled', budget_tokens: config.budgetTokens };\n}\n\nfunction toAnthropicMessage(msg: Message): Anthropic.MessageParam {\n const content: Anthropic.ContentBlockParam[] = msg.content\n .map((block): Anthropic.ContentBlockParam | null => {\n switch (block.type) {\n case 'text':\n return { type: 'text' as const, text: block.text };\n case 'thinking':\n return { type: 'thinking' as const, thinking: block.thinking, signature: block.signature } as unknown as Anthropic.ContentBlockParam;\n case 'redacted_thinking':\n return { type: 'redacted_thinking' as const, data: block.data } as unknown as Anthropic.ContentBlockParam;\n case 'tool_use':\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input as Record<string, unknown>,\n };\n case 'tool_result':\n return {\n type: 'tool_result' as const,\n tool_use_id: block.toolUseId,\n content: block.content,\n is_error: block.isError,\n };\n }\n })\n .filter((b): b is Anthropic.ContentBlockParam => b !== null);\n\n return { role: msg.role, content };\n}\n\nfunction toAnthropicTool(\n def: ToolDefinition,\n): Anthropic.Messages.Tool {\n return {\n name: def.name,\n description: def.description,\n input_schema: def.input_schema as Anthropic.Messages.Tool.InputSchema,\n };\n}\n\nfunction mapStopReason(reason: string): StopReason {\n switch (reason) {\n case 'end_turn':\n return 'end_turn';\n case 'tool_use':\n return 'tool_use';\n case 'max_tokens':\n return 'max_tokens';\n default:\n return 'end_turn';\n }\n}\n\n/**\n * Last-line-of-defense sanitization operating directly on Anthropic-format messages.\n * Enforces the positional constraint: every tool_use in an assistant message must have\n * a matching tool_result (by tool_use_id) in the immediately next user message.\n * Strips orphans in both directions and fixes role alternation.\n */\nfunction sanitizeAnthropicMessages(\n messages: Anthropic.MessageParam[],\n): Anthropic.MessageParam[] {\n const result: Anthropic.MessageParam[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n const content = Array.isArray(msg.content) ? msg.content : [{ type: 'text' as const, text: msg.content }];\n\n // Collect tool_use ids in this assistant message\n const toolUseIds = content\n .filter((b): b is Anthropic.ToolUseBlockParam => (b as { type: string }).type === 'tool_use')\n .map((b) => b.id);\n\n if (msg.role === 'assistant' && toolUseIds.length > 0) {\n const next = messages[i + 1];\n const nextContent = next ? (Array.isArray(next.content) ? next.content : []) : [];\n const nextResultIds = new Set(\n nextContent\n .filter((b): b is Anthropic.ToolResultBlockParam => (b as { type: string }).type === 'tool_result')\n .map((b) => b.tool_use_id),\n );\n\n // Keep only tool_use blocks that have a result in the next message\n const cleanContent = content.filter((b) => {\n if ((b as { type: string }).type === 'tool_use') return nextResultIds.has((b as Anthropic.ToolUseBlockParam).id);\n return true;\n });\n\n // Keep only tool_result blocks in next whose tool_use survived\n const keptIds = new Set(\n cleanContent\n .filter((b): b is Anthropic.ToolUseBlockParam => (b as { type: string }).type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanNext = nextContent.filter((b) => {\n if ((b as { type: string }).type === 'tool_result')\n return keptIds.has((b as Anthropic.ToolResultBlockParam).tool_use_id);\n return true;\n });\n\n if (cleanContent.length > 0) result.push({ role: 'assistant', content: cleanContent });\n if (cleanNext.length > 0 && next) result.push({ role: next.role, content: cleanNext });\n i++; // skip the next message (already processed)\n\n if (cleanContent.length < content.length || cleanNext.length < nextContent.length) {\n console.warn(\n `[anthropic] sanitized orphans: stripped ${content.length - cleanContent.length} tool_use, ${nextContent.length - cleanNext.length} tool_result`,\n );\n }\n continue;\n }\n\n // For user messages: strip tool_result referencing non-existent tool_use in prev assistant\n if (msg.role === 'user' && content.some((b) => (b as { type: string }).type === 'tool_result')) {\n const prev = result[result.length - 1];\n const prevContent = prev?.role === 'assistant' && Array.isArray(prev.content) ? prev.content : [];\n const prevToolUseIds = new Set(\n prevContent\n .filter((b): b is Anthropic.ToolUseBlockParam => (b as { type: string }).type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanContent = content.filter((b) => {\n if ((b as { type: string }).type === 'tool_result')\n return prevToolUseIds.has((b as Anthropic.ToolResultBlockParam).tool_use_id);\n return true;\n });\n if (cleanContent.length > 0) result.push({ role: msg.role, content: cleanContent });\n continue;\n }\n\n result.push(msg);\n }\n\n // Merge consecutive same-role messages\n const merged: Anthropic.MessageParam[] = [];\n for (const msg of result) {\n const last = merged[merged.length - 1];\n if (last && last.role === msg.role) {\n const lastContent = Array.isArray(last.content) ? last.content : [{ type: 'text' as const, text: last.content }];\n const msgContent = Array.isArray(msg.content) ? msg.content : [{ type: 'text' as const, text: msg.content }];\n last.content = [...lastContent, ...msgContent];\n } else {\n merged.push({ ...msg });\n }\n }\n\n // First message must be user\n while (merged.length > 0 && merged[0].role !== 'user') {\n merged.shift();\n }\n\n return merged;\n}\n"]}
1
+ {"version":3,"sources":["../src/tool.ts","../src/orchestration.ts","../src/tool-flags.ts","../src/navi-config.ts","../src/tools/utils.ts","../src/navi-transforms.ts","../src/sui-rpc.ts","../src/defi-cache.ts","../src/wallet-cache.ts","../src/cross-instance-lock.ts","../src/telemetry.ts","../src/blockvision-prices.ts","../src/audric-api.ts","../src/sui-address.ts","../src/tools/balance.ts","../src/navi-cache.ts","../src/navi-reads.ts","../src/tools/savings.ts","../src/tools/health.ts","../src/tools/rates.ts","../src/tools/history.ts","../src/tools/save.ts","../src/tools/withdraw.ts","../src/tools/transfer.ts","../src/tools/borrow.ts","../src/tools/repay.ts","../src/tools/claim.ts","../src/tools/pay.ts","../src/tools/mpp-services.ts","../src/tools/swap.ts","../src/tools/swap-quote.ts","../src/tools/volo-stake.ts","../src/tools/volo-unstake.ts","../src/tools/volo-stats.ts","../src/tools/contacts.ts","../src/tools/web-search.ts","../src/tools/explain-tx.ts","../src/tools/portfolio-analysis.ts","../src/tools/protocol-deep-dive.ts","../src/tools/receive.ts","../src/tools/canvas.ts","../src/tools/spending.ts","../src/tools/yield-summary.ts","../src/tools/activity-summary.ts","../src/tools/resolve-suins.ts","../src/tools/update-todo.ts","../src/tools/token-prices.ts","../src/tools/index.ts","../src/tools/tool-modifiable-fields.ts","../src/prompt.ts","../src/cost.ts","../src/describe-action.ts","../src/thinking-budget.ts","../src/guards.ts","../src/compact/microcompact.ts","../src/context.ts","../src/permission-rules.ts","../src/turn-read-cache.ts","../src/early-dispatcher.ts","../src/tool-ttls.ts","../src/compose-bundle.ts","../src/engine.ts","../src/types.ts","../src/streaming.ts","../src/session.ts","../src/recipes/loader.ts","../src/recipes/registry.ts","../src/classify-effort.ts","../src/eval-summary.ts","../src/prompt-cache.ts","../src/intelligence.ts","../src/state/conversation-state.ts","../src/mcp.ts","../src/mcp-client.ts","../src/mcp-tool-adapter.ts","../src/providers/anthropic.ts"],"names":["getDecimalsForCoinType","activeStore","sleep","resolveSymbol","n","SUI_MAINNET_URL","GAS_RESERVE_SUI","gasReserveUsd","balance","usdcHolding","usdsuiHolding","defi","callNavi","z","result","stamped","borrowed","status","transportHf","hf","STABLECOIN_SYMBOLS","priceFor","records","filtered","cutoffMs","recent","assertAllowedAsset","MPP_GATEWAY","services","inputSchema","SUI_ADDRESS_REGEX","stableStringify","randomUUID","DEFAULT_MAX_TOKENS"],"mappings":"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","file":"index.js","sourcesContent":["import type { z } from 'zod';\nimport type {\n PermissionLevel,\n PreflightResult,\n Tool,\n ToolContext,\n ToolFlags,\n ToolJsonSchema,\n ToolResult,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// buildTool — factory for creating typed, permission-aware tools\n// ---------------------------------------------------------------------------\n\nexport interface BuildToolOptions<TInput, TOutput> {\n name: string;\n description: string;\n inputSchema: z.ZodType<TInput>;\n jsonSchema: ToolJsonSchema;\n call: (input: TInput, context: ToolContext) => Promise<ToolResult<TOutput>>;\n isReadOnly?: boolean;\n permissionLevel?: PermissionLevel;\n flags?: ToolFlags;\n preflight?: (input: TInput) => PreflightResult;\n maxResultSizeChars?: number;\n summarizeOnTruncate?: (result: string, maxChars: number) => string;\n /**\n * [v1.5.1] See `Tool.cacheable`. Default `true`. Set `false` for\n * tools whose results depend on mutable on-chain state.\n */\n cacheable?: boolean;\n}\n\ntype AnyPreflight = (input: unknown) => PreflightResult;\n\nexport function buildTool<TInput, TOutput>(\n opts: BuildToolOptions<TInput, TOutput>,\n): Tool<TInput, TOutput> {\n const isReadOnly = opts.isReadOnly ?? true;\n return {\n name: opts.name,\n description: opts.description,\n inputSchema: opts.inputSchema,\n jsonSchema: opts.jsonSchema,\n call: opts.call,\n isReadOnly,\n isConcurrencySafe: isReadOnly,\n permissionLevel: opts.permissionLevel ?? (isReadOnly ? 'auto' : 'confirm'),\n flags: opts.flags ?? {},\n preflight: opts.preflight as AnyPreflight | undefined,\n maxResultSizeChars: opts.maxResultSizeChars,\n summarizeOnTruncate: opts.summarizeOnTruncate,\n cacheable: opts.cacheable,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tool helpers\n// ---------------------------------------------------------------------------\n\nexport function toolsToDefinitions(tools: Tool[]): {\n name: string;\n description: string;\n input_schema: ToolJsonSchema;\n}[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.jsonSchema,\n }));\n}\n\nexport function findTool(tools: Tool[], name: string): Tool | undefined {\n return tools.find((t) => t.name === name);\n}\n","import type { EngineEvent, Tool, ToolContext } from './types.js';\nimport { findTool } from './tool.js';\n\n// ---------------------------------------------------------------------------\n// Pending tool call — accumulated from provider events\n// ---------------------------------------------------------------------------\n\nexport interface PendingToolCall {\n id: string;\n name: string;\n input: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// TxMutex — serialises write operations to prevent race conditions\n// ---------------------------------------------------------------------------\n\nexport class TxMutex {\n private queue: (() => void)[] = [];\n private locked = false;\n\n async acquire(): Promise<void> {\n if (!this.locked) {\n this.locked = true;\n return;\n }\n return new Promise<void>((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n release(): void {\n const next = this.queue.shift();\n if (next) {\n next();\n } else {\n this.locked = false;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// [SPEC 8 v0.5.1 B3.2] withRetryStats — per-tool retry attempt counter\n//\n// Engine dispatchers wrap each tool invocation with a fresh\n// `retryStats: { attemptCount: 1 }` so every tool gets an isolated counter.\n// The BlockVision retry wrapper (`fetchBlockVisionWithRetry`) deep in the\n// call stack increments `retryStats.attemptCount` on every retry beyond\n// the first attempt; the dispatcher reads it back via `readAttemptCount()`\n// and surfaces the value (when > 1) on the `tool_result` event.\n//\n// Tools that don't use a retry wrapper never observe a non-default value,\n// so `attemptCount` stays undefined on `tool_result` for them — matching\n// the spec's \"kept undefined to avoid header noise on the common path.\"\n// ---------------------------------------------------------------------------\n\nexport function withRetryStats(context: ToolContext): {\n context: ToolContext;\n readAttemptCount: () => number | undefined;\n} {\n const retryStats = { attemptCount: 1 };\n return {\n context: { ...context, retryStats },\n readAttemptCount: () =>\n retryStats.attemptCount > 1 ? retryStats.attemptCount : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// runTools — executes tool calls with parallel reads, serial writes\n// ---------------------------------------------------------------------------\n\nexport async function* runTools(\n pending: PendingToolCall[],\n tools: Tool[],\n context: ToolContext,\n txMutex: TxMutex,\n): AsyncGenerator<EngineEvent> {\n const { reads, writes } = partitionToolCalls(pending, tools);\n\n // Phase 1: execute all read-only tools in parallel\n if (reads.length > 0) {\n const readResults = await Promise.allSettled(\n reads.map(async (call) => {\n const tool = findTool(tools, call.name);\n if (!tool) {\n return {\n call,\n result: { data: { error: `Unknown tool: ${call.name}` } },\n isError: true,\n attemptCount: undefined as number | undefined,\n };\n }\n const { context: toolCtx, readAttemptCount } = withRetryStats(context);\n const execResult = await executeSingleTool(tool, call, toolCtx);\n if (!execResult.isError) {\n execResult.data = budgetToolResult(execResult.data, tool);\n }\n return {\n call,\n result: execResult,\n isError: execResult.isError,\n attemptCount: readAttemptCount(),\n };\n }),\n );\n\n for (const settled of readResults) {\n if (settled.status === 'fulfilled') {\n const { call, result, isError, attemptCount } = settled.value;\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: result.data,\n isError,\n ...(attemptCount !== undefined ? { attemptCount } : {}),\n };\n } else {\n const idx = readResults.indexOf(settled);\n const call = reads[idx];\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: settled.reason?.message ?? 'Tool execution failed' },\n isError: true,\n };\n }\n }\n }\n\n // Phase 2: execute write tools sequentially under mutex\n for (const call of writes) {\n const tool = findTool(tools, call.name);\n if (!tool) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: `Unknown tool: ${call.name}` },\n isError: true,\n };\n continue;\n }\n await txMutex.acquire();\n try {\n const { context: toolCtx, readAttemptCount } = withRetryStats(context);\n const result = await executeSingleTool(tool, call, toolCtx);\n if (!result.isError) {\n result.data = budgetToolResult(result.data, tool);\n }\n const attemptCount = readAttemptCount();\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: result.data,\n isError: result.isError,\n ...(attemptCount !== undefined ? { attemptCount } : {}),\n };\n } catch (err) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: err instanceof Error ? err.message : 'Tool execution failed' },\n isError: true,\n };\n } finally {\n txMutex.release();\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction partitionToolCalls(\n pending: PendingToolCall[],\n tools: Tool[],\n): { reads: PendingToolCall[]; writes: PendingToolCall[] } {\n const reads: PendingToolCall[] = [];\n const writes: PendingToolCall[] = [];\n\n for (const call of pending) {\n const tool = findTool(tools, call.name);\n if (!tool) {\n reads.push(call); // unknown tools treated as reads — will fail safely\n continue;\n }\n if (tool.isReadOnly && tool.isConcurrencySafe) {\n reads.push(call);\n } else {\n writes.push(call);\n }\n }\n\n return { reads, writes };\n}\n\nasync function executeSingleTool(\n tool: Tool,\n call: PendingToolCall,\n context: ToolContext,\n): Promise<{ data: unknown; isError: boolean }> {\n const parsed = tool.inputSchema.safeParse(call.input);\n if (!parsed.success) {\n return {\n data: {\n error: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(', ')}`,\n },\n isError: true,\n };\n }\n\n const result = await tool.call(parsed.data, context);\n return { data: result.data, isError: false };\n}\n\n/**\n * Enforce per-tool result size limits. When a serialized result exceeds\n * `maxResultSizeChars`, truncate it with a hint to re-call with narrower\n * parameters. Uses the tool's custom `summarizeOnTruncate` when available.\n */\nexport function budgetToolResult(\n data: unknown,\n tool: Tool,\n): unknown {\n if (!tool.maxResultSizeChars) return data;\n\n const serialized = typeof data === 'string' ? data : JSON.stringify(data);\n if (serialized.length <= tool.maxResultSizeChars) return data;\n\n if (tool.summarizeOnTruncate) {\n const summarized = tool.summarizeOnTruncate(serialized, tool.maxResultSizeChars);\n try { return JSON.parse(summarized); } catch { return summarized; }\n }\n\n const preview = serialized.slice(0, tool.maxResultSizeChars);\n const linesOmitted = serialized.split('\\n').length - preview.split('\\n').length;\n const note = `[Truncated — ${linesOmitted} lines omitted. Call ${tool.name} with narrower parameters (e.g. smaller date range or limit) to see more.]`;\n /**\n * [v1.5.2] If the original payload was a JSON object, *don't* return a\n * raw sliced string — the slice is invalid JSON, JSON.parse fails, and\n * downstream consumers (frontend card renderers, history-replay logic,\n * etc.) get a string they cannot destructure. Instead, wrap the\n * preview in a structured `_truncated` envelope so the result stays\n * object-shaped. Tools that genuinely return a string (rare) fall\n * through to the legacy concat behavior.\n */\n if (typeof data === 'object' && data !== null) {\n return { _truncated: true, _preview: preview, _note: note };\n }\n return `${preview}\\n\\n${note}`;\n}\n","import type { Tool, ToolFlags } from './types.js';\n\n/**\n * Central registry of tool flags for the guard runner (RE-2.2).\n *\n * Flags are declarative metadata that guards read to decide what checks to run.\n * Read-only tools have no flags by default (empty object).\n *\n * Flag meanings:\n * mutating — changes on-chain state (deposit, swap, send, borrow)\n * requiresBalance — needs sufficient funds to execute\n * affectsHealth — can change borrow health factor\n * irreversible — physical mail, external transfers — can't undo\n * producesArtifact — returns images, documents, generated content\n * costAware — has a monetary cost the user should know about\n * maxRetries — max calls with same input (default: unlimited for reads, 1 for writes)\n * bundleable — [SPEC 7 Layer 2] can participate in a multi-write Payment Stream\n * PTB. Set on every confirm-tier write whose on-chain effect is\n * fully expressible at compose time. Excluded: `pay_api` (recipient/\n * amount/currency unknown until gateway 402 challenge resolves at\n * route time) and `save_contact` (Postgres-only, no on-chain effect).\n */\nexport const TOOL_FLAGS: Record<string, ToolFlags> = {\n // Write tools — financial (bundleable — SPEC 7 Layer 2)\n save_deposit: { mutating: true, requiresBalance: true, bundleable: true },\n withdraw: { mutating: true, affectsHealth: true, bundleable: true },\n send_transfer: { mutating: true, requiresBalance: true, irreversible: true, bundleable: true },\n swap_execute: { mutating: true, requiresBalance: true, bundleable: true },\n borrow: { mutating: true, affectsHealth: true, bundleable: true },\n repay_debt: { mutating: true, requiresBalance: true, bundleable: true },\n claim_rewards: { mutating: true, bundleable: true },\n volo_stake: { mutating: true, requiresBalance: true, bundleable: true },\n volo_unstake: { mutating: true, bundleable: true },\n\n // Write tools — pay / services (NOT bundleable — see ToolFlags.bundleable JSDoc)\n pay_api: { mutating: true, requiresBalance: true, costAware: true, producesArtifact: true, maxRetries: 1 },\n\n // Write tools — lightweight (no financial guards, NOT bundleable — Postgres only)\n save_contact: {},\n\n // [SIMPLIFICATION DAY 7] Removed flag entries for deleted tools:\n // create_schedule, cancel_schedule (DCA schedules retired)\n // toggle_allowance, update_daily_limit, update_permissions (allowance dormant)\n\n // Receive tools — create/cancel mutate server state\n create_payment_link: { mutating: true },\n cancel_payment_link: { mutating: true },\n create_invoice: { mutating: true },\n cancel_invoice: { mutating: true },\n};\n\n/**\n * Apply flags from the central registry to a tool array.\n * Tools not in the registry get empty flags (read-only tools).\n */\nexport function applyToolFlags<T extends Tool>(tools: T[]): T[] {\n return tools.map((tool) => {\n const flags = TOOL_FLAGS[tool.name];\n if (!flags) return tool;\n return { ...tool, flags: { ...tool.flags, ...flags } };\n });\n}\n\n/**\n * Get flags for a tool by name. Returns empty flags if not registered.\n */\nexport function getToolFlags(name: string): ToolFlags {\n return TOOL_FLAGS[name] ?? {};\n}\n\n/**\n * [SPEC 7 P2.5 Layer 4] True if this tool is in the v1 bundleable set.\n *\n * Used by the recipe loader's `bundle: true` validation — recipes that\n * declare `bundle: true` on a step MUST point to a tool that returns\n * `true` here. The set is the 9 confirm-tier write tools whose on-chain\n * effect is fully expressible at compose time:\n *\n * save_deposit, withdraw, borrow, repay_debt, send_transfer,\n * swap_execute, claim_rewards, volo_stake, volo_unstake.\n */\nexport function isBundleableTool(name: string): boolean {\n return TOOL_FLAGS[name]?.bundleable === true;\n}\n","import type { McpServerConfig } from './mcp-client.js';\n\n// ---------------------------------------------------------------------------\n// NAVI MCP server configuration\n// ---------------------------------------------------------------------------\n\nexport const NAVI_SERVER_NAME = 'navi';\nexport const NAVI_MCP_URL = 'https://open-api.naviprotocol.io/api/mcp';\n\nexport const NAVI_MCP_CONFIG: McpServerConfig = {\n name: NAVI_SERVER_NAME,\n url: NAVI_MCP_URL,\n transport: 'streamable-http',\n cacheTtlMs: 30_000,\n readOnly: true,\n};\n\n// ---------------------------------------------------------------------------\n// NAVI MCP tool name constants (as observed from live discovery)\n// ---------------------------------------------------------------------------\n\nexport const NaviTools = {\n GET_POOLS: 'navi_get_pools',\n GET_POOL: 'navi_get_pool',\n GET_PROTOCOL_STATS: 'navi_get_protocol_stats',\n GET_HEALTH_FACTOR: 'navi_get_health_factor',\n GET_BORROW_FEE: 'navi_get_borrow_fee',\n GET_FEES: 'navi_get_fees',\n GET_FLASH_LOAN_ASSETS: 'navi_get_flash_loan_assets',\n GET_FLASH_LOAN_ASSET: 'navi_get_flash_loan_asset',\n GET_LENDING_REWARDS: 'navi_get_lending_rewards',\n GET_AVAILABLE_REWARDS: 'navi_get_available_rewards',\n GET_PRICE_FEEDS: 'navi_get_price_feeds',\n GET_SWAP_QUOTE: 'navi_get_swap_quote',\n GET_BRIDGE_CHAINS: 'navi_get_bridge_chains',\n SEARCH_BRIDGE_TOKENS: 'navi_search_bridge_tokens',\n GET_BRIDGE_QUOTE: 'navi_get_bridge_quote',\n GET_BRIDGE_TX_STATUS: 'navi_get_bridge_tx_status',\n GET_BRIDGE_HISTORY: 'navi_get_bridge_history',\n GET_DCA_ORDERS: 'navi_get_dca_orders',\n GET_DCA_ORDER_DETAILS: 'navi_get_dca_order_details',\n LIST_DCA_ORDERS: 'navi_list_dca_orders',\n GET_COINS: 'navi_get_coins',\n GET_MARKET_CONFIG: 'navi_get_market_config',\n GET_POSITIONS: 'get_positions',\n GET_TRANSACTION: 'sui_get_transaction',\n EXPLAIN_TRANSACTION: 'sui_explain_transaction',\n SEARCH_TOKENS: 'navi_search_tokens',\n} as const;\n","import type { T2000 } from '@t2000/sdk';\nimport type { McpClientManager } from '../mcp-client.js';\nimport { NAVI_SERVER_NAME } from '../navi-config.js';\nimport type { ToolContext } from '../types.js';\n\nexport function hasAgent(context: ToolContext): boolean {\n return !!context.agent;\n}\n\nexport function requireAgent(context: ToolContext): T2000 {\n if (!context.agent) {\n throw new Error(\n 'Tool requires a T2000 agent instance — pass `agent` in EngineConfig',\n );\n }\n return context.agent as T2000;\n}\n\n/**\n * Check if context has an MCP manager with a connected NAVI server\n * and a wallet address for address-dependent reads.\n */\nexport function hasNaviMcp(context: ToolContext): boolean {\n if (!context.mcpManager || !context.walletAddress) return false;\n const mgr = context.mcpManager as McpClientManager;\n return mgr.isConnected(NAVI_SERVER_NAME);\n}\n\n/**\n * Check if context has a connected NAVI MCP (no wallet required).\n * Use for global reads like rates/pools that don't depend on a user address.\n */\nexport function hasNaviMcpGlobal(context: ToolContext): boolean {\n if (!context.mcpManager) return false;\n const mgr = context.mcpManager as McpClientManager;\n return mgr.isConnected(NAVI_SERVER_NAME);\n}\n\n/**\n * Get the MCP client manager from context (assumes hasNaviMcp() is true).\n */\nexport function getMcpManager(context: ToolContext): McpClientManager {\n return context.mcpManager as McpClientManager;\n}\n\n/**\n * Get the wallet address from context (assumes hasNaviMcp() is true).\n */\nexport function getWalletAddress(context: ToolContext): string {\n return context.walletAddress!;\n}\n","import { getDecimalsForCoinType } from '@t2000/sdk';\n\n// ---------------------------------------------------------------------------\n// Raw NAVI MCP response types (as returned by the live NAVI MCP server)\n// ---------------------------------------------------------------------------\n\nexport interface NaviRawPool {\n id: number;\n symbol: string;\n coinType: string;\n price: string;\n market: string;\n ltv: number;\n liquidation: {\n bonus: string;\n ratio: string;\n threshold: string;\n };\n supply: string;\n borrow: string;\n supplyApy: string;\n borrowApy: string;\n}\n\nexport interface NaviRawPosition {\n id: string;\n protocol: string;\n type: string;\n market: string;\n tokenASymbol: string;\n tokenAPrice: number;\n amountA: string;\n tokenBSymbol?: string | null;\n tokenBPrice?: number | null;\n amountB?: string | null;\n valueUSD: string;\n apr: string;\n liquidationThreshold: string;\n lowerPrice?: string | null;\n upperPrice?: string | null;\n currentPrice?: string | null;\n claimableRewards?: string | null;\n isActive?: boolean;\n}\n\nexport interface NaviRawPositionsResponse {\n address: string;\n positions: NaviRawPosition[];\n}\n\nexport interface NaviRawHealthFactor {\n address: string;\n healthFactor: number | null;\n}\n\nexport interface NaviRawCoin {\n coinType: string;\n totalBalance: string;\n coinObjectCount: number;\n symbol?: string;\n decimals?: number;\n}\n\nexport interface NaviRawRewardsResponse {\n address: string;\n rewards: Array<{\n pool?: string;\n rewardType?: string;\n amount?: string;\n symbol?: string;\n valueUsd?: number;\n }>;\n summary: Array<{\n symbol: string;\n totalAmount: string;\n valueUSD?: string;\n }>;\n}\n\nexport interface NaviRawProtocolStats {\n tvl: number;\n totalBorrowUsd: number;\n averageUtilization: number;\n maxApy: number;\n userAmount: number;\n interactionUserAmount: number;\n borrowFee: number;\n}\n\n// ---------------------------------------------------------------------------\n// Transformed engine-friendly types\n// ---------------------------------------------------------------------------\n\nexport interface RatesResult {\n [symbol: string]: {\n saveApy: number;\n borrowApy: number;\n ltv: number;\n price: number;\n };\n}\n\nexport interface HealthFactorResult {\n healthFactor: number;\n supplied: number;\n borrowed: number;\n maxBorrow: number;\n liquidationThreshold: number;\n}\n\nexport interface BalanceResult {\n available: number;\n savings: number;\n debt: number;\n pendingRewards: number;\n gasReserve: number;\n total: number;\n stables: number;\n}\n\nexport interface PositionEntry {\n protocol: string;\n type: 'supply' | 'borrow';\n symbol: string;\n amount: number;\n valueUsd: number;\n apy: number;\n liquidationThreshold: number;\n}\n\nexport interface SavingsResult {\n positions: PositionEntry[];\n earnings: {\n totalYieldEarned: number;\n currentApy: number;\n dailyEarning: number;\n supplied: number;\n };\n fundStatus: {\n supplied: number;\n apy: number;\n earnedToday: number;\n earnedAllTime: number;\n projectedMonthly: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Safe number parser — handles strings, numbers, null, undefined\n// ---------------------------------------------------------------------------\n\nfunction toNum(v: unknown): number {\n if (v == null) return 0;\n const n = typeof v === 'number' ? v : Number(v);\n return Number.isFinite(n) ? n : 0;\n}\n\n// ---------------------------------------------------------------------------\n// Transform: pools → rates\n// ---------------------------------------------------------------------------\n\nexport function transformRates(raw: unknown): RatesResult {\n const pools = Array.isArray(raw) ? (raw as NaviRawPool[]) : [];\n const result: RatesResult = {};\n\n for (const pool of pools) {\n if (!pool.symbol) continue;\n result[pool.symbol] = {\n saveApy: toNum(pool.supplyApy) / 100,\n borrowApy: toNum(pool.borrowApy) / 100,\n ltv: toNum(pool.ltv),\n price: toNum(pool.price),\n };\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Transform: positions → typed PositionEntry[]\n// ---------------------------------------------------------------------------\n\n// NAVI MCP divides ALL position amounts by 10^9 (original storage precision),\n// but newer pools (id > 10) store at the token's native decimals. For 6-decimal\n// stablecoins in newer pools, this makes amounts 1000x too small.\n// Correction factor: 10^(9 - 6) = 1000.\n// Remove this map if/when the NAVI MCP fixes pool-aware decimal handling.\nconst NAVI_NEWER_POOL_SYMBOLS = new Set([\n 'USDSUI', 'USDsui',\n 'SUI_USDE', 'suiUSDe', 'USDe',\n 'suiUSDT',\n]);\nconst NEWER_POOL_FACTOR = 1000;\n\nfunction naviDecimalFactor(symbol: string): number {\n return NAVI_NEWER_POOL_SYMBOLS.has(symbol) ? NEWER_POOL_FACTOR : 1;\n}\n\nexport function transformPositions(raw: unknown): PositionEntry[] {\n const data = raw as NaviRawPositionsResponse | undefined;\n const positions = data?.positions ?? (Array.isArray(raw) ? (raw as NaviRawPosition[]) : []);\n\n return positions.map((p) => {\n const symbol = p.tokenASymbol ?? 'UNKNOWN';\n const factor = naviDecimalFactor(symbol);\n return {\n protocol: p.protocol ?? 'navi',\n type: p.type?.includes('borrow') ? ('borrow' as const) : ('supply' as const),\n symbol,\n amount: toNum(p.amountA) * factor,\n valueUsd: toNum(p.valueUSD) * factor,\n apy: toNum(p.apr) / 100,\n liquidationThreshold: toNum(p.liquidationThreshold),\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Transform: health factor (+ optional positions for enrichment)\n// ---------------------------------------------------------------------------\n\nexport function transformHealthFactor(\n rawHf: unknown,\n rawPositions?: unknown,\n): HealthFactorResult {\n const hf = rawHf as NaviRawHealthFactor | undefined;\n const positions = transformPositions(rawPositions);\n\n const supplied = positions\n .filter((p) => p.type === 'supply')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n const borrowed = positions\n .filter((p) => p.type === 'borrow')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n\n const supplyPositions = positions.filter((p) => p.type === 'supply');\n const weightedLt =\n supplied > 0\n ? supplyPositions.reduce(\n (acc, p) => acc + p.liquidationThreshold * p.valueUsd,\n 0,\n ) / supplied\n : 0;\n\n const maxBorrow = supplied * weightedLt - borrowed;\n\n return {\n healthFactor: toNum(hf?.healthFactor) || (borrowed === 0 ? Infinity : 0),\n supplied,\n borrowed,\n maxBorrow: Math.max(0, maxBorrow),\n liquidationThreshold: weightedLt,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Transform: rewards → typed reward summaries\n// ---------------------------------------------------------------------------\n\nexport interface PendingReward {\n symbol: string;\n totalAmount: number;\n valueUsd: number;\n}\n\nexport function transformRewards(raw: unknown): PendingReward[] {\n const data = raw as NaviRawRewardsResponse | undefined;\n return (data?.summary ?? []).map((s) => ({\n symbol: s.symbol ?? 'UNKNOWN',\n totalAmount: toNum(s.totalAmount),\n valueUsd: toNum(s.valueUSD),\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Transform: coins + positions + rewards → balance breakdown\n// Requires `prices` map (symbol → USD price) for proper cross-currency totals.\n// ---------------------------------------------------------------------------\n\nconst STABLECOIN_SYMBOLS = new Set([\n 'USDC', 'USDT', 'USDe', 'USDsui', 'wUSDC', 'wUSDT', 'suiUSDe', 'USDSUI',\n]);\n\nconst GAS_RESERVE_SUI = 0.05;\n\nexport interface BalancePrices {\n [symbol: string]: number;\n}\n\nexport function transformBalance(\n rawCoins: unknown,\n rawPositions: unknown,\n rawRewards: unknown,\n prices?: BalancePrices,\n): BalanceResult {\n const coins = Array.isArray(rawCoins) ? (rawCoins as NaviRawCoin[]) : [];\n const positions = transformPositions(rawPositions);\n const rewards = transformRewards(rawRewards);\n\n let availableUsd = 0;\n let stablesUsd = 0;\n let gasReserveUsd = 0;\n\n for (const coin of coins) {\n const symbol = coin.symbol ?? '';\n const decimals = coin.decimals ?? getDecimalsForCoinType(coin.coinType ?? '');\n const balance = toNum(coin.totalBalance) / 10 ** decimals;\n const price = prices?.[symbol] ?? (STABLECOIN_SYMBOLS.has(symbol) ? 1 : 0);\n\n if (symbol === 'SUI' || coin.coinType === '0x2::sui::SUI') {\n const reserveAmount = Math.min(balance, GAS_RESERVE_SUI);\n gasReserveUsd = reserveAmount * price;\n availableUsd += (balance - reserveAmount) * price;\n } else {\n availableUsd += balance * price;\n if (STABLECOIN_SYMBOLS.has(symbol)) {\n stablesUsd += balance * price;\n }\n }\n }\n\n const savings = positions\n .filter((p) => p.type === 'supply')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n const debt = positions\n .filter((p) => p.type === 'borrow')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n\n const pendingRewardsUsd = rewards.reduce((sum, r) => sum + r.valueUsd, 0);\n\n return {\n available: availableUsd,\n savings,\n debt,\n pendingRewards: pendingRewardsUsd,\n gasReserve: gasReserveUsd,\n total: availableUsd + savings + gasReserveUsd + pendingRewardsUsd - debt,\n stables: stablesUsd,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Transform: positions + pools → savings info\n// ---------------------------------------------------------------------------\n\nexport function transformSavings(\n rawPositions: unknown,\n rawPools: unknown,\n): SavingsResult {\n const positions = transformPositions(rawPositions);\n const rates = transformRates(rawPools);\n\n const supplyPositions = positions.filter((p) => p.type === 'supply');\n const supplied = supplyPositions.reduce((sum, p) => sum + p.valueUsd, 0);\n\n const weightedApy =\n supplied > 0\n ? supplyPositions.reduce(\n (acc, p) => acc + (rates[p.symbol]?.saveApy ?? p.apy) * p.valueUsd,\n 0,\n ) / supplied\n : 0;\n\n const dailyEarning = (supplied * weightedApy) / 365;\n const projectedMonthly = dailyEarning * 30;\n\n return {\n positions,\n earnings: {\n totalYieldEarned: 0, // not available from MCP reads alone\n currentApy: weightedApy,\n dailyEarning,\n supplied,\n },\n fundStatus: {\n supplied,\n apy: weightedApy,\n earnedToday: dailyEarning,\n earnedAllTime: 0, // not available from MCP reads alone\n projectedMonthly,\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers: extract text content from MCP response\n// ---------------------------------------------------------------------------\n\nexport function extractMcpText(\n content: Array<{ type: string; text?: string; [key: string]: unknown }>,\n): string {\n return content\n .filter((c) => c.type === 'text' && c.text)\n .map((c) => c.text!)\n .join('\\n');\n}\n\nexport function parseMcpJson<T = unknown>(\n content: Array<{ type: string; text?: string; [key: string]: unknown }>,\n): T {\n const text = extractMcpText(content);\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n}\n","// ---------------------------------------------------------------------------\n// Direct Sui JSON-RPC coin fetcher — no SDK dependency required.\n// Uses suix_getAllBalances to get wallet coin balances.\n// ---------------------------------------------------------------------------\n\nimport { getDecimalsForCoinType, resolveSymbol } from '@t2000/sdk';\n\nconst SUI_MAINNET_URL = 'https://fullnode.mainnet.sui.io:443';\n\nexport interface SuiCoinBalance {\n coinType: string;\n totalBalance: string;\n coinObjectCount: number;\n}\n\n/** Supplementary coins not in the SDK registry (legacy/wrapped variants). */\nconst EXTRA_COINS: Record<string, { symbol: string; decimals: number }> = {\n '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN': { symbol: 'USDT', decimals: 6 },\n};\n\nexport interface WalletCoin {\n coinType: string;\n symbol: string;\n decimals: number;\n totalBalance: string;\n coinObjectCount: number;\n}\n\n/**\n * Fetch all coin balances for an address directly from the Sui JSON-RPC.\n * Returns enriched objects with known symbol/decimals where possible.\n */\nexport async function fetchWalletCoins(\n address: string,\n rpcUrl?: string,\n): Promise<WalletCoin[]> {\n const url = rpcUrl || SUI_MAINNET_URL;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_getAllBalances',\n params: [address],\n }),\n signal: AbortSignal.timeout(8_000),\n });\n\n if (!res.ok) {\n throw new Error(`Sui RPC error: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as {\n result?: SuiCoinBalance[];\n error?: { message: string };\n };\n\n if (json.error) {\n throw new Error(`Sui RPC error: ${json.error.message}`);\n }\n\n const balances = json.result ?? [];\n\n return balances.map((b) => {\n const extra = EXTRA_COINS[b.coinType];\n const symbol = extra?.symbol ?? resolveSymbol(b.coinType);\n const decimals = extra?.decimals ?? getDecimalsForCoinType(b.coinType);\n return {\n coinType: b.coinType,\n symbol,\n decimals,\n totalBalance: b.totalBalance,\n coinObjectCount: b.coinObjectCount,\n };\n });\n}\n","// ---------------------------------------------------------------------------\n// DefiCacheStore — pluggable cache backend for `fetchAddressDefiPortfolio`\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// Pre-v0.54 the DeFi cache was a process-local `Map<string, DefiCacheEntry>`\n// inside `blockvision-prices.ts`. That worked for the CLI and for\n// single-instance dev servers, but it broke the SSOT promise on Vercel\n// where every API route runs in its own serverless function with its own\n// process. Three readers (`balance_check` tool, `/api/portfolio` route,\n// `/api/analytics/portfolio-history` route) running on three Vercel\n// instances produced three independent cache states for the same address,\n// so during a BlockVision burst the user saw three different totals on the\n// same chat turn (e.g. $36,991 from balance_check, $36,992 from the\n// timeline canvas, $29,514 from the full-portfolio canvas). This is the\n// exact divergence the SSOT refactor was meant to eliminate.\n//\n// The fix\n// -------\n// `fetchAddressDefiPortfolio` now reads/writes through this `DefiCacheStore`\n// interface. The default `InMemoryDefiCacheStore` preserves the legacy\n// behavior for the CLI / tests / dev. Audric injects an Upstash-backed\n// implementation at engine init so all routes/instances share one cache.\n//\n// Sticky-positive write semantics live in the FETCHER (not the store) so\n// the store stays a dumb key-value with TTL. That keeps the contract small\n// and lets callers swap stores freely without re-implementing policy.\n//\n// Stale tolerance\n// ---------------\n// The store TTL is the **sticky window** (default 30 minutes), not the\n// fresh-data window. Freshness is computed by the fetcher from the entry's\n// `pricedAt` against source-specific thresholds:\n// - `blockvision` — fresh for 60s → fully successful, trust it\n// - `partial` — fresh for 15s → some protocols 429'd, retry sooner\n// - `partial-stale` — fresh for 0s → always re-fetch in the background\n// - `degraded` — never cached → no value to serve\n// If a fresh fetch returns degraded/partial-zero, the fetcher serves the\n// last positive cached value (up to 30 minutes old) marked as\n// `partial-stale` — \"this is the most recent real number we've seen, but\n// BlockVision is currently unreachable, so the canvas/UI can decide\n// whether to render it as-is or with a 'last refresh Nm ago' caveat.\"\n// ---------------------------------------------------------------------------\n\nimport type { DefiSummary } from './blockvision-prices.js';\n\n/** Cache entry stored under each address key. */\nexport interface DefiCacheEntry {\n data: DefiSummary;\n /** Wall-clock ms when this was written — used by the fetcher to compute freshness. */\n pricedAt: number;\n}\n\n/**\n * Pluggable cache backend.\n *\n * All methods are async because Redis-backed implementations are\n * inherently async; the in-memory impl wraps in resolved promises.\n *\n * Implementations MUST tolerate transport errors gracefully — `get`\n * should return `null` (not throw) on backend failure so the fetcher\n * falls through to a fresh BlockVision read instead of erroring the\n * whole `balance_check` call. `set` should swallow errors (logging is\n * fine) so a Redis hiccup doesn't break a successful read.\n */\nexport interface DefiCacheStore {\n /** Returns the cached entry, or `null` if not found / expired / backend error. */\n get(address: string): Promise<DefiCacheEntry | null>;\n\n /** Writes an entry with a TTL in seconds. Errors are swallowed (logged). */\n set(address: string, entry: DefiCacheEntry, ttlSec: number): Promise<void>;\n\n /** Removes the entry for an address. Errors are swallowed. */\n delete(address: string): Promise<void>;\n\n /** Removes all entries. Used by tests and `clearDefiCache()`. */\n clear(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\n/**\n * Process-local cache backed by a `Map`. Used as the default when no\n * other store has been injected via `setDefiCacheStore()`.\n *\n * NOT suitable for multi-instance deployments — each Vercel function\n * instance gets its own Map, which causes the SSOT divergence this\n * module exists to fix. Audric replaces this at engine init with an\n * Upstash-backed store; the CLI keeps it.\n */\nexport class InMemoryDefiCacheStore implements DefiCacheStore {\n private readonly store = new Map<string, { entry: DefiCacheEntry; expiresAt: number }>();\n\n async get(address: string): Promise<DefiCacheEntry | null> {\n const slot = this.store.get(address.toLowerCase());\n if (!slot) return null;\n if (Date.now() >= slot.expiresAt) {\n this.store.delete(address.toLowerCase());\n return null;\n }\n return slot.entry;\n }\n\n async set(address: string, entry: DefiCacheEntry, ttlSec: number): Promise<void> {\n this.store.set(address.toLowerCase(), {\n entry,\n expiresAt: Date.now() + ttlSec * 1000,\n });\n }\n\n async delete(address: string): Promise<void> {\n this.store.delete(address.toLowerCase());\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeStore: DefiCacheStore = new InMemoryDefiCacheStore();\n\n/**\n * Swap the active DeFi cache store. Call once at engine init from a\n * runtime that wants a non-default backend (e.g. Audric injecting\n * `RedisDefiCacheStore`). Idempotent — calling again replaces the\n * previous store, but does NOT migrate entries; warm cache is lost\n * on swap. Tests use this to inject a fake/spy store and `resetDefiCacheStore()`\n * to restore the in-memory default.\n */\nexport function setDefiCacheStore(store: DefiCacheStore): void {\n activeStore = store;\n}\n\n/** Returns the currently active store. Used by `fetchAddressDefiPortfolio`. */\nexport function getDefiCacheStore(): DefiCacheStore {\n return activeStore;\n}\n\n/** Restore the default in-memory store. Used by test teardowns. */\nexport function resetDefiCacheStore(): void {\n activeStore = new InMemoryDefiCacheStore();\n}\n","// ---------------------------------------------------------------------------\n// WalletCacheStore — pluggable cache backend for `fetchAddressPortfolio`\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// Pre-v0.55 the wallet portfolio cache was a process-local\n// `Map<string, PortfolioCacheEntry>` inside `blockvision-prices.ts`.\n// That mirrored the pre-v0.54 DeFi situation exactly: it worked for\n// the CLI and single-instance dev servers but broke the SSOT promise\n// on Vercel where every API route runs in its own serverless function\n// with its own process. `/api/portfolio` and `balance_check` could\n// observe different wallet states for the same address during a\n// BlockVision 429 burst — one route had a healthy cache hit, another\n// freshly degraded to `sui-rpc-degraded` (which can't price\n// non-stables), so the same chat turn rendered different totals on\n// different cards.\n//\n// PR 1+2 of the scaling spec closes the loop by mirroring the v0.54\n// DeFi cache pattern verbatim. The default `InMemoryWalletCacheStore`\n// preserves the legacy behavior for the CLI / tests / dev. Audric\n// injects an Upstash-backed implementation at engine init so all\n// routes/instances share one cache.\n//\n// Sticky-positive write semantics live in the FETCHER (not the store)\n// so the store stays a dumb key-value with TTL. That keeps the\n// contract small and lets callers swap stores freely without\n// re-implementing policy.\n//\n// Stale tolerance\n// ---------------\n// The store TTL is the **sticky window** (default 30 minutes), not\n// the fresh-data window. Freshness is computed by the fetcher from\n// the entry's `pricedAt` against source-specific thresholds:\n// - `blockvision` — fresh for 60s → fully successful, trust it\n// - `sui-rpc-degraded` — fresh for 15s → BV unavailable, retry sooner\n// If a fresh fetch returns `sui-rpc-degraded`, the fetcher serves the\n// last positive `blockvision` value (up to 30 minutes old) instead of\n// overwriting — same sticky-positive contract as DeFi. The cache\n// entry's `pricedAt` is preserved so a UI consumer can render\n// \"last refresh Nm ago\" if it wants to caveat the staleness.\n// ---------------------------------------------------------------------------\n\nimport type { AddressPortfolio } from './blockvision-prices.js';\n\n/** Cache entry stored under each address key. */\nexport interface WalletCacheEntry {\n data: AddressPortfolio;\n /**\n * Wall-clock ms when this entry was WRITTEN to the cache — used by\n * the fetcher to compute freshness.\n *\n * Distinct from `data.pricedAt` (the upstream-data timestamp from\n * BlockVision / Sui RPC). Mirrors `DefiCacheEntry.pricedAt` for\n * cross-pattern consistency.\n */\n pricedAt: number;\n}\n\n/**\n * Pluggable cache backend.\n *\n * All methods are async because Redis-backed implementations are\n * inherently async; the in-memory impl wraps in resolved promises.\n *\n * Implementations MUST tolerate transport errors gracefully — `get`\n * should return `null` (not throw) on backend failure so the fetcher\n * falls through to a fresh BlockVision read instead of erroring the\n * whole `balance_check` call. `set` should swallow errors (logging is\n * fine) so a Redis hiccup doesn't break a successful read.\n */\nexport interface WalletCacheStore {\n /** Returns the cached entry, or `null` if not found / expired / backend error. */\n get(address: string): Promise<WalletCacheEntry | null>;\n\n /** Writes an entry with a TTL in seconds. Errors are swallowed (logged). */\n set(address: string, entry: WalletCacheEntry, ttlSec: number): Promise<void>;\n\n /** Removes the entry for an address. Errors are swallowed. */\n delete(address: string): Promise<void>;\n\n /** Removes all entries. Used by tests and `clearPortfolioCache()`. */\n clear(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\n/**\n * Process-local cache backed by a `Map`. Used as the default when no\n * other store has been injected via `setWalletCacheStore()`.\n *\n * NOT suitable for multi-instance deployments — each Vercel function\n * instance gets its own Map, which causes the SSOT divergence this\n * module exists to fix. Audric replaces this at engine init with an\n * Upstash-backed store; the CLI and MCP server keep it.\n *\n * Address normalization: keys are lowercased to match the\n * `UpstashWalletCacheStore.key()` convention. Sui addresses are\n * case-insensitive after the `0x` prefix in practice; keying by\n * lowercase prevents accidental cache misses from `0xABC...` vs\n * `0xabc...` callers (e.g. one route normalizes, another doesn't).\n */\nexport class InMemoryWalletCacheStore implements WalletCacheStore {\n private readonly store = new Map<string, { entry: WalletCacheEntry; expiresAt: number }>();\n\n async get(address: string): Promise<WalletCacheEntry | null> {\n const slot = this.store.get(address.toLowerCase());\n if (!slot) return null;\n if (Date.now() >= slot.expiresAt) {\n this.store.delete(address.toLowerCase());\n return null;\n }\n return slot.entry;\n }\n\n async set(address: string, entry: WalletCacheEntry, ttlSec: number): Promise<void> {\n this.store.set(address.toLowerCase(), {\n entry,\n expiresAt: Date.now() + ttlSec * 1000,\n });\n }\n\n async delete(address: string): Promise<void> {\n this.store.delete(address.toLowerCase());\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeStore: WalletCacheStore = new InMemoryWalletCacheStore();\n\n/**\n * Swap the active wallet cache store. Call once at engine init from a\n * runtime that wants a non-default backend (e.g. Audric injecting\n * `UpstashWalletCacheStore`). Idempotent — calling again replaces the\n * previous store, but does NOT migrate entries; warm cache is lost on\n * swap. Tests use this to inject a fake/spy store and\n * `resetWalletCacheStore()` to restore the in-memory default.\n */\nexport function setWalletCacheStore(store: WalletCacheStore): void {\n activeStore = store;\n}\n\n/** Returns the currently active store. Used by `fetchAddressPortfolio`. */\nexport function getWalletCacheStore(): WalletCacheStore {\n return activeStore;\n}\n\n/** Restore the default in-memory store. Used by test teardowns. */\nexport function resetWalletCacheStore(): void {\n activeStore = new InMemoryWalletCacheStore();\n}\n","// ---------------------------------------------------------------------------\n// FetchLock — pluggable cross-instance request coalescing\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// Even with v0.54's shared DeFi cache and v0.55's shared wallet cache,\n// when N concurrent Vercel instances all miss the cache for the same\n// address at the same instant, all N independently fire the BlockVision\n// portfolio call AND the 9-protocol DeFi fan-out. At 200 concurrent\n// users with one popular shared address (e.g. a treasury everyone is\n// watching), a single cache-miss instant produces 200 × 10 = 2000 BV\n// calls in <1 second — self-inflicted DoS.\n//\n// `defiInflight` and `portfolioInflight` Maps coalesce WITHIN a process,\n// but every Vercel instance is its own process. We need a CROSS-process\n// coalescer.\n//\n// The contract\n// ------------\n// `awaitOrFetch(key, fetcher, opts)`:\n// 1. Try `lock.acquire(key, leaseSec)` — backed by Upstash `SET NX EX`\n// in production, in-memory Map in CLI/tests/dev.\n// 2. **Lock acquired** → run `fetcher()` (which writes the cache as\n// its last act), then `release()`. Cache write is the signal —\n// no separate pub/sub channel needed.\n// 3. **Lock NOT acquired** → another instance is fetching. Poll\n// `opts.pollCache()` every ~100ms (jittered) for up to\n// `pollBudgetMs`. If cache fills → return that. If timeout →\n// fall through to a direct `fetcher()` call (defensive degraded\n// path; never block forever on a phantom lock).\n//\n// Lease sizing\n// ------------\n// Default lease is **15 seconds**, sized for the worst-case\n// `fetchBlockVisionWithRetry` budget:\n// - 3 HTTP attempts × 4s timeout = 12s\n// - + backoff sleeps 250ms + 750ms = 1s\n// - Total ≈ 13s\n// A shorter lease (e.g. 5s) expires mid-fetch under load, the leader\n// loses the lock, a follower acquires it, and now 2 instances are\n// fetching the same address — exactly the amplification we exist to\n// prevent. We never extend; if a process dies, the lease expires and\n// the next caller takes over.\n//\n// Default poll budget is **4.5 seconds** — must be < the engine's\n// per-tool timeout (typically 5s for `balance_check` /\n// `portfolio_analysis`) so a dead leader doesn't cascade into a tool\n// timeout for every follower. 4.5s × 100ms poll = ≤45 cheap GETs per\n// follower per coalesced fan-out.\n//\n// Implementation note: store transport errors are swallowed and the\n// caller falls through to `fetcher()` (i.e. degrades to per-instance\n// fetching). A Redis outage should never break a successful read.\n// ---------------------------------------------------------------------------\n\n/**\n * Pluggable distributed mutex. Implementations MUST tolerate transport\n * errors gracefully — `acquire` returning `false` (not throwing) on\n * backend failure is fine; the caller will fall through to a direct\n * fetch. The Upstash impl uses `SET NX EX` which is the canonical\n * Redis distributed-lock primitive at this scale.\n */\nexport interface FetchLock {\n /**\n * Try to acquire the lock for `key`, with an automatic expiry of\n * `leaseSec` seconds.\n *\n * Returns `true` if acquired (caller is now the leader for that key,\n * MUST call `release` when done). Returns `false` if the lock is\n * already held by someone else (caller is a follower).\n *\n * Errors are swallowed (logged); on backend failure return `false`\n * so the caller falls through to its degraded direct-fetch path.\n */\n acquire(key: string, leaseSec: number): Promise<boolean>;\n\n /**\n * Release the lock for `key`. Idempotent — calling on a key the\n * caller doesn't hold is a no-op (we accept a small window of\n * potential ABA: if our lease expired and another caller took the\n * key, we'll harmlessly delete THEIR lock once. Production traffic\n * patterns make this exceedingly rare; the cost is one extra\n * fan-out, which is the same cost we'd pay anyway under contention.)\n *\n * Errors are swallowed (logged) — release failures are non-fatal\n * because the lease expires on its own.\n */\n release(key: string): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\n/**\n * Process-local mutex backed by a `Map<key, expiryMs>`. Used as the\n * default when no other lock has been injected via `setFetchLock()`.\n *\n * NOT suitable for multi-instance deployments — each Vercel function\n * instance gets its own Map, which means N concurrent instances all\n * acquire successfully and all fan out to BlockVision. Audric replaces\n * this at engine init with `UpstashFetchLock`; the CLI keeps it\n * (single-process, so process-local is correct).\n */\nexport class InMemoryFetchLock implements FetchLock {\n private readonly held = new Map<string, number>();\n\n async acquire(key: string, leaseSec: number): Promise<boolean> {\n const now = Date.now();\n const expiry = this.held.get(key);\n if (expiry !== undefined && expiry > now) return false;\n this.held.set(key, now + leaseSec * 1000);\n return true;\n }\n\n async release(key: string): Promise<void> {\n this.held.delete(key);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeLock: FetchLock = new InMemoryFetchLock();\n\n/**\n * Swap the active fetch lock backend. Call once at engine init from a\n * runtime that wants a non-default backend (e.g. Audric injecting\n * `UpstashFetchLock`). Idempotent — calling again replaces the previous\n * lock instance, but does NOT migrate held leases (which are stored in\n * the backend, not the lock object).\n */\nexport function setFetchLock(lock: FetchLock): void {\n activeLock = lock;\n}\n\n/** Returns the currently active lock. Used by `awaitOrFetch`. */\nexport function getFetchLock(): FetchLock {\n return activeLock;\n}\n\n/** Restore the default in-memory lock. Used by test teardowns. */\nexport function resetFetchLock(): void {\n activeLock = new InMemoryFetchLock();\n}\n\n// ---------------------------------------------------------------------------\n// awaitOrFetch — the high-level coalescing primitive\n// ---------------------------------------------------------------------------\n\n/** Default lease seconds — sized for worst-case BV retry budget. See header. */\nexport const DEFAULT_LEASE_SEC = 15;\n\n/** Default follower poll budget ms — must be < engine per-tool timeout. */\nexport const DEFAULT_POLL_BUDGET_MS = 4_500;\n\n/** Default poll interval ms (jittered ±20%) — ~45 GETs over 4.5s. */\nexport const DEFAULT_POLL_INTERVAL_MS = 100;\n\nexport interface AwaitOrFetchOpts<T> {\n /** Override the active lock instance (test seam). */\n lock?: FetchLock;\n /** Lease seconds for `lock.acquire`. Default 15. */\n leaseSec?: number;\n /** Total ms a follower will poll the cache before falling through. Default 4500. */\n pollBudgetMs?: number;\n /** Poll cadence ms (jittered ±20%). Default 100. */\n pollIntervalMs?: number;\n /**\n * Optional cache reader for followers. If provided, followers poll\n * this every `pollIntervalMs` (jittered) until it returns non-null\n * or the budget is exhausted. If omitted, followers fall through\n * immediately to a direct `fetcher()` call (no coalescing benefit).\n *\n * The follower's \"is this fresh enough?\" decision lives inside this\n * callback — it should return `null` when the cache entry exists but\n * is too stale to serve, so the poll keeps trying.\n */\n pollCache?: () => Promise<T | null>;\n /** Test seam — defaults to `Math.random()`. */\n rng?: () => number;\n /** Test seam — defaults to `setTimeout`-backed promise. */\n sleep?: (ms: number) => Promise<void>;\n /** Test seam — defaults to `Date.now()`. */\n now?: () => number;\n /** Optional abort signal — caller cancellation halts polling. */\n signal?: AbortSignal;\n}\n\n/**\n * Cross-instance request coalescer.\n *\n * `key` MUST be stable across instances for the same logical fetch —\n * e.g. `bv-lock:wallet:0xabc...` for the wallet portfolio of `0xabc...`.\n * Different operations on the same address (wallet vs DeFi) MUST use\n * different keys so they don't block each other.\n *\n * `fetcher` is the leader's work. It SHOULD write the cache as its\n * last act, otherwise followers will time out and fall through to\n * direct fetches (functionally correct, just no coalescing benefit).\n *\n * The leader is guaranteed to call `release()` even if `fetcher()`\n * throws — propagated to the caller after release completes.\n *\n * Followers degrade to direct `fetcher()` on:\n * - lock backend failure (`acquire` threw or returned `false` due to a\n * transport error rather than contention)\n * - poll budget exhausted (leader didn't write cache, or wrote with\n * an old enough `pricedAt` that `pollCache` keeps returning `null`)\n * - no `pollCache` callback provided\n */\nexport async function awaitOrFetch<T>(\n key: string,\n fetcher: () => Promise<T>,\n opts: AwaitOrFetchOpts<T> = {},\n): Promise<T> {\n const lock = opts.lock ?? getFetchLock();\n const leaseSec = opts.leaseSec ?? DEFAULT_LEASE_SEC;\n const pollBudgetMs = opts.pollBudgetMs ?? DEFAULT_POLL_BUDGET_MS;\n const pollIntervalMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const rng = opts.rng ?? Math.random;\n const now = opts.now ?? Date.now;\n const sleep =\n opts.sleep ??\n ((ms: number) =>\n new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, ms);\n if (opts.signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n if (opts.signal.aborted) onAbort();\n else opts.signal.addEventListener('abort', onAbort, { once: true });\n }\n }));\n\n let acquired = false;\n try {\n acquired = await lock.acquire(key, leaseSec);\n } catch (err) {\n // Backend failure — degrade to direct fetch (no coalescing).\n console.warn(`[fetch-lock] acquire(${key}) threw; falling through to direct fetch:`, err);\n return fetcher();\n }\n\n if (acquired) {\n try {\n return await fetcher();\n } finally {\n try {\n await lock.release(key);\n } catch (err) {\n // Release failure is non-fatal — lease expires on its own.\n console.warn(`[fetch-lock] release(${key}) failed (non-fatal):`, err);\n }\n }\n }\n\n // ---------------------------------------------------------------\n // Follower path\n // ---------------------------------------------------------------\n // Without a pollCache there's no benefit to waiting — a follower\n // can't know when the leader is done. Fall through immediately.\n if (!opts.pollCache) {\n return fetcher();\n }\n\n const deadline = now() + pollBudgetMs;\n while (now() < deadline) {\n // Symmetric jitter ±20% so concurrent followers don't hammer\n // Redis on synchronized 100ms boundaries.\n const jitterPx = (rng() * 0.4 - 0.2) * pollIntervalMs;\n const wait = Math.max(0, pollIntervalMs + jitterPx);\n try {\n await sleep(wait);\n } catch (err) {\n // Caller cancelled mid-poll — propagate.\n if ((err as { name?: string })?.name === 'AbortError') throw err;\n // Anything else is a sleep impl bug; bail to direct fetch.\n return fetcher();\n }\n let cached: T | null = null;\n try {\n cached = await opts.pollCache();\n } catch (err) {\n // pollCache transport failure — log and keep polling, not the\n // caller's problem. Eventually the budget runs out and we fall\n // through to a direct fetch.\n console.warn(`[fetch-lock] pollCache(${key}) threw; continuing to poll:`, err);\n }\n if (cached !== null) return cached;\n }\n\n // Defensive degraded path: leader didn't fill the cache within the\n // poll budget. Could be a dead leader, a too-slow leader, or a\n // misconfigured pollCache that always returns null. Fetching\n // directly preserves correctness at the cost of one fan-out.\n return fetcher();\n}\n","// ---------------------------------------------------------------------------\n// TelemetrySink — pluggable observability backend for hot-path counters\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// PR 5 of the scaling spec adds structured counters/gauges/histograms to\n// the engine's hot paths (BlockVision retry, NAVI MCP, Anthropic usage).\n// The engine package has no runtime dependency on any observability vendor —\n// it can't import @vercel/analytics because it ships to the CLI and MCP\n// server which have no Vercel runtime. The solution is the same pluggable\n// injection pattern used for the cache stores:\n//\n// - Default `NoopSink` does nothing (zero overhead for CLI/MCP/tests).\n// - Audric injects `VercelTelemetrySink` at engine init, which writes\n// structured `console.log` lines (ingested by Vercel Observability)\n// and calls `track()` for discrete events (Vercel Analytics).\n//\n// The interface is intentionally minimal. We don't need full OTel-style\n// spans or trace IDs at 1k DAU — counters + histograms on the 10 key\n// metrics listed in the spec are enough to answer every incident question\n// this stack will face at this scale.\n//\n// Tag shape\n// ---------\n// Tags are flat key-value string pairs. This matches what both Vercel\n// Observability (structured log fields) and @vercel/analytics `track()`\n// natively consume. No nested objects, no arrays — keep it serializable.\n//\n// Naming convention (mirrors the spec counters table)\n// ---------------------------------------------------\n// bv.requests — BlockVision fetch attempts\n// bv.cache_hit — wallet/defi cache reads\n// bv.cb_open — circuit breaker state (gauge 0|1)\n// navi.requests — NAVI MCP call attempts\n// navi.cache_hit — NAVI cache reads\n// navi.cb_open — NAVI CB state (gauge 0|1)\n// anthropic.tokens — input/output/cache tokens\n// anthropic.latency_ms — per-turn latency (histogram)\n// upstash.requests — store operations\n// cron.fin_ctx_shard_duration_ms — shard processing time (histogram)\n// cron.fin_ctx_users_processed — users processed per shard\n// ---------------------------------------------------------------------------\n\n/** A flat tag bag. Values are strings for universal serialization. */\nexport type TelemetryTags = Record<string, string | number>;\n\n/**\n * Pluggable telemetry backend.\n *\n * All methods are fire-and-forget — implementations MUST NOT throw.\n * Swallow errors internally and optionally log a warning; the hot path\n * should never fail because an observability call failed.\n */\nexport interface TelemetrySink {\n /**\n * Increment a named counter by 1 (or `value` if supplied).\n * Used for discrete countable events: requests, errors, cache hits.\n */\n counter(name: string, tags?: TelemetryTags, value?: number): void;\n\n /**\n * Record the current value of a gauge.\n * Used for point-in-time measurements: circuit-breaker open (0|1),\n * queue depths, active connections.\n */\n gauge(name: string, value: number, tags?: TelemetryTags): void;\n\n /**\n * Record a distribution sample (latency, sizes).\n * Implementations may bucket, percentile, or just counter/average.\n */\n histogram(name: string, value: number, tags?: TelemetryTags): void;\n}\n\n// ---------------------------------------------------------------------------\n// No-op implementation — default for CLI, MCP, tests\n// ---------------------------------------------------------------------------\n\nclass NoopTelemetrySink implements TelemetrySink {\n counter(_name: string, _tags?: TelemetryTags, _value?: number): void {}\n gauge(_name: string, _value: number, _tags?: TelemetryTags): void {}\n histogram(_name: string, _value: number, _tags?: TelemetryTags): void {}\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeSink: TelemetrySink = new NoopTelemetrySink();\n\n/**\n * Swap the active telemetry sink. Call once at engine init from a runtime\n * that wants to emit real metrics (e.g. Audric injecting `VercelTelemetrySink`).\n * Idempotent — calling again replaces the previous sink. Tests can inject\n * a spy sink and use `resetTelemetrySink()` to restore the noop default.\n */\nexport function setTelemetrySink(sink: TelemetrySink): void {\n activeSink = sink;\n}\n\n/** Returns the currently active sink. Used by hot-path instrumentation. */\nexport function getTelemetrySink(): TelemetrySink {\n return activeSink;\n}\n\n/** Restore the default noop sink. Used by test teardowns. */\nexport function resetTelemetrySink(): void {\n activeSink = new NoopTelemetrySink();\n}\n","// ---------------------------------------------------------------------------\n// BlockVision Indexer REST API — wallet portfolio + multi-token price feed.\n//\n// Replaces the DefiLlama public price endpoint (`coins.llama.fi`) for both\n// `balance_check` (full portfolio) and `portfolio_analysis` /\n// `engine-factory` prompt-time price seeding (multi-token quotes).\n//\n// Two endpoints are wrapped here:\n//\n// GET /v2/sui/account/coins — full wallet portfolio + USD prices\n// (paid Pro-tier endpoint; one call)\n// GET /v2/sui/coin/price/list — multi-token price list\n// (max 10 tokens per call; chunked\n// transparently if more are passed)\n//\n// Auth: `x-api-key` header. The shared API key is available as\n// `process.env.BLOCKVISION_API_KEY` in the audric web app and is threaded\n// into `ToolContext.blockvisionApiKey` via the engine factory.\n//\n// Failure mode: layered fallback. If BlockVision `/account/coins` returns\n// 5xx, 429, or the `apiKey` is missing/blank we drop to a Sui-RPC path\n// for the coin list, then [v0.50.3] still attempt the BlockVision\n// `/coin/price/list` endpoint to USD-price non-stable holdings. Only when\n// BOTH BV endpoints fail do we degrade to the hardcoded stable allow-list\n// (USDC/USDT/USDe/USDsui get $1.00, everything else `null`). The two\n// endpoints have separate rate limits and price-list responses are cached\n// in-process for `CACHE_TTL_MS`, so the second call is frequently a hot\n// hit. The `source` field on the returned portfolio surfaces the final\n// path so callers can decide whether to badge \"approximate\" totals.\n// ---------------------------------------------------------------------------\n\nimport { getDecimalsForCoinType, resolveSymbol, normalizeCoinType, isInRegistry } from '@t2000/sdk';\nimport { fetchWalletCoins } from './sui-rpc.js';\nimport { getDefiCacheStore, type DefiCacheEntry, type DefiCacheStore } from './defi-cache.js';\nimport { getWalletCacheStore, type WalletCacheEntry, type WalletCacheStore } from './wallet-cache.js';\nimport { awaitOrFetch } from './cross-instance-lock.js';\nimport { getTelemetrySink } from './telemetry.js';\n\nconst BLOCKVISION_BASE = 'https://api.blockvision.org/v2/sui';\nconst PORTFOLIO_TIMEOUT_MS = 4_000;\nconst PRICES_TIMEOUT_MS = 3_000;\nconst CACHE_TTL_MS = 60_000;\n\n// ---------------------------------------------------------------------------\n// Wallet portfolio cache TTLs (PR 1+2 — v0.55)\n//\n// Per-source freshness for `fetchAddressPortfolio`. Mirrors the DeFi\n// cache pattern (`DEFI_FRESH_TTL_MS_*`). The store TTL we pass to\n// `set(address, entry, ttlSec)` is the **sticky window** (30 min) —\n// we want the entry to STAY in Redis long enough that a sustained\n// BV outage can keep serving the last known-good positive value\n// stamped as such. Freshness is computed by the FETCHER from the\n// entry's own `pricedAt`, not by the store.\n//\n// Why split:\n// - 60s `blockvision` — fully successful BV reply; trust it.\n// - 15s `sui-rpc-degraded` — BV unavailable, retry sooner so the\n// next caller gets a chance to recover.\n//\n// Pre-PR-1 the degraded TTL was emulated with the\n// `ts: Date.now() - (CACHE_TTL_MS - DEGRADED_CACHE_TTL_MS)` aging\n// trick at the write site. That worked under the in-process Map (TTL\n// was client-checked at read time using `ts`) but silently broke\n// under Redis (`EX` is server-enforced and ignores client `ts`).\n// Now we pass per-source TTLs explicitly to `store.set`.\n// ---------------------------------------------------------------------------\nconst WALLET_FRESH_TTL_MS_BLOCKVISION = 60_000;\nconst WALLET_FRESH_TTL_MS_DEGRADED = 15_000;\n/** Sticky window — entries persist this long after their fresh window so\n * brief BV bursts can fall back to last known-good positive. */\nconst WALLET_STICKY_TTL_SEC = 30 * 60;\n/** Lock keyspace prefix for cross-instance fan-out coalescing. */\nconst WALLET_LOCK_KEY = (address: string) => `bv-lock:wallet:${address.toLowerCase()}`;\nconst DEFI_LOCK_KEY = (address: string) => `bv-lock:defi:${address.toLowerCase()}`;\n\n// ---------------------------------------------------------------------------\n// BlockVision retry policy\n//\n// BlockVision Pro periodically returns 429 (\"rate limited\") under burst\n// load — both the per-second key limit AND a global edge throttle that\n// can fire even when the key is well under quota. Without retry, a\n// single 429 cascades through the whole stack:\n// - balance_check's wallet read degrades to Sui-RPC ($0 for long-tail)\n// - DeFi read returns degraded → falls to sticky cache (or empty)\n// - portfolio_analysis trusts the partial+0 → no DeFi line\n//\n// Three attempts with jittered exponential backoff (250/750/2250ms ± 25%)\n// catches the typical 1–3s BV throttle window before any user-visible\n// degradation happens. If BlockVision sends a `Retry-After` header we\n// honor it (capped at 5s to stay inside the per-call timeout budget).\n//\n// Worst case: 250 + 750 = ~1s of waiting before the third (final)\n// attempt. Still well inside the 4s portfolio / 3s prices / 5s defi\n// per-call timeouts because each `fetch()` carries its own\n// `AbortSignal.timeout()` independent of the retry sleep.\n// ---------------------------------------------------------------------------\nconst BV_RETRY_MAX_ATTEMPTS = 3;\nconst BV_RETRY_BASE_DELAY_MS = 250;\nconst BV_RETRY_BACKOFF_FACTOR = 3;\nconst BV_RETRY_JITTER = 0.25;\nconst BV_RETRY_AFTER_CAP_MS = 5_000;\n\n// ---------------------------------------------------------------------------\n// Circuit breaker — scaling guard\n//\n// Naive retry amplifies BV load 3x during sustained outages. At 10k\n// users that's a self-inflicted DoS — every retry burst pushes BV\n// further into rate-limit territory and prolongs the outage. Solution:\n// a process-local circuit breaker. After CB_THRESHOLD 429s within a\n// CB_WINDOW_MS rolling window, open the circuit for CB_COOLDOWN_MS\n// and treat 429s as final (no retry). This isolates retry to the\n// burst case it's designed for and removes amplification during real\n// outages.\n//\n// Per-process state is intentional — global Redis-backed coordination\n// would add latency on the hot path, and each Vercel function having\n// its own breaker is acceptable: at 10k users we'd have ~10–50\n// concurrent function instances; each one independently learning the\n// circuit is open within ~5s of the outage starting is fast enough.\n//\n// Tunables chosen to detect a sustained outage in <5s without\n// false-positiving on momentary bursts that retry would absorb.\n// ---------------------------------------------------------------------------\nconst CB_WINDOW_MS = 5_000;\nconst CB_THRESHOLD = 10;\nconst CB_COOLDOWN_MS = 30_000;\n\nlet cb429Timestamps: number[] = [];\nlet cbOpenUntil = 0;\n\nfunction cbIsOpen(now: number): boolean {\n return now < cbOpenUntil;\n}\n\nfunction cbRecord429(now: number): void {\n cb429Timestamps.push(now);\n cb429Timestamps = cb429Timestamps.filter((t) => now - t < CB_WINDOW_MS);\n if (cb429Timestamps.length >= CB_THRESHOLD && !cbIsOpen(now)) {\n cbOpenUntil = now + CB_COOLDOWN_MS;\n getTelemetrySink().gauge('bv.cb_open', 1);\n console.warn(\n `[blockvision] circuit breaker OPEN — ${CB_THRESHOLD} 429s in ${CB_WINDOW_MS}ms, retries disabled for ${CB_COOLDOWN_MS / 1000}s`,\n );\n cb429Timestamps = [];\n }\n}\n\n/** Test seam — reset breaker state between tests. */\nexport function _resetBlockVisionCircuitBreaker(): void {\n cb429Timestamps = [];\n cbOpenUntil = 0;\n}\n\ninterface BvRetryOpts {\n signal?: AbortSignal;\n /** Test seam — defaults to `Math.random()`. Inject a fixed RNG for deterministic tests. */\n rng?: () => number;\n /** Test seam — defaults to `setTimeout`-backed promise. */\n sleep?: (ms: number) => Promise<void>;\n /** Test seam — defaults to `Date.now()`. Inject for deterministic CB tests. */\n now?: () => number;\n /**\n * [SPEC 8 v0.5.1 B3.2] Mutable counter the engine attaches to\n * `ToolContext.retryStats`. Bumped to `attempt + 1` on every retry\n * iteration past the first, so a 1st-try success leaves the value\n * at 1 and a 2nd-try success leaves it at 2. The dispatcher reads\n * the final value back and surfaces it on the `tool_result` event\n * (only when > 1) so the host renders \"TOOL · attempt N · 1.4s\".\n */\n retryStats?: { attemptCount: number };\n}\n\n/**\n * `fetch()` with bounded retry on transient failures.\n *\n * Retries on:\n * - HTTP 429 (rate limited) — honors `Retry-After` if present\n * - HTTP 5xx (transient server error)\n * - Network errors (DNS, ECONNRESET, etc.) — but NOT AbortError\n *\n * Does NOT retry on:\n * - HTTP 4xx other than 429 (client error — won't change on retry)\n * - AbortError from the caller's signal (caller cancelled — respect)\n *\n * Returns the final `Response` (success or last non-retryable error)\n * so existing `res.ok` / `res.status` checks at call sites continue\n * to work unchanged. Re-throws the original error only when every\n * attempt was a network error (no Response object to return).\n */\nexport async function fetchBlockVisionWithRetry(\n url: string,\n init: RequestInit,\n opts: BvRetryOpts = {},\n): Promise<Response> {\n const rng = opts.rng ?? Math.random;\n const sleep = opts.sleep ?? ((ms: number) =>\n new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, ms);\n // Wire the caller's signal into the sleep so cancelling the\n // overall request aborts the retry wait too — otherwise we'd\n // burn the full backoff before noticing the caller gave up.\n if (opts.signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n if (opts.signal.aborted) onAbort();\n else opts.signal.addEventListener('abort', onAbort, { once: true });\n }\n }));\n\n let lastError: unknown = null;\n let lastResponse: Response | null = null;\n\n for (let attempt = 0; attempt < BV_RETRY_MAX_ATTEMPTS; attempt++) {\n // [SPEC 8 v0.5.1 B3.2] Reflect the actual attempt count (1-indexed) into\n // the caller's mutable counter. Done at the top of every iteration so\n // even a network-error path (which `continue`s) still advances the\n // visible attempt count for the dispatcher's read-back.\n if (opts.retryStats) opts.retryStats.attemptCount = attempt + 1;\n if (attempt > 0) {\n // Base wait with exponential growth: 250, 750, 2250 ms.\n let waitMs = BV_RETRY_BASE_DELAY_MS * Math.pow(BV_RETRY_BACKOFF_FACTOR, attempt - 1);\n // Honor Retry-After when the server told us to wait — capped so\n // a misbehaving header (`Retry-After: 3600`) can't stall a\n // single tool call past its per-call timeout budget.\n const retryAfter = lastResponse?.headers.get('retry-after');\n if (retryAfter) {\n const secs = Number(retryAfter);\n if (Number.isFinite(secs) && secs > 0) {\n waitMs = Math.min(secs * 1000, BV_RETRY_AFTER_CAP_MS);\n }\n }\n // Symmetric jitter (±jitterFactor) to spread out caller bursts\n // — without it, every concurrent request retries at the same\n // moment and re-creates the burst we're trying to absorb.\n const jitterPx = (rng() * 2 - 1) * BV_RETRY_JITTER * waitMs;\n const delay = Math.max(0, waitMs + jitterPx);\n try {\n await sleep(delay);\n } catch (err) {\n // Caller aborted during backoff — bail with the last error/\n // response so the caller sees the same surface as if the\n // abort had fired during fetch itself.\n if (lastResponse) return lastResponse;\n throw err;\n }\n }\n\n try {\n lastResponse = await fetch(url, init);\n } catch (err) {\n lastError = err;\n // Don't retry if the caller cancelled — that's intentional.\n if ((err as { name?: string })?.name === 'AbortError') throw err;\n getTelemetrySink().counter('bv.requests', { status: 'network_err', attempt: String(attempt) });\n continue;\n }\n\n if (lastResponse.ok) {\n getTelemetrySink().counter('bv.requests', { status: '2xx', attempt: String(attempt) });\n return lastResponse;\n }\n // 4xx other than 429 are permanent client errors — no point retrying.\n if (lastResponse.status !== 429 && lastResponse.status < 500) {\n getTelemetrySink().counter('bv.requests', { status: String(lastResponse.status), attempt: String(attempt) });\n return lastResponse;\n }\n // Track 429s for the circuit breaker — if too many fire in a\n // short window we stop retrying and let the caller degrade\n // gracefully rather than amplifying load on an already-overloaded\n // upstream.\n if (lastResponse.status === 429) {\n getTelemetrySink().counter('bv.requests', { status: '429', attempt: String(attempt) });\n const now = (opts.now ?? Date.now)();\n cbRecord429(now);\n if (cbIsOpen(now)) {\n return lastResponse;\n }\n } else {\n getTelemetrySink().counter('bv.requests', { status: '5xx', attempt: String(attempt) });\n }\n }\n\n if (lastResponse) return lastResponse;\n throw lastError ?? new Error('fetch failed after retries');\n}\n// [PR 1 — v0.55] `DEGRADED_CACHE_TTL_MS` (the v0.53.3 constant for the\n// Sui-RPC fallback path's effective TTL) was removed alongside the\n// `portfolioCache` Map and its `ts: Date.now() - (CACHE_TTL_MS -\n// DEGRADED_CACHE_TTL_MS)` aging trick. The same effect — short retry\n// window for degraded reads — now lives in `WALLET_FRESH_TTL_MS_DEGRADED`\n// at the top of the file, applied as a per-source `EX` value at write\n// time so Redis enforces it server-side.\n//\n// BlockVision caps `tokenIds` at 10. Internal callers (engine-factory, the\n// future `token_prices` LLM tool) may request more — we chunk transparently.\nconst PRICE_LIST_CHUNK = 10;\n\n/**\n * Hardcoded $1.00 allow-list for the canonical Sui stablecoins. Used in\n * two places:\n * 1. `fetchTokenPrices` short-circuit — the LLM rarely needs to quote\n * USDC/USDT against an external feed, and skipping the network call\n * saves ~200–400ms p50 per balance render.\n * 2. Sui-RPC degraded fallback inside `fetchAddressPortfolio` — when\n * BlockVision is unavailable, stables still resolve to USD so the\n * visible \"$X total\" doesn't suddenly read $0.\n *\n * Coverage rationale: the four native Sui stables (USDC/USDT/USDe/USDsui)\n * plus the two Wormhole-bridged variants present in legacy wallets. We\n * intentionally do NOT include long-tail \"USD*\" tokens — depeg risk is\n * real (e.g. Frax, sUSD) and a stale $1.00 on a depegged asset is more\n * misleading than `null`.\n */\nconst STABLE_USD_PRICES: Readonly<Record<string, number>> = {\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC': 1,\n '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT': 1,\n '0x41d587e5336f1c86cad50d38a7136db99333bb9bda91cea4ba69115defeb1402::sui_usde::SUI_USDE': 1,\n '0x44f838219cf67b058f3b37907b655f226153c18e33dfcd0da559a844fea9b1c1::usdsui::USDSUI': 1,\n '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN': 1,\n '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN': 1,\n};\n\nexport interface PortfolioCoin {\n coinType: string;\n symbol: string;\n decimals: number;\n /** Raw on-chain amount (string to preserve precision). */\n balance: string;\n /** USD spot price; `null` when not available (long-tail, degraded mode). */\n price: number | null;\n /** balance/10^decimals * price; `null` when price is `null`. */\n usdValue: number | null;\n}\n\nexport interface AddressPortfolio {\n coins: PortfolioCoin[];\n totalUsd: number;\n pricedAt: number;\n source: 'blockvision' | 'sui-rpc-degraded';\n}\n\n// [PR 1 — v0.55] The module-level `portfolioCache` Map is gone.\n// Replaced by the pluggable `WalletCacheStore` (default `InMemoryWalletCacheStore`,\n// Audric injects `UpstashWalletCacheStore`). See `wallet-cache.ts` for\n// the why — same SSOT bug class as the v0.54 DeFi work, just on the\n// wallet half. `portfolioInflight` is kept as an in-process coalescer\n// so N concurrent in-process callers share one promise; cross-process\n// coalescing is handled by `awaitOrFetch` in PR 2.\nconst portfolioInflight = new Map<string, Promise<AddressPortfolio>>();\n\ninterface PriceMapCacheEntry {\n prices: Record<string, { price: number; change24h?: number }>;\n ts: number;\n}\nlet priceMapCache: PriceMapCacheEntry | null = null;\n\ninterface BlockVisionAccountCoinsResponse {\n code: number;\n message: string;\n result?: {\n coins?: Array<{\n coinType: string;\n name?: string;\n symbol?: string;\n decimals?: number;\n balance: string;\n verified?: boolean;\n logo?: string;\n usdValue?: string;\n objects?: number;\n price?: string;\n priceChangePercentage24H?: string;\n }>;\n usdValue?: string;\n };\n}\n\ninterface BlockVisionPriceListResponse {\n code: number;\n message: string;\n result?: {\n prices?: Record<string, string>;\n coin24HChange?: Record<string, string>;\n };\n}\n\n/** Source-aware fresh-TTL lookup for wallet portfolio entries. */\nfunction walletFreshTtlMs(source: AddressPortfolio['source']): number {\n switch (source) {\n case 'blockvision':\n return WALLET_FRESH_TTL_MS_BLOCKVISION;\n case 'sui-rpc-degraded':\n return WALLET_FRESH_TTL_MS_DEGRADED;\n }\n}\n\n/**\n * Store-write helper that swallows backend errors. A Redis hiccup\n * during write should never break a successful read — the next caller\n * will simply re-fetch on cache miss. Errors are logged so an outage\n * is still observable in Vercel logs. Mirrors `safeStoreSet` in the\n * DeFi half.\n */\nasync function safeWalletStoreSet(\n store: WalletCacheStore,\n address: string,\n entry: WalletCacheEntry,\n ttlSec: number,\n): Promise<void> {\n try {\n await store.set(address, entry, ttlSec);\n } catch (err) {\n console.warn('[wallet] cache set failed (non-fatal):', err);\n }\n}\n\n/**\n * Read the wallet store, swallowing transport errors as cache misses.\n * Used by both the leader (pre-fanout check) and the follower (poll\n * loop while another instance fetches).\n */\nasync function safeWalletStoreGet(\n store: WalletCacheStore,\n address: string,\n): Promise<WalletCacheEntry | null> {\n try {\n return await store.get(address);\n } catch (err) {\n console.warn('[wallet] cache get failed (continuing as cache miss):', err);\n return null;\n }\n}\n\n/**\n * One-shot wallet portfolio fetcher. BlockVision returns balances + USD\n * prices in a single call; on failure we degrade to a Sui-RPC coin\n * fetch with hardcoded stablecoin pricing.\n *\n * Caching shape (PR 1+2 — v0.55):\n * 1. Store-level cache (Redis in prod, in-memory in CLI/tests). Read\n * first; if entry is fresh-for-source serve directly.\n * 2. In-process inflight Map dedupes concurrent in-process callers\n * onto one promise.\n * 3. The leader path runs under a cross-instance lock\n * (`bv-lock:wallet:<addr>`) so at most one Vercel instance per\n * address is hitting BlockVision at any moment. Followers poll\n * the store for the leader's write; if the leader dies they fall\n * through to a direct fetch as a defensive degraded path.\n *\n * Sticky-positive write rules mirror the DeFi half:\n * - `blockvision` (any total) → write unconditionally; latest BV\n * truth always wins.\n * - `sui-rpc-degraded` → write only when no fresher positive\n * `blockvision` entry exists in the sticky window (30 min). When\n * a positive sticky entry exists, return it as-is and DO NOT\n * overwrite — preserves the original `pricedAt` so a UI can\n * render \"last refresh Nm ago\".\n */\nexport async function fetchAddressPortfolio(\n address: string,\n apiKey: string | undefined,\n fallbackRpcUrl?: string,\n // [SPEC 8 v0.5.1 B3.2] Optional retry-stats counter forwarded to\n // `fetchBlockVisionWithRetry`. The dispatcher passes\n // `ctx.retryStats` here; the wrapper bumps `.attemptCount` on each\n // retry; the dispatcher reads the final value and surfaces it on\n // the `tool_result` event when > 1.\n opts: { retryStats?: { attemptCount: number } } = {},\n): Promise<AddressPortfolio> {\n const store = getWalletCacheStore();\n\n // ---------------------------------------------------------------\n // Read path — source-aware freshness\n // ---------------------------------------------------------------\n const cachedEntry = await safeWalletStoreGet(store, address);\n if (cachedEntry) {\n const ageMs = Date.now() - cachedEntry.pricedAt;\n if (ageMs < walletFreshTtlMs(cachedEntry.data.source)) {\n getTelemetrySink().counter('bv.cache_hit', { kind: 'wallet', freshness: 'fresh' });\n return cachedEntry.data;\n }\n // Stale hit — kept in scope for the sticky-positive fallback below.\n getTelemetrySink().counter('bv.cache_hit', { kind: 'wallet', freshness: 'stale-served' });\n } else {\n getTelemetrySink().counter('bv.cache_hit', { kind: 'wallet', freshness: 'miss' });\n }\n\n // In-process inflight dedup. Even with a cross-instance lock, we\n // still want concurrent in-process callers to share one promise.\n const existing = portfolioInflight.get(address);\n if (existing) return existing;\n\n const promise = (async (): Promise<AddressPortfolio> => {\n try {\n return await awaitOrFetch<AddressPortfolio>(\n WALLET_LOCK_KEY(address),\n // ----------------------------------------------------------\n // Leader path — runs after we've won the cross-instance lock.\n // Re-checks the cache (small window where another leader on a\n // different process just wrote) before paying for the BV call.\n // ----------------------------------------------------------\n async () => {\n const recheck = await safeWalletStoreGet(store, address);\n if (recheck) {\n const ageMs = Date.now() - recheck.pricedAt;\n if (ageMs < walletFreshTtlMs(recheck.data.source)) {\n return recheck.data;\n }\n }\n\n // Try BlockVision first (fast path).\n if (apiKey && apiKey.trim().length > 0) {\n const blockvision = await fetchPortfolioFromBlockVision(address, apiKey, opts.retryStats);\n if (blockvision) {\n // `blockvision` always wins — latest BV truth.\n await safeWalletStoreSet(\n store,\n address,\n { data: blockvision, pricedAt: Date.now() },\n WALLET_STICKY_TTL_SEC,\n );\n return blockvision;\n }\n }\n\n // [v0.50.3] Pass apiKey through so the RPC fallback can\n // still use the BlockVision price-list endpoint to USD-price\n // non-stables. Without this, a transient `/account/coins`\n // failure (429, 5xx, network) would silently zero out every\n // non-stable holding in the wallet view.\n const degraded = await fetchPortfolioFromSuiRpc(address, apiKey, fallbackRpcUrl);\n\n // -----------------------------------------------------\n // Sticky-positive write rules (PR 1 — v0.55)\n //\n // If a positive `blockvision` entry exists within the sticky\n // window, prefer it over a fresh degraded read. This stops a\n // BV burst from poisoning the cache with a $0/missing-token\n // wallet across every Vercel instance simultaneously — the\n // exact divergence that fired three different totals on the\n // same chat turn pre-v0.54 (DeFi half) and pre-v0.55 (wallet\n // half).\n //\n // We use `recheck` (which we read inside the lock) as the\n // basis for the comparison. If `recheck` is null but the\n // pre-lock `cachedEntry` was positive within the sticky\n // window, prefer that — covers the case where the pre-lock\n // read raced a deleting writer.\n // -----------------------------------------------------\n const stickyCandidate =\n recheck && recheck.data.source === 'blockvision' && recheck.data.totalUsd > 0\n ? recheck\n : cachedEntry &&\n cachedEntry.data.source === 'blockvision' &&\n cachedEntry.data.totalUsd > 0\n ? cachedEntry\n : null;\n\n const stickyFresh =\n stickyCandidate && Date.now() - stickyCandidate.pricedAt < WALLET_STICKY_TTL_SEC * 1000;\n\n if (stickyFresh) {\n // Return the cached positive as-is — preserve `pricedAt` so\n // a UI consumer can decide whether to caveat staleness.\n // Do NOT overwrite the cache; the existing entry is still\n // the most truthful thing we have for this address.\n return stickyCandidate!.data;\n }\n\n // No sticky fallback — write the degraded result with a\n // short TTL so the next caller retries BV soon. Pre-PR-1\n // this used the `ts: Date.now() - (CACHE_TTL_MS -\n // DEGRADED_CACHE_TTL_MS)` aging trick to emulate a short\n // TTL on top of the long base TTL; under Redis's\n // server-enforced `EX` that no longer works, so we pass\n // an explicit per-source TTL instead.\n await safeWalletStoreSet(\n store,\n address,\n { data: degraded, pricedAt: Date.now() },\n Math.ceil(WALLET_FRESH_TTL_MS_DEGRADED / 1000),\n );\n return degraded;\n },\n {\n // Followers poll the wallet cache while the leader fetches.\n // Returns non-null only when the leader has written a\n // fresh-for-source entry — stale entries keep the poll going.\n pollCache: async () => {\n const e = await safeWalletStoreGet(store, address);\n if (!e) return null;\n const ageMs = Date.now() - e.pricedAt;\n return ageMs < walletFreshTtlMs(e.data.source) ? e.data : null;\n },\n },\n );\n } finally {\n portfolioInflight.delete(address);\n }\n })();\n\n portfolioInflight.set(address, promise);\n return promise;\n}\n\nasync function fetchPortfolioFromBlockVision(\n address: string,\n apiKey: string,\n retryStats?: { attemptCount: number },\n): Promise<AddressPortfolio | null> {\n const url = `${BLOCKVISION_BASE}/account/coins?account=${encodeURIComponent(address)}`;\n const signal = AbortSignal.timeout(PORTFOLIO_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchBlockVisionWithRetry(\n url,\n {\n headers: { 'x-api-key': apiKey, accept: 'application/json' },\n signal,\n },\n { signal, retryStats },\n );\n } catch (err) {\n console.warn('[blockvision-prices] portfolio fetch threw, degrading:', err);\n return null;\n }\n\n if (!res.ok) {\n console.warn(`[blockvision-prices] portfolio HTTP ${res.status}, degrading`);\n return null;\n }\n\n let json: BlockVisionAccountCoinsResponse;\n try {\n json = (await res.json()) as BlockVisionAccountCoinsResponse;\n } catch (err) {\n console.warn('[blockvision-prices] portfolio JSON parse failed, degrading:', err);\n return null;\n }\n\n if (json.code !== 200 || !json.result) {\n console.warn(`[blockvision-prices] portfolio code=${json.code} msg=${json.message}, degrading`);\n return null;\n }\n\n const rawCoins = json.result.coins ?? [];\n const coins: PortfolioCoin[] = rawCoins.map((c) => {\n const coinType = c.coinType;\n // [v0.55.0 Fix 1] Prefer canonical SDK symbol over the raw symbol returned\n // by BlockVision when the coin type is in COIN_REGISTRY. BlockVision can\n // return uppercase variants (e.g. 'USDSUI') that don't match the canonical\n // mixed-case symbol ('USDsui'), and downstream consumers (balance.ts\n // STABLE_SYMBOLS set + saveableUsdsui find, audric chip flows, useBalance\n // hook) all key off the canonical form. The earlier `c.symbol || resolveSymbol`\n // ordering caused saveableUsdsui to read 0 right after a USDC→USDsui swap\n // because BV's 'USDSUI' beat the registry's 'USDsui' and the find() missed.\n //\n // We use `isInRegistry` (NOT `isSupported`) on purpose: USDsui/USDe/USDT\n // are legacy/no-tier registry entries today, but they STILL have canonical\n // symbol metadata that downstream code keys off. `isSupported` would\n // exclude them and re-introduce the bug.\n //\n // For coins NOT in the registry (memecoins, long-tail tokens) we fall\n // back to whatever BV returns since it's typically more user-friendly\n // than resolveSymbol's last-segment heuristic.\n const symbol = isInRegistry(coinType)\n ? resolveSymbol(coinType)\n : c.symbol || resolveSymbol(coinType);\n const decimals = typeof c.decimals === 'number' ? c.decimals : getDecimalsForCoinType(coinType);\n const stablePrice = STABLE_USD_PRICES[coinType];\n const apiPrice = parseNumberOrNull(c.price);\n const apiUsd = parseNumberOrNull(c.usdValue);\n const price = apiPrice ?? stablePrice ?? null;\n let usdValue = apiUsd;\n if (usdValue == null && price != null) {\n const amount = Number(c.balance) / 10 ** decimals;\n usdValue = Number.isFinite(amount) ? amount * price : null;\n }\n return {\n coinType,\n symbol,\n decimals,\n balance: c.balance,\n price,\n usdValue,\n };\n });\n\n const apiTotal = parseNumberOrNull(json.result.usdValue);\n const totalUsd = apiTotal ?? coins.reduce((sum, c) => sum + (c.usdValue ?? 0), 0);\n\n return {\n coins,\n totalUsd,\n pricedAt: Date.now(),\n source: 'blockvision',\n };\n}\n\nasync function fetchPortfolioFromSuiRpc(\n address: string,\n apiKey: string | undefined,\n fallbackRpcUrl?: string,\n): Promise<AddressPortfolio> {\n const walletCoins = await fetchWalletCoins(address, fallbackRpcUrl).catch((err) => {\n console.warn('[blockvision-prices] sui rpc coin fetch failed:', err);\n return [];\n });\n\n // [v0.50.3] When the BV `/account/coins` endpoint is unavailable\n // (typically a 429 burst, sometimes a 5xx) we still hit the BV\n // `/coin/price/list` endpoint to USD-price non-stable holdings. The two\n // endpoints have separate rate limits and price-list responses are\n // cached for `CACHE_TTL_MS`, so this is cheap and frequently a hot hit.\n // If price-list ALSO fails (e.g. true BV outage) we degrade further to\n // stables-only, which matches the v0.50.2 behaviour. Net effect: one\n // more chance to recover from a BV blip before the wallet shows $0.\n const nonStableCoinTypes = walletCoins\n .map((c) => c.coinType)\n .filter((coinType) => !(coinType in STABLE_USD_PRICES));\n const livePrices =\n apiKey && apiKey.trim().length > 0 && nonStableCoinTypes.length > 0\n ? await fetchTokenPrices(nonStableCoinTypes, apiKey).catch((err) => {\n console.warn('[blockvision-prices] price-list fallback failed:', err);\n return {} as Record<string, { price: number; change24h?: number }>;\n })\n : {};\n\n const coins: PortfolioCoin[] = walletCoins.map((c) => {\n const stablePrice = STABLE_USD_PRICES[c.coinType] ?? null;\n const livePrice = livePrices[c.coinType]?.price ?? null;\n const price = stablePrice ?? livePrice;\n const amount = Number(c.totalBalance) / 10 ** c.decimals;\n const usdValue = price != null && Number.isFinite(amount) ? amount * price : null;\n return {\n coinType: c.coinType,\n symbol: c.symbol,\n decimals: c.decimals,\n balance: c.totalBalance,\n price,\n usdValue,\n };\n });\n\n const totalUsd = coins.reduce((sum, c) => sum + (c.usdValue ?? 0), 0);\n return {\n coins,\n totalUsd,\n pricedAt: Date.now(),\n source: 'sui-rpc-degraded',\n };\n}\n\n/**\n * Multi-token price lookup. Returns a map of coinType → `{ price, change24h }`\n * with the `change24h` field populated when BlockVision returns it.\n * Hardcoded stable allow-list short-circuits before the network call so\n * USDC/USDT lookups don't pay the BlockVision RTT. Chunks transparently\n * (BlockVision caps `tokenIds` at 10 per call). Cached in-process for\n * `CACHE_TTL_MS` with merge-on-miss semantics — a cache containing 8 of 10\n * requested coins fetches only the missing 2 instead of throwing the\n * whole map away.\n */\nexport async function fetchTokenPrices(\n coinTypes: string[],\n apiKey: string | undefined,\n // [SPEC 8 v0.5.1 B3.2] See `fetchAddressPortfolio` for the retry-stats\n // contract.\n opts: { retryStats?: { attemptCount: number } } = {},\n): Promise<Record<string, { price: number; change24h?: number }>> {\n if (coinTypes.length === 0) return {};\n\n const now = Date.now();\n const cacheValid = priceMapCache !== null && now - priceMapCache.ts < CACHE_TTL_MS;\n const cached = cacheValid ? priceMapCache!.prices : {};\n\n // [v0.47.1] Cache + STABLE_USD_PRICES are keyed by long-form coin types\n // (64-hex address). Caller inputs may be short-form (`0x2::sui::SUI`).\n // Normalize for lookup, but preserve the caller's original string in\n // the result map so consumers indexing by their input keys still work.\n const result: Record<string, { price: number; change24h?: number }> = {};\n const stillMissing: string[] = [];\n for (const original of coinTypes) {\n const norm = normalizeCoinType(original);\n if (cached[norm]) {\n result[original] = cached[norm];\n continue;\n }\n const stable = STABLE_USD_PRICES[norm];\n if (typeof stable === 'number') {\n result[original] = { price: stable };\n continue;\n }\n stillMissing.push(original);\n }\n\n if (stillMissing.length === 0) return result;\n if (!apiKey || apiKey.trim().length === 0) {\n return result;\n }\n\n const fetched = await fetchPricesFromBlockVision(stillMissing, apiKey, opts.retryStats);\n Object.assign(result, fetched);\n\n // Cache by long form so subsequent calls with either form hit the cache.\n const cacheUpdates: Record<string, { price: number; change24h?: number }> = {};\n for (const [original, value] of Object.entries(fetched)) {\n cacheUpdates[normalizeCoinType(original)] = value;\n }\n const merged = { ...cached, ...cacheUpdates };\n priceMapCache = { prices: merged, ts: cacheValid ? priceMapCache!.ts : now };\n\n return result;\n}\n\nasync function fetchPricesFromBlockVision(\n coinTypes: string[],\n apiKey: string,\n retryStats?: { attemptCount: number },\n): Promise<Record<string, { price: number; change24h?: number }>> {\n const out: Record<string, { price: number; change24h?: number }> = {};\n\n // [v0.47.1] BlockVision's `/coin/price/list` requires fully-normalized\n // 64-hex coin types — short forms like `0x2::sui::SUI` come back with\n // `result.prices = {}` even on Pro. Normalize before sending; build a\n // long→original map so callers who passed `0x2::sui::SUI` see exactly\n // that key in the response (not the long form BlockVision echoes back).\n const longToOriginal = new Map<string, string>();\n for (const original of coinTypes) {\n const long = normalizeCoinType(original);\n if (!longToOriginal.has(long)) longToOriginal.set(long, original);\n }\n const longForms = Array.from(longToOriginal.keys());\n\n for (let i = 0; i < longForms.length; i += PRICE_LIST_CHUNK) {\n const chunk = longForms.slice(i, i + PRICE_LIST_CHUNK);\n const tokenIds = encodeURIComponent(chunk.join(','));\n const url = `${BLOCKVISION_BASE}/coin/price/list?tokenIds=${tokenIds}&show24hChange=true`;\n const signal = AbortSignal.timeout(PRICES_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchBlockVisionWithRetry(\n url,\n {\n headers: { 'x-api-key': apiKey, accept: 'application/json' },\n signal,\n },\n { signal, retryStats },\n );\n } catch (err) {\n console.warn('[blockvision-prices] price chunk threw, skipping:', err);\n continue;\n }\n\n if (!res.ok) {\n console.warn(`[blockvision-prices] price chunk HTTP ${res.status}`);\n continue;\n }\n\n let json: BlockVisionPriceListResponse;\n try {\n json = (await res.json()) as BlockVisionPriceListResponse;\n } catch (err) {\n console.warn('[blockvision-prices] price chunk JSON parse failed:', err);\n continue;\n }\n if (json.code !== 200 || !json.result) continue;\n const prices = json.result.prices ?? {};\n const changes = json.result.coin24HChange ?? {};\n for (const [returnedType, priceStr] of Object.entries(prices)) {\n const price = parseNumberOrNull(priceStr);\n if (price == null) continue;\n // BlockVision echoes whatever long form we sent. Map back to the\n // caller's input string, falling through to the returned key for\n // safety if BlockVision ever normalizes differently than we do.\n const original = longToOriginal.get(returnedType) ?? returnedType;\n const change24h = parseNumberOrNull(changes[returnedType]);\n out[original] = change24h == null ? { price } : { price, change24h };\n }\n }\n return out;\n}\n\nfunction parseNumberOrNull(input: unknown): number | null {\n if (typeof input === 'number') return Number.isFinite(input) ? input : null;\n if (typeof input !== 'string' || input.trim().length === 0) return null;\n const n = Number(input);\n return Number.isFinite(n) ? n : null;\n}\n\n// ---------------------------------------------------------------------------\n// [v0.50.2] DeFi portfolio aggregation\n//\n// `balance_check` historically returned only wallet coins + NAVI savings,\n// missing DeFi positions across the rest of Sui DeFi — for active users\n// this can be a meaningful fraction of net worth.\n//\n// v0.50 introduced parallel fan-out across BlockVision's\n// `/account/defiPortfolio` endpoint (excluding NAVI, which is already\n// covered by `positionFetcher` / NAVI MCP). v0.50.1 expanded to all 26\n// supported protocols, but 26 simultaneous BV calls + the wallet\n// `/account/coins` call hit BlockVision's per-second burst cap, so the\n// wallet endpoint occasionally 429'd and silently degraded to Sui RPC\n// (which only prices stables, leaving non-stables at $0). v0.50.2 walks\n// it back to 9 protocols — the original 6 majors plus the 3 native-token\n// stakings users were missing — keeping the burst at 10 parallel calls\n// (1 wallet + 9 DeFi). Adding a future protocol is a 1-line append in\n// `DEFI_PROTOCOLS` below.\n//\n// Two-pass design:\n//\n// 1. Generic shape walker — recursively walks the response tree,\n// extracting paired-LP shapes (coinTypeA/B + balance, with X/Y and\n// tokenX/Y aliases) and single-coin shapes (coinType +\n// balance/amount/value), automatically handling Scallop's pre-USD\n// totals, NAVI's `type: 'Supply'|'Borrow'` flag, and parent-key debt\n// detection (`borrows`, `debt`, `borrowings` → subtract). Skips\n// `rewards` / `fees` / `pendingRewards` branches to avoid double-\n// counting incentives.\n//\n// 2. Bespoke shims for shapes the walker can't infer (implied coin types):\n// - bluefin: usdcVault/blueVault expose `{amount}` with implied coin type\n// - haedal: stakings expose `{sui_amount}` with implied SUI\n// - suistake / walrus / suins-staking: stakings of an implied native\n// token (SUI / WAL / NS); walker can't guess the coin type from\n// a bare `{amount}` field\n//\n// Pricing: callers pass a `priceHints` map (typically derived from the\n// wallet portfolio's coin prices). Coin types that appear in DeFi\n// positions but not in the wallet (e.g. one half of an LP that the user\n// doesn't otherwise hold) are looked up via a single batched\n// `fetchTokenPrices` call. STABLE_USD_PRICES short-circuits stables.\n//\n// Failure isolation: a 5xx for one protocol drops just that protocol. The\n// `source` field on the result surfaces 'partial' when any protocol failed.\n//\n// Concurrency: 9 parallel BV calls per balance_check + 1 wallet coins\n// call = 10 simultaneous, comfortably below BV Pro-tier burst caps.\n// Cache TTL 60s dedupes repeated balance_check calls for the same address\n// inside a chat session.\n// ---------------------------------------------------------------------------\n\nconst DEFI_PORTFOLIO_TIMEOUT_MS = 4_000;\n\n/**\n * Source-aware freshness thresholds. When a cache hit has age <\n * threshold, the fetcher serves it directly without re-attempting\n * BlockVision. When age >= threshold but < `STICKY_TTL_SEC`, the entry\n * is kept around as a sticky-positive fallback (see fetcher logic).\n */\nconst DEFI_FRESH_TTL_MS_BLOCKVISION = 60_000; // 60s — fully successful\nconst DEFI_FRESH_TTL_MS_PARTIAL = 15_000; // 15s — at least one protocol failed; retry sooner\nconst DEFI_FRESH_TTL_MS_PARTIAL_STALE = 0; // 0s — always re-fetch in background\n\n/**\n * [v0.54] Sticky-positive window: entries persist in the cache store\n * for this long even after their fresh-TTL has elapsed, so a brief\n * BlockVision burst that would otherwise return `partial+0` or\n * `degraded` can fall back to the last-known-good positive value\n * (marked `partial-stale` so consumers can render an honest \"last\n * refresh Nm ago\" caveat). 30 minutes is long enough to absorb a\n * sustained BV outage without serving wildly stale data; users hold\n * positions on the order of hours/days, so a 30-minute lag rarely\n * misleads. Tunable per-deployment via the cache store TTL.\n */\nconst DEFI_STICKY_TTL_SEC = 30 * 60;\n\n// [v0.50.2] 9 protocols — the v0.50 majors (Cetus/Suilend/Scallop/Bluefin/\n// Aftermath/Haedal) plus three native-token stakings (Suistake/SuiNS-staking/\n// Walrus). v0.50.1 expanded to all 26 BlockVision protocols, but the resulting\n// 26-call burst caused the wallet `/account/coins` endpoint to occasionally\n// 429, falling back to Sui-RPC degraded mode where non-stables are unpriced\n// — so wallet display showed $0 for users with MANIFEST/FAITH/etc. holdings.\n// 9 protocols = 9+1 burst per balance_check, comfortably below BV burst\n// caps. Walker + bespoke shims stay as-is — adding a future protocol is a\n// 1-line append here. Deliberately excludes NAVI (already covered by\n// `savings_info` via positionFetcher / NAVI MCP — including would\n// double-count savings).\nconst DEFI_PROTOCOLS = [\n 'aftermath',\n 'bluefin',\n 'cetus',\n 'haedal',\n 'scallop',\n 'suilend',\n 'suins-staking',\n 'suistake',\n 'walrus',\n] as const;\nexport type DefiProtocol = (typeof DEFI_PROTOCOLS)[number];\n\n// Implied coin types for protocols whose response shape buries the coin\n// identity in the protocol's own conventions (no `coinType` field).\nconst SUI_TYPE_FULL =\n '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI';\nconst USDC_TYPE_FULL =\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC';\nconst BLUE_TYPE_FULL =\n '0xe1b45a0e641b9955a20aa0ad1c1f4ad86aad8afb07296d4085e349a50e90bdca::blue::BLUE';\nconst WAL_TYPE_FULL =\n '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL';\nconst NS_TYPE_FULL =\n '0x5145494a5f5100e645e4b0aa950fa6b68f614e8c59e17bc5ded3495123a79178::ns::NS';\n\nexport interface DefiSummary {\n /** Net USD value of all aggregated DeFi positions (supply + collateral - debt). */\n totalUsd: number;\n /** Per-protocol breakdown for cards / debugging. Only protocols with non-zero value are present. */\n perProtocol: Partial<Record<DefiProtocol, number>>;\n pricedAt: number;\n /**\n * `blockvision` — every protocol in `DEFI_PROTOCOLS` responded successfully.\n * `partial` — at least one protocol failed; total may under-count.\n * `partial-stale` — fresh fetch returned degraded/partial-zero, but we have a\n * positive value cached within the sticky window\n * (`DEFI_STICKY_TTL_SEC`, default 30min). The numbers are\n * real, just not freshly verified — UI should caveat with\n * \"last refresh Nm ago\" so the user knows the provenance.\n * Introduced in v0.54 to fix cross-instance SSOT divergence\n * when BlockVision is bursting.\n * `degraded` — no API key, or every protocol failed AND no sticky\n * fallback exists; total = 0.\n */\n source: 'blockvision' | 'partial' | 'partial-stale' | 'degraded';\n}\n\n// Process-local inflight dedup. Even with a shared cache store (Redis),\n// we still want to coalesce 9 BlockVision calls when N concurrent\n// callers in the same process miss the cache simultaneously — one\n// fetch fans out, all callers await the same promise. The store\n// handles cross-process dedup via TTL (last writer wins, but the\n// sticky-positive write rules below ensure the wrong winner can't\n// poison cached known-good data).\nconst defiInflight = new Map<string, Promise<DefiSummary>>();\n\n/** Source-aware fresh-TTL lookup. See constants block above for rationale. */\nfunction freshTtlForSource(source: DefiSummary['source']): number {\n switch (source) {\n case 'blockvision':\n return DEFI_FRESH_TTL_MS_BLOCKVISION;\n case 'partial':\n return DEFI_FRESH_TTL_MS_PARTIAL;\n case 'partial-stale':\n return DEFI_FRESH_TTL_MS_PARTIAL_STALE;\n case 'degraded':\n return 0;\n }\n}\n\n/**\n * Store-write helper that swallows backend errors. A Redis hiccup\n * during write should never break a successful read — the next caller\n * will simply re-fetch on cache miss. Errors are logged so an outage\n * is still observable in Vercel logs.\n */\nasync function safeStoreSet(\n store: DefiCacheStore,\n address: string,\n entry: DefiCacheEntry,\n): Promise<void> {\n try {\n await store.set(address, entry, DEFI_STICKY_TTL_SEC);\n } catch (err) {\n console.warn('[defi] cache set failed (non-fatal):', err);\n }\n}\n\n/**\n * Read the DeFi store, swallowing transport errors as cache misses.\n * Used by both the leader (pre-fanout + post-lock recheck) and the\n * follower (poll loop). Mirrors `safeWalletStoreGet`.\n */\nasync function safeDefiStoreGet(\n store: DefiCacheStore,\n address: string,\n): Promise<DefiCacheEntry | null> {\n try {\n return await store.get(address);\n } catch (err) {\n console.warn('[defi] cache get failed (continuing as cache miss):', err);\n return null;\n }\n}\n\n// Warn-once gate so we don't spam logs every time `balance_check` runs in a\n// misconfigured environment. The first request that hits the missing-key\n// guard logs a loud, scannable warning; subsequent requests stay quiet.\n// Reset on process restart, which is fine — the next deploy logs again\n// until the operator sets the key.\n//\n// Defense-in-depth note: the audric web app gates the empty-key class of\n// bug at server boot via `apps/web/lib/env.ts`. This warn-and-degrade\n// path remains because the engine package is also consumed by the CLI,\n// MCP server, and other hosts that may not have the same gate, AND the\n// SDK form of `balance_check` accepts the apiKey as a runtime parameter\n// — degrading visibly is the right behavior when a caller passes blank.\nlet warnedMissingApiKey = false;\n\ninterface BlockVisionDefiResponse {\n code: number;\n message: string;\n result?: Record<string, unknown>;\n}\n\nexport async function fetchAddressDefiPortfolio(\n address: string,\n apiKey: string | undefined,\n priceHints: Record<string, number> = {},\n // [SPEC 8 v0.5.1 B3.2] See `fetchAddressPortfolio` for the retry-stats\n // contract.\n opts: { retryStats?: { attemptCount: number } } = {},\n): Promise<DefiSummary> {\n if (!apiKey || apiKey.trim().length === 0) {\n if (!warnedMissingApiKey) {\n warnedMissingApiKey = true;\n // Loud, single-line warning so it's grep-able in log explorers.\n // BLOCKVISION_API_KEY missing OR empty string (\"\") — both produce\n // identical silent-zero behavior, which the v0.50 fix-it pass after\n // the audric-roadmap S.18 work surfaced as a class of bug\n // (env var present in Vercel but blank → degraded forever).\n console.warn(\n '[defi] BLOCKVISION_API_KEY missing or empty — DeFi positions will report $0 across all protocols. Set the key in your runtime env to enable Bluefin/Suilend/Cetus/etc. aggregation.',\n );\n }\n return { totalUsd: 0, perProtocol: {}, pricedAt: Date.now(), source: 'degraded' };\n }\n\n const store = getDefiCacheStore();\n\n // ---------------------------------------------------------------\n // Read path — source-aware freshness\n //\n // `cachedEntry` may be present but past its source-specific\n // freshness threshold. In that case we fall through to a fresh\n // fetch but keep the entry in scope as a sticky-positive fallback\n // (see write rules below). Store-level errors are swallowed; we\n // log and continue as if the cache were empty so a Redis hiccup\n // never breaks `balance_check`.\n // ---------------------------------------------------------------\n const cachedEntry = await safeDefiStoreGet(store, address);\n if (cachedEntry) {\n const ageMs = Date.now() - cachedEntry.pricedAt;\n const freshTtlMs = freshTtlForSource(cachedEntry.data.source);\n if (ageMs < freshTtlMs) {\n // Fresh hit — serve directly without re-fetching.\n getTelemetrySink().counter('bv.cache_hit', { kind: 'defi', freshness: 'fresh' });\n return cachedEntry.data;\n }\n // Stale hit kept in scope for the sticky-positive fallback below.\n getTelemetrySink().counter('bv.cache_hit', { kind: 'defi', freshness: 'stale-served' });\n } else {\n getTelemetrySink().counter('bv.cache_hit', { kind: 'defi', freshness: 'miss' });\n }\n\n let inflight = defiInflight.get(address);\n if (inflight) return inflight;\n\n // ---------------------------------------------------------------\n // [PR 2 — v0.55] Cross-instance coalescer wraps the WHOLE 9-protocol\n // fan-out as a single unit. Lock key is `bv-lock:defi:<addr>` —\n // distinct from the wallet lock so they don't block each other.\n //\n // IMPORTANT: the lock sits at the fan-out level, NOT around each\n // individual `fetchOneDefiProtocol` call. Per-protocol locking would\n // cause the 9 sibling protocols to compete for the same lock — one\n // would win and 8 would poll-then-refetch, completely defeating\n // coalescing.\n // ---------------------------------------------------------------\n inflight = (async () => {\n try {\n return await awaitOrFetch<DefiSummary>(\n DEFI_LOCK_KEY(address),\n // Leader path — runs after acquiring the lock.\n async () => {\n // Re-check the cache after acquiring the lock — a leader on\n // another process may have written between our pre-lock\n // miss and our lock acquisition.\n const recheck = await safeDefiStoreGet(store, address);\n if (recheck) {\n const ageMs = Date.now() - recheck.pricedAt;\n if (ageMs < freshTtlForSource(recheck.data.source)) {\n return recheck.data;\n }\n }\n // Use the freshest sticky basis we have for the write rules\n // below. Prefer `recheck` over the pre-lock `cachedEntry`\n // (covers the case where a previous leader's write expired\n // since our pre-lock read).\n const stickyBasis: DefiCacheEntry | null = recheck ?? cachedEntry;\n const fanoutAt = Date.now();\n\n const settled = await Promise.allSettled(\n DEFI_PROTOCOLS.map((p) => fetchOneDefiProtocol(address, p, apiKey, opts.retryStats)),\n );\n\n // Pass 1 — discover every coin type referenced across all protocol\n // responses, then fill any missing prices in a single batched call.\n const seen = new Set<string>();\n for (const s of settled) {\n if (s.status === 'fulfilled' && s.value) collectCoinTypes(s.value, seen);\n }\n const normalizedHints: Record<string, number> = {};\n for (const [k, v] of Object.entries(priceHints)) {\n normalizedHints[normalizeCoinType(k)] = v;\n }\n const missing = Array.from(seen).filter((ct) => {\n const norm = normalizeCoinType(ct);\n return !normalizedHints[norm] && !STABLE_USD_PRICES[norm];\n });\n let fetchedPrices: Record<string, { price: number }> = {};\n if (missing.length > 0) {\n try {\n fetchedPrices = await fetchTokenPrices(missing, apiKey);\n } catch (err) {\n console.warn('[defi] fill-missing-prices failed:', err);\n }\n }\n\n const prices: Record<string, number> = { ...normalizedHints };\n for (const [ct, v] of Object.entries(fetchedPrices)) {\n prices[normalizeCoinType(ct)] ??= v.price;\n }\n for (const [ct, p] of Object.entries(STABLE_USD_PRICES)) {\n prices[normalizeCoinType(ct)] ??= p;\n }\n\n // Pass 2 — run the per-protocol normaliser. Bespoke handlers cover\n // the protocols the walker can't infer (implied coin types, nested\n // phantomType); everything else falls through to the generic walker.\n let totalUsd = 0;\n let failures = 0;\n const perProtocol: Partial<Record<DefiProtocol, number>> = {};\n\n for (let i = 0; i < DEFI_PROTOCOLS.length; i++) {\n const proto = DEFI_PROTOCOLS[i];\n const s = settled[i];\n if (s.status !== 'fulfilled' || !s.value) {\n failures++;\n continue;\n }\n try {\n const usd = normalizeProtocol(proto, s.value, prices);\n if (Number.isFinite(usd) && usd !== 0) {\n perProtocol[proto] = usd;\n totalUsd += usd;\n }\n } catch (err) {\n console.warn(`[defi] ${proto} normaliser threw:`, err);\n failures++;\n }\n }\n\n // Floor under-zero rollups to 0 — net negative would mean borrows >\n // supplies on a *DeFi-only* basis, which is implausible without\n // collateral counted; safer to surface 0 than a misleading negative.\n if (totalUsd < 0) totalUsd = 0;\n\n const fetchedAt = Date.now();\n const summary: DefiSummary = {\n totalUsd,\n perProtocol,\n pricedAt: fetchedAt,\n source:\n failures === DEFI_PROTOCOLS.length\n ? 'degraded'\n : failures > 0\n ? 'partial'\n : 'blockvision',\n };\n\n // -------------------------------------------------------------\n // Sticky-positive write rules (v0.54 — see header for the\n // four-state truth table). `stickyBasis` was captured inside\n // the lock above so it reflects the freshest known state at\n // leader-entry time (not the pre-lock observation, which may\n // have raced a deleting writer).\n // -------------------------------------------------------------\n const cachedPositive =\n stickyBasis &&\n stickyBasis.data.totalUsd > 0 &&\n fanoutAt - stickyBasis.pricedAt < DEFI_STICKY_TTL_SEC * 1000;\n\n if (summary.source === 'blockvision') {\n // Fully successful — overwrites unconditionally.\n await safeStoreSet(store, address, { data: summary, pricedAt: fetchedAt });\n return summary;\n }\n\n if (summary.source === 'partial' && summary.totalUsd > 0) {\n // Observed real value despite a failure — write but with a\n // short fresh-TTL so the next reader retries the failing\n // protocols within 15s.\n await safeStoreSet(store, address, { data: summary, pricedAt: fetchedAt });\n return summary;\n }\n\n // partial+0 OR degraded — fall back to the sticky cache if we\n // have a positive entry that's fresher than 30 minutes.\n if (cachedPositive) {\n const stale: DefiSummary = {\n ...stickyBasis!.data,\n source: 'partial-stale',\n };\n // Don't write — preserve the original `pricedAt` so the UI\n // can render an honest \"last refresh Nm ago\" caveat.\n // Re-writing would reset the age and hide the staleness.\n return stale;\n }\n\n // No fallback available — return as-is, don't cache so the\n // next caller retries BlockVision.\n return summary;\n },\n {\n // Followers poll the DeFi cache while the leader fans out.\n // Returns non-null only when the leader has written a\n // fresh-for-source entry — stale entries keep the poll going.\n pollCache: async () => {\n const e = await safeDefiStoreGet(store, address);\n if (!e) return null;\n const ageMs = Date.now() - e.pricedAt;\n return ageMs < freshTtlForSource(e.data.source) ? e.data : null;\n },\n },\n );\n } finally {\n defiInflight.delete(address);\n }\n })();\n\n defiInflight.set(address, inflight);\n return inflight;\n}\n\nasync function fetchOneDefiProtocol(\n address: string,\n protocol: DefiProtocol,\n apiKey: string,\n retryStats?: { attemptCount: number },\n): Promise<Record<string, unknown> | null> {\n const url = `${BLOCKVISION_BASE}/account/defiPortfolio?address=${encodeURIComponent(address)}&protocol=${protocol}`;\n const signal = AbortSignal.timeout(DEFI_PORTFOLIO_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchBlockVisionWithRetry(\n url,\n {\n headers: { 'x-api-key': apiKey, accept: 'application/json' },\n signal,\n },\n { signal, retryStats },\n );\n } catch (err) {\n console.warn(`[defi] ${protocol} fetch threw:`, err);\n return null;\n }\n if (!res.ok) {\n console.warn(`[defi] ${protocol} HTTP ${res.status}`);\n return null;\n }\n let json: BlockVisionDefiResponse;\n try {\n json = (await res.json()) as BlockVisionDefiResponse;\n } catch (err) {\n console.warn(`[defi] ${protocol} JSON parse failed:`, err);\n return null;\n }\n if (json.code !== 200 || !json.result) return null;\n return json.result;\n}\n\n// ---------------------------------------------------------------------------\n// Shape extraction — generic walker\n//\n// Recursively walks a protocol's response and sums net USD value, handling\n// the common shape patterns BlockVision returns:\n//\n// - Paired LPs: {coinTypeA, coinTypeB, balanceA, balanceB} with X/Y and\n// tokenX/Y aliases (Cetus/Bluefin/Haedal/Steamm/Turbos/Magma/Ferra/\n// FlowX/Kriya/Momentum/BlueMove); decimals can be at sibling\n// (coinTypeADecimals, decimalsA) or nested (coinA.decimals).\n// - Single-coin: {coinType, amount/balance/value, decimals?} with\n// `type: 'Borrow'` flag for NAVI-style flat lists.\n// - Pre-USD totals: Scallop's totalSupplyValue / totalDebtValue /\n// totalCollateralValue / totalLockedScaValue at root.\n//\n// Debt detection happens in two ways: the parent key (`borrows`, `debt`,\n// `borrowings` → flips debtSide for the entire subtree) OR the item's own\n// `type` field set to `'Borrow'` (NAVI flat list).\n//\n// Reward / fee branches (`rewards`, `fees`, `pendingRewards`, etc.) are\n// skipped entirely — those amounts are typically already implicit in the\n// position's principal value, and double-counting them inflates net worth.\n// Power users rarely have unclaimed-reward stacks worth >1% of their LP.\n// ---------------------------------------------------------------------------\n\nconst PAIR_A_COIN_KEYS = ['coinTypeA', 'coinTypeX', 'tokenXType'] as const;\nconst PAIR_B_COIN_KEYS = ['coinTypeB', 'coinTypeY', 'tokenYType'] as const;\nconst PAIR_A_AMOUNT_KEYS = [\n 'balanceA',\n 'amountA',\n 'coinAmountA',\n 'coinAAmount',\n 'coinTypeAAmount',\n 'tokenXBalance',\n 'tokenXAmount',\n 'amountX',\n 'valueA',\n] as const;\nconst PAIR_B_AMOUNT_KEYS = [\n 'balanceB',\n 'amountB',\n 'coinAmountB',\n 'coinBAmount',\n 'coinTypeBAmount',\n 'tokenYBalance',\n 'tokenYAmount',\n 'amountY',\n 'valueB',\n] as const;\nconst PAIR_A_DECIMALS_KEYS = ['coinTypeADecimals', 'tokenXDecimals', 'decimalsA'] as const;\nconst PAIR_B_DECIMALS_KEYS = ['coinTypeBDecimals', 'tokenYDecimals', 'decimalsB'] as const;\n\nconst SINGLE_COIN_KEYS = ['coinType', 'depositToken', 'token'] as const;\nconst SINGLE_AMOUNT_KEYS = ['amount', 'balance', 'value', 'equity'] as const;\nconst SINGLE_DECIMALS_KEYS = ['decimals', 'decimal', 'coinDecimals'] as const;\n\nconst DEBT_KEYS = new Set([\n 'borrow',\n 'borrows',\n 'debt',\n 'debts',\n 'borrowings',\n 'borrowedpools',\n]);\n// Skip reward/fee/incentive subtrees so we don't double-count pending yield\n// already implied by the position principal value.\nconst SKIP_KEYS = new Set([\n 'rewards',\n 'reward',\n 'fees',\n 'fee',\n 'pendingrewards',\n 'incentiveinfos',\n 'feereward',\n 'incentivereward',\n]);\n\nfunction isCoinTypeString(v: unknown): v is string {\n if (typeof v !== 'string' || !v.includes('::')) return false;\n // Accept both `0x…::module::TYPE` and unprefixed `…::module::TYPE`\n // (Typus's `depositToken` / `rewardsToken` omit the leading `0x`).\n return v.startsWith('0x') || /^[0-9a-fA-F]/.test(v);\n}\n\nfunction ensure0xPrefix(coinType: string): string {\n return coinType.startsWith('0x') ? coinType : '0x' + coinType;\n}\n\nfunction isAmountValue(v: unknown): v is string | number {\n return (\n (typeof v === 'string' && v.trim().length > 0) ||\n (typeof v === 'number' && Number.isFinite(v))\n );\n}\n\nfunction isFiniteNumber(v: unknown): v is number {\n return typeof v === 'number' && Number.isFinite(v);\n}\n\nfunction pickField<T>(\n obj: Record<string, unknown>,\n keys: readonly string[],\n predicate: (v: unknown) => v is T,\n): T | undefined {\n for (const k of keys) {\n const v = obj[k];\n if (predicate(v)) return v;\n }\n return undefined;\n}\n\nfunction nestedDecimals(node: unknown): number | undefined {\n if (!node || typeof node !== 'object') return undefined;\n const obj = node as Record<string, unknown>;\n if (typeof obj.decimals === 'number') return obj.decimals;\n return undefined;\n}\n\n/**\n * Convert a BlockVision amount field to a human-readable token quantity.\n * BlockVision is inconsistent across protocols:\n * - integer string (\"229380000000\") or integer number (1485) → raw,\n * divide by 10^decimals\n * - decimal-string (\"4.240927787\") or non-integer JS number (4.24) →\n * already human-readable, return as-is\n */\nfunction toHumanQuantity(raw: string | number, decimalsHint: number | undefined): number {\n if (typeof raw === 'number') {\n if (!Number.isFinite(raw)) return 0;\n if (!Number.isInteger(raw)) return raw;\n if (decimalsHint != null) return raw / 10 ** decimalsHint;\n return raw;\n }\n const trimmed = raw.trim();\n if (trimmed.length === 0) return 0;\n if (trimmed.includes('.') || trimmed.includes('e') || trimmed.includes('E')) {\n const n = Number(trimmed);\n return Number.isFinite(n) ? n : 0;\n }\n const n = Number(trimmed);\n if (!Number.isFinite(n)) return 0;\n const dec = decimalsHint ?? 9;\n return n / 10 ** dec;\n}\n\nfunction priceFor(coinType: string, prices: Record<string, number>): number {\n const prefixed = ensure0xPrefix(coinType);\n const norm = normalizeCoinType(prefixed);\n return prices[norm] ?? prices[prefixed] ?? prices[coinType] ?? STABLE_USD_PRICES[norm] ?? 0;\n}\n\nfunction toUsd(\n coinType: string,\n raw: unknown,\n decimalsHint: number | undefined,\n prices: Record<string, number>,\n): number {\n if (raw == null || (typeof raw !== 'string' && typeof raw !== 'number')) return 0;\n if (typeof raw === 'string' && raw.trim().length === 0) return 0;\n const prefixed = ensure0xPrefix(coinType);\n const decimals =\n typeof decimalsHint === 'number' ? decimalsHint : getDecimalsForCoinType(prefixed);\n const human = toHumanQuantity(raw, decimals);\n if (!Number.isFinite(human)) return 0;\n return human * priceFor(prefixed, prices);\n}\n\ninterface ExtractedPair {\n coinTypeA: string;\n amountA: string | number;\n decimalsA: number | undefined;\n coinTypeB: string;\n amountB: string | number;\n decimalsB: number | undefined;\n}\n\nfunction extractPair(obj: Record<string, unknown>): ExtractedPair | null {\n const coinTypeA = pickField(obj, PAIR_A_COIN_KEYS, isCoinTypeString);\n const coinTypeB = pickField(obj, PAIR_B_COIN_KEYS, isCoinTypeString);\n if (!coinTypeA || !coinTypeB) return null;\n const amountA = pickField(obj, PAIR_A_AMOUNT_KEYS, isAmountValue);\n const amountB = pickField(obj, PAIR_B_AMOUNT_KEYS, isAmountValue);\n if (amountA == null || amountB == null) return null;\n const decimalsA =\n pickField(obj, PAIR_A_DECIMALS_KEYS, isFiniteNumber) ??\n nestedDecimals(obj.coinA);\n const decimalsB =\n pickField(obj, PAIR_B_DECIMALS_KEYS, isFiniteNumber) ??\n nestedDecimals(obj.coinB);\n return { coinTypeA, amountA, decimalsA, coinTypeB, amountB, decimalsB };\n}\n\ninterface ExtractedSingle {\n coinType: string;\n amount: string | number;\n decimals: number | undefined;\n isBorrow: boolean;\n}\n\nfunction extractSingle(obj: Record<string, unknown>): ExtractedSingle | null {\n const coinType = pickField(obj, SINGLE_COIN_KEYS, isCoinTypeString);\n if (!coinType) return null;\n const amount = pickField(obj, SINGLE_AMOUNT_KEYS, isAmountValue);\n if (amount == null) return null;\n const decimals = pickField(obj, SINGLE_DECIMALS_KEYS, isFiniteNumber);\n const isBorrow = obj.type === 'Borrow';\n return { coinType, amount, decimals, isBorrow };\n}\n\nfunction walkProtocolResponse(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n let total = 0;\n walk(result, false);\n return total;\n\n function walk(node: unknown, debtSide: boolean): void {\n if (!node || typeof node !== 'object') return;\n if (Array.isArray(node)) {\n for (const item of node) walk(item, debtSide);\n return;\n }\n const obj = node as Record<string, unknown>;\n\n // Scallop pre-USD totals (root-level only, but cheap to check anywhere).\n if (typeof obj.totalSupplyValue === 'number') total += obj.totalSupplyValue;\n if (typeof obj.totalCollateralValue === 'number') total += obj.totalCollateralValue;\n if (typeof obj.totalLockedScaValue === 'number') total += obj.totalLockedScaValue;\n if (typeof obj.totalDebtValue === 'number') total -= obj.totalDebtValue;\n\n const pair = extractPair(obj);\n if (pair) {\n const a = toUsd(pair.coinTypeA, pair.amountA, pair.decimalsA, prices);\n const b = toUsd(pair.coinTypeB, pair.amountB, pair.decimalsB, prices);\n total += debtSide ? -(a + b) : a + b;\n } else {\n const single = extractSingle(obj);\n if (single) {\n const usd = toUsd(single.coinType, single.amount, single.decimals, prices);\n total += debtSide || single.isBorrow ? -usd : usd;\n }\n }\n\n for (const [k, v] of Object.entries(obj)) {\n const lk = k.toLowerCase();\n if (SKIP_KEYS.has(lk)) continue;\n const childDebt = debtSide || DEBT_KEYS.has(lk);\n walk(v, childDebt);\n }\n }\n}\n\n/**\n * Walks the response object recursively and collects every string value at\n * any key that looks like a Sui coin-type field. Used to discover which\n * token prices we still need to fetch before normalisers run. Coin types\n * may be returned without the `0x` prefix (Typus); we normalize before\n * adding so the price-cache key matches subsequent lookups.\n */\nfunction collectCoinTypes(obj: unknown, out: Set<string>): void {\n if (!obj || typeof obj !== 'object') return;\n if (Array.isArray(obj)) {\n for (const x of obj) collectCoinTypes(x, out);\n return;\n }\n for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n if (typeof v === 'string' && isCoinTypeString(v)) {\n const lk = k.toLowerCase();\n if (\n lk.includes('cointype') ||\n lk === 'tokenxtype' ||\n lk === 'tokenytype' ||\n lk === 'deposittoken' ||\n lk === 'rewardstoken' ||\n lk === 'token' ||\n lk === 'coinaddress' ||\n lk === 'phantomtype' ||\n lk === 'typename'\n ) {\n out.add(ensure0xPrefix(v));\n }\n } else if (typeof v === 'object' && v !== null) {\n collectCoinTypes(v, out);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Bespoke handlers — protocols whose shape the generic walker can't infer\n// (implied coin types or non-standard amount/decimals nesting).\n// ---------------------------------------------------------------------------\n\ninterface BluefinLp {\n coinTypeA?: string;\n coinTypeB?: string;\n coinAmountA?: number | string;\n coinAmountB?: number | string;\n}\n\nfunction normalizeBluefin(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data =\n (result.bluefin as {\n lps?: BluefinLp[];\n usdcVault?: { amount?: number | string };\n blueVault?: { amount?: number | string };\n }) ?? {};\n let total = 0;\n for (const lp of data.lps ?? []) {\n if (lp.coinTypeA && lp.coinAmountA != null) {\n total += toUsd(lp.coinTypeA, lp.coinAmountA, undefined, prices);\n }\n if (lp.coinTypeB && lp.coinAmountB != null) {\n total += toUsd(lp.coinTypeB, lp.coinAmountB, undefined, prices);\n }\n }\n // Vaults expose a raw `amount` without a coinType — usdcVault implies USDC\n // (6dp) and blueVault implies BLUE (9dp) per the BlockVision schema.\n if (data.usdcVault?.amount != null) {\n total += toUsd(USDC_TYPE_FULL, data.usdcVault.amount, 6, prices);\n }\n if (data.blueVault?.amount != null) {\n total += toUsd(BLUE_TYPE_FULL, data.blueVault.amount, 9, prices);\n }\n return total;\n}\n\nfunction normalizeHaedal(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data =\n (result.haedal as {\n lps?: Array<{\n coinTypeA?: string;\n coinTypeB?: string;\n balanceA?: number | string;\n balanceB?: number | string;\n }>;\n stakings?: Array<{ sui_amount?: number | string }>;\n }) ?? {};\n let total = 0;\n for (const lp of data.lps ?? []) {\n if (lp.coinTypeA && lp.balanceA != null) {\n total += toUsd(lp.coinTypeA, lp.balanceA, undefined, prices);\n }\n if (lp.coinTypeB && lp.balanceB != null) {\n total += toUsd(lp.coinTypeB, lp.balanceB, undefined, prices);\n }\n }\n for (const stake of data.stakings ?? []) {\n if (stake.sui_amount != null) {\n total += toUsd(SUI_TYPE_FULL, stake.sui_amount, 9, prices);\n }\n }\n return total;\n}\n\ninterface BareStaking {\n amount?: number | string;\n sui_amount?: number | string;\n}\n\nfunction sumBareStakings(\n data: { stakings?: BareStaking[] } | undefined,\n impliedCoinType: string,\n decimals: number,\n prices: Record<string, number>,\n): number {\n if (!data) return 0;\n let total = 0;\n for (const s of data.stakings ?? []) {\n const amt = s.sui_amount ?? s.amount;\n if (amt != null) total += toUsd(impliedCoinType, amt, decimals, prices);\n }\n return total;\n}\n\nfunction normalizeSuistake(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data = result.suistake as { stakings?: BareStaking[] } | undefined;\n return sumBareStakings(data, SUI_TYPE_FULL, 9, prices);\n}\n\nfunction normalizeWalrus(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const data = result.walrus as { stakings?: BareStaking[] } | undefined;\n return sumBareStakings(data, WAL_TYPE_FULL, 9, prices);\n}\n\nfunction normalizeSuinsStaking(\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n // BlockVision may expose this under either `suins-staking`, `suinsStaking`,\n // or `suins_staking` — probe all three since the doc uses the kebab form\n // for the protocol param but JS conventions tend to camelCase response keys.\n const data =\n (result['suins-staking'] as { stakings?: BareStaking[] } | undefined) ??\n (result.suinsStaking as { stakings?: BareStaking[] } | undefined) ??\n (result.suins_staking as { stakings?: BareStaking[] } | undefined);\n return sumBareStakings(data, NS_TYPE_FULL, 6, prices);\n}\n\nconst BESPOKE_NORMALIZERS: Partial<\n Record<DefiProtocol, (result: Record<string, unknown>, prices: Record<string, number>) => number>\n> = {\n bluefin: normalizeBluefin,\n haedal: normalizeHaedal,\n suistake: normalizeSuistake,\n walrus: normalizeWalrus,\n 'suins-staking': normalizeSuinsStaking,\n};\n\nfunction normalizeProtocol(\n protocol: DefiProtocol,\n result: Record<string, unknown>,\n prices: Record<string, number>,\n): number {\n const bespoke = BESPOKE_NORMALIZERS[protocol];\n if (bespoke) return bespoke(result, prices);\n return walkProtocolResponse(result, prices);\n}\n\nexport async function clearDefiCache(): Promise<void> {\n // Clears both the active store (Redis or in-memory) and any\n // in-flight promises. Async because store.clear() may need to\n // round-trip to Redis. Existing callers (tests, post-write refresh)\n // were sync and didn't await — we keep the promise return so new\n // callers can await but legacy fire-and-forget still works.\n await getDefiCacheStore().clear();\n defiInflight.clear();\n}\n\nexport async function clearDefiCacheFor(address: string): Promise<void> {\n await getDefiCacheStore().delete(address);\n defiInflight.delete(address);\n}\n\n/**\n * Wipe the wallet portfolio cache plus any in-flight promises.\n *\n * Async because the underlying store may be Redis-backed. Existing\n * fire-and-forget callers (tests, `clearDefiCache`-shape utilities)\n * still work since they just don't `await` — they get the same\n * effective \"schedule the clear\" behavior.\n */\nexport async function clearPortfolioCache(): Promise<void> {\n await getWalletCacheStore().clear();\n portfolioInflight.clear();\n}\n\n/**\n * [v1.4 — Day 2.5] Per-address invalidator.\n *\n * Engine `runPostWriteRefresh` calls this right before the 1.5s\n * Sui-RPC-indexer-lag delay so the next `fetchAddressPortfolio` for\n * the affected address is forced to hit BlockVision again instead of\n * returning the cached pre-write snapshot.\n *\n * **MUST be awaited** — pre-PR-1 the cache was a synchronous Map and\n * the `engine.ts` caller fired-and-forgot. Now the underlying store\n * is async (Upstash in production), so without `await` the next\n * `balance_check` races the Redis delete and can fetch the stale\n * pre-write balance — exactly the symptom v0.54 sticky cache shipped\n * to fix. `engine.ts` `runPostWriteRefresh` was updated to await this\n * in the same PR.\n *\n * No-op when `address` doesn't match a cached entry — cheap to call\n * unconditionally on every write.\n */\nexport async function clearPortfolioCacheFor(address: string): Promise<void> {\n await getWalletCacheStore().delete(address);\n portfolioInflight.delete(address);\n}\n\nexport function clearPriceMapCache(): void {\n priceMapCache = null;\n}\n","// ---------------------------------------------------------------------------\n// Audric canonical-API client.\n//\n// When the engine runs server-side inside the Audric Next.js host, every\n// portfolio / history / price read should resolve through Audric's\n// canonical fetchers (`apps/web/lib/portfolio.ts`,\n// `apps/web/lib/transaction-history.ts`) so that the LLM, the dashboard,\n// and the daily cron all see identical numbers. This file is the engine's\n// thin client for those routes.\n//\n// Activation: set `T2000_AUDRIC_API` (preferred) or fall back to\n// `AUDRIC_INTERNAL_API_URL` / `NEXT_PUBLIC_APP_URL`. When neither is\n// available — e.g. CLI, MCP server, or any non-Audric embedding — the\n// helpers return `null` and callers MUST use their existing in-engine\n// path. This preserves the engine's standalone usability.\n//\n// All calls inherit the request `AbortSignal` from `ToolContext.signal`\n// so engine-level cancellation propagates to in-flight HTTP fetches.\n// ---------------------------------------------------------------------------\n\nimport type { AddressPortfolio, DefiSummary, PortfolioCoin } from './blockvision-prices.js';\nimport type { ServerPositionData } from './types.js';\n\nconst FETCH_TIMEOUT_MS = 6_000;\n\n/**\n * Resolve the audric API base URL from the engine's env shim, falling\n * back to `process.env`. Returns `null` when no override is configured —\n * callers MUST treat this as \"use in-engine fallback path\".\n *\n * Lookup order (first defined wins):\n * 1. `env.T2000_AUDRIC_API` — canonical override\n * 2. `process.env.T2000_AUDRIC_API` — same, picked up directly\n * 3. `env.AUDRIC_INTERNAL_API_URL` — legacy alias from audric host\n * 4. `process.env.AUDRIC_INTERNAL_API_URL`\n * 5. `process.env.NEXT_PUBLIC_APP_URL` — last-ditch host hint\n */\nexport function getAudricApiBase(env?: Record<string, string>): string | null {\n const fromEnv =\n env?.T2000_AUDRIC_API ??\n env?.AUDRIC_INTERNAL_API_URL ??\n null;\n if (fromEnv && fromEnv.trim().length > 0) return fromEnv.replace(/\\/$/, '');\n\n const fromProcess =\n process.env.T2000_AUDRIC_API ??\n process.env.AUDRIC_INTERNAL_API_URL ??\n process.env.NEXT_PUBLIC_APP_URL ??\n null;\n if (fromProcess && fromProcess.trim().length > 0) return fromProcess.replace(/\\/$/, '');\n\n return null;\n}\n\ninterface AudricPortfolioWire {\n address: string;\n netWorthUsd: number;\n walletValueUsd: number;\n walletAllocations: Record<string, number>;\n wallet: PortfolioCoin[];\n positions: {\n savings: number;\n borrows: number;\n savingsRate: number;\n healthFactor: number | null;\n maxBorrow: number;\n pendingRewards: number;\n supplies: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n borrowsDetail: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n };\n estimatedDailyYield: number;\n source: AddressPortfolio['source'];\n pricedAt: number;\n // [Bug — 2026-04-28] Surface DeFi from audric's canonical /api/portfolio.\n // Pre-fix the engine wire shape stripped these fields, so any tool that\n // resolved through the audric snapshot path (portfolio_analysis,\n // future timeline tools) silently dropped DeFi value from totals — even\n // though balance_check (which calls fetchAddressDefiPortfolio directly)\n // reported them correctly. Same SSOT-divergence class as the v0.54\n // FullPortfolioCanvas bug, manifesting in a different tool.\n // Optional on the wire so older audric deploys (pre-defi) don't error.\n defiValueUsd?: number;\n defiSource?: DefiSummary['source'];\n}\n\nexport interface AudricPortfolioResult {\n /** Wallet half — directly compatible with the existing `AddressPortfolio` shape. */\n portfolio: AddressPortfolio;\n /** NAVI lending positions, normalized to the engine's `ServerPositionData`. */\n positions: ServerPositionData;\n /** Net worth derived audric-side (`wallet + savings + defi - borrows`). */\n netWorthUsd: number;\n /** `savings * savingsRate / 365`, capped at 0. */\n estimatedDailyYield: number;\n /** Per-symbol balance map — convenient for adapters that already used `WalletBalances`. */\n walletAllocations: Record<string, number>;\n /**\n * [Bug — 2026-04-28] Aggregated DeFi value (Cetus LPs, Bluefin, Suilend,\n * etc.) when available. `defiSource === 'degraded'` when audric's wire\n * didn't include the field — callers should treat that as \"fall back to\n * a direct fetchAddressDefiPortfolio call\" (same convention used\n * inside the audric web app's UI components).\n */\n defiValueUsd: number;\n defiSource: DefiSummary['source'];\n}\n\n/**\n * Fetch the canonical portfolio snapshot from audric. Returns `null` if\n * audric isn't configured for this runtime, or if the request fails for\n * any reason — callers MUST fall back to the in-engine BlockVision +\n * NAVI path on `null`.\n */\nexport async function fetchAudricPortfolio(\n address: string,\n env?: Record<string, string>,\n signal?: AbortSignal,\n): Promise<AudricPortfolioResult | null> {\n const base = getAudricApiBase(env);\n if (!base) return null;\n\n try {\n const res = await fetch(\n `${base}/api/portfolio?address=${encodeURIComponent(address)}`,\n { signal: signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS) },\n );\n if (!res.ok) {\n console.warn(`[audric-api] portfolio ${address.slice(0, 10)} → HTTP ${res.status}`);\n return null;\n }\n const json = (await res.json()) as AudricPortfolioWire;\n\n const portfolio: AddressPortfolio = {\n coins: Array.isArray(json.wallet) ? json.wallet : [],\n totalUsd: json.walletValueUsd ?? 0,\n pricedAt: json.pricedAt ?? Date.now(),\n source: json.source ?? 'blockvision',\n };\n\n const positions: ServerPositionData = {\n savings: json.positions?.savings ?? 0,\n borrows: json.positions?.borrows ?? 0,\n savingsRate: json.positions?.savingsRate ?? 0,\n healthFactor: json.positions?.healthFactor ?? null,\n maxBorrow: json.positions?.maxBorrow ?? 0,\n pendingRewards: json.positions?.pendingRewards ?? 0,\n supplies: json.positions?.supplies ?? [],\n // The engine type calls this `borrows_detail`; audric's wire shape\n // calls it `borrowsDetail`. Normalize on the engine side so\n // downstream tools can keep their existing field names.\n borrows_detail: json.positions?.borrowsDetail ?? [],\n };\n\n return {\n portfolio,\n positions,\n netWorthUsd: json.netWorthUsd ?? portfolio.totalUsd + positions.savings - positions.borrows,\n estimatedDailyYield: json.estimatedDailyYield ?? 0,\n walletAllocations: json.walletAllocations ?? {},\n // Default to 'degraded' (not 'partial') when the wire shape lacks\n // DeFi: 'partial' implies \"we tried and got partial data\" which is\n // misleading for a route that simply doesn't return the field.\n // Callers that need DeFi must fall back to a direct fetch on\n // 'degraded' — exactly the convention BalanceCard already uses.\n defiValueUsd: typeof json.defiValueUsd === 'number' ? json.defiValueUsd : 0,\n defiSource: json.defiSource ?? 'degraded',\n };\n } catch (err) {\n console.warn(`[audric-api] portfolio ${address.slice(0, 10)} fetch failed:`, err);\n return null;\n }\n}\n\ninterface AudricHistoryWireItem {\n digest: string;\n action: string;\n label?: string;\n direction?: 'in' | 'out';\n amount?: number;\n asset?: string;\n counterparty?: string;\n timestamp: number;\n gasCost?: number;\n}\n\nexport interface AudricHistoryRecord {\n digest: string;\n action: string;\n label?: string;\n direction?: 'in' | 'out';\n amount?: number;\n asset?: string;\n /** Counterparty address (only set for transfers with a clear recipient). */\n recipient?: string;\n timestamp: number;\n date?: string;\n gasCost?: number;\n}\n\n/**\n * Fetch the canonical transaction history list from audric. Same fall\n * back contract as `fetchAudricPortfolio` — `null` means \"use in-engine\n * Sui-RPC path\". Audric's `/api/history` already merges `FromAddress` +\n * `ToAddress`, dedupes by digest, and parses Move calls via\n * `@t2000/sdk`'s shared parser, so the wire shape is a 1:1 match for the\n * engine's existing `TxRecord` once we rename `counterparty` →\n * `recipient`.\n */\nexport async function fetchAudricHistory(\n address: string,\n opts: { limit?: number },\n env?: Record<string, string>,\n signal?: AbortSignal,\n): Promise<AudricHistoryRecord[] | null> {\n const base = getAudricApiBase(env);\n if (!base) return null;\n\n const params = new URLSearchParams({ address });\n if (opts.limit != null) params.set('limit', String(opts.limit));\n\n try {\n const res = await fetch(`${base}/api/history?${params}`, {\n signal: signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n if (!res.ok) {\n console.warn(`[audric-api] history ${address.slice(0, 10)} → HTTP ${res.status}`);\n return null;\n }\n const json = (await res.json()) as { items?: AudricHistoryWireItem[] };\n const items = Array.isArray(json.items) ? json.items : [];\n\n return items.map((item) => ({\n digest: item.digest,\n action: item.action,\n label: item.label,\n direction: item.direction,\n amount: item.amount,\n asset: item.asset,\n recipient: item.counterparty,\n timestamp: item.timestamp,\n date: item.timestamp > 0 ? new Date(item.timestamp).toISOString() : undefined,\n gasCost: item.gasCost,\n }));\n } catch (err) {\n console.warn(`[audric-api] history ${address.slice(0, 10)} fetch failed:`, err);\n return null;\n }\n}\n","// ---------------------------------------------------------------------------\n// Sui address + SuiNS normalization — single source of truth.\n//\n// Background. Six read tools (balance, health, savings, history,\n// activity-summary, portfolio-analysis) accept an optional `address`\n// parameter so the LLM can inspect any public Sui wallet. Pre-v1.2 each\n// tool re-implemented the same `/^0x[a-fA-F0-9]{1,64}$/` regex inline AND\n// rejected SuiNS names (`obehi.sui`) entirely — the LLM had no way to\n// answer \"transaction list for obehi.sui\" because the schema would\n// reject the name before the call ever reached the tool body.\n//\n// This module is the canonical normalizer. It consolidates the regex,\n// adds SuiNS resolution via Sui RPC's `suix_resolveNameServiceAddress`,\n// and returns a structured `{ address, suinsName, raw }` triple so\n// downstream tools can both query the right 0x address AND surface the\n// name on result cards (e.g. titling \"Transaction history · obehi.sui\"\n// instead of \"Transaction history · 0x1234…abcd\").\n//\n// Single source of truth — see `.cursor/rules/single-source-of-truth.mdc`\n// and `.cursor/rules/engineering-principles.mdc` Principle 2.\n// ---------------------------------------------------------------------------\n\nconst SUI_MAINNET_URL = 'https://fullnode.mainnet.sui.io:443';\n\n/**\n * Canonical 0x-address shape. Loose lower bound (>= 1 hex char) so\n * pre-v1.0 short addresses still validate; tools that need a full 64-hex\n * address can additionally check `length === 66`. Case-insensitive on\n * the `0x` prefix because some upstream callers (and historic tests)\n * uppercase the prefix as part of address normalization tests; the\n * normalizer always returns the lowercased canonical form regardless.\n */\nexport const SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;\n\n/**\n * Strict canonical 0x-address shape (66 chars total). Used by the\n * resolver's \"looks like\" check to disambiguate \"user pasted an\n * address\" vs \"user typed a SuiNS name\".\n */\nexport const SUI_ADDRESS_STRICT_REGEX = /^0x[a-fA-F0-9]{64}$/i;\n\n/**\n * Mirrors the pattern in `audric/apps/web/lib/suins-resolver.ts` so the\n * host-side send executor and the engine-side read normalizer agree on\n * what counts as a SuiNS name. SuiNS allows nested labels (`team.alex.sui`)\n * but every label must use only `[a-z0-9-]`.\n */\nexport const SUINS_NAME_REGEX = /^[a-z0-9-]+(\\.[a-z0-9-]+)*\\.sui$/;\n\nexport class InvalidAddressError extends Error {\n constructor(public readonly raw: string) {\n super(\n `\"${raw}\" isn't a valid Sui address or SuiNS name. ` +\n `Pass a 0x-prefixed hex address (e.g. 0x40cd…3e62) or a SuiNS name ending in .sui (e.g. alex.sui).`,\n );\n this.name = 'InvalidAddressError';\n }\n}\n\nexport class SuinsNotRegisteredError extends Error {\n constructor(public readonly name_: string) {\n super(\n `\"${name_}\" isn't a registered SuiNS name. Double-check the spelling, ` +\n `or paste the full Sui address (0x… 64 hex characters).`,\n );\n this.name = 'SuinsNotRegisteredError';\n }\n}\n\nexport class SuinsRpcError extends Error {\n constructor(public readonly name_: string, detail: string) {\n super(`SuiNS lookup failed for \"${name_}\" (${detail}). Try again, or paste the full Sui address.`);\n this.name = 'SuinsRpcError';\n }\n}\n\n/**\n * Returns true if `value` looks like a SuiNS name (case-insensitive).\n * Cheap synchronous check — use to avoid an unnecessary RPC round-trip\n * for inputs that obviously aren't names (0x addresses, contact handles).\n */\nexport function looksLikeSuiNs(value: string): boolean {\n if (!value) return false;\n return SUINS_NAME_REGEX.test(value.trim().toLowerCase());\n}\n\n/**\n * Resolve a SuiNS name to its on-chain Sui address via the public\n * `suix_resolveNameServiceAddress` JSON-RPC method. Returns `null` if\n * the name resolves to no address (= not registered or expired). Throws\n * `SuinsRpcError` on RPC/network failure.\n *\n * The host SHOULD pass a `rpcUrl` that includes any vendor key (e.g.\n * audric's BlockVision-keyed URL) so the call benefits from the host's\n * paid retry/cache budget. Falls back to the public mainnet endpoint.\n */\nexport async function resolveSuinsViaRpc(\n rawName: string,\n ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<string | null> {\n const name = rawName.trim().toLowerCase();\n if (!SUINS_NAME_REGEX.test(name)) {\n throw new InvalidAddressError(rawName);\n }\n\n const url = ctx.suiRpcUrl || SUI_MAINNET_URL;\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_resolveNameServiceAddress',\n params: [name],\n }),\n signal: ctx.signal ?? AbortSignal.timeout(8_000),\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(name, msg);\n }\n\n if (!res.ok) {\n throw new SuinsRpcError(name, `HTTP ${res.status}`);\n }\n\n let body: { result?: string | null; error?: { code: number; message: string } };\n try {\n body = (await res.json()) as typeof body;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(name, `JSON parse failed: ${msg}`);\n }\n\n if (body.error) {\n throw new SuinsRpcError(name, body.error.message);\n }\n\n // result is the 0x…64-hex address, or null when the name has never\n // been registered (or has expired and the record was reaped).\n return body.result ?? null;\n}\n\n/**\n * Reverse-resolve a 0x address to its registered SuiNS names via\n * `suix_resolveNameServiceNames`. Returns the names sorted by the\n * registry (the first entry is conventionally the user's \"primary\"\n * name on dApps that show one), or `[]` when the address has no\n * SuiNS records. Throws `SuinsRpcError` on RPC/network failure.\n *\n * Why this is its own helper (not folded into `normalizeAddressInput`):\n * a reverse lookup adds a second RPC round-trip per tool call. We don't\n * want every read tool that takes an `address` to silently double its\n * latency. The lookup primitive is opt-in via the `resolve_suins` tool;\n * normalizers stay forward-only.\n */\nexport async function resolveAddressToSuinsViaRpc(\n rawAddress: string,\n ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<string[]> {\n const address = rawAddress.trim().toLowerCase();\n if (!SUI_ADDRESS_REGEX.test(address)) {\n throw new InvalidAddressError(rawAddress);\n }\n\n const url = ctx.suiRpcUrl || SUI_MAINNET_URL;\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_resolveNameServiceNames',\n params: [address],\n }),\n signal: ctx.signal ?? AbortSignal.timeout(8_000),\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(address, msg);\n }\n\n if (!res.ok) {\n throw new SuinsRpcError(address, `HTTP ${res.status}`);\n }\n\n // SuiNS reverse-lookup returns a paginated page object. We don't\n // bother paginating because (a) the LLM consumer only needs the\n // primary name, and (b) addresses with >50 names are vanishingly\n // rare. The first page (default 50) is the canonical view.\n let body: {\n result?: { data: string[]; nextCursor: string | null; hasNextPage: boolean };\n error?: { code: number; message: string };\n };\n try {\n body = (await res.json()) as typeof body;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SuinsRpcError(address, `JSON parse failed: ${msg}`);\n }\n\n if (body.error) {\n throw new SuinsRpcError(address, body.error.message);\n }\n\n return body.result?.data ?? [];\n}\n\nexport interface NormalizedAddress {\n /**\n * Canonical 0x-prefixed lowercase hex address. Always set on success.\n * Tools should use this for any downstream query (BlockVision, NAVI,\n * positionFetcher, etc.) and for cache keys.\n */\n address: string;\n /**\n * The user-facing name when the input was resolved via SuiNS, otherwise\n * `null`. Tools should stamp this on result data so card titles can\n * render \"Balance · obehi.sui\" instead of \"Balance · 0x1234…abcd\".\n */\n suinsName: string | null;\n /**\n * The original input (pre-normalization). Useful for error narration —\n * \"I tried to resolve `Obehi.Sui` and …\" reads better than the\n * post-trim/lowercase form.\n */\n raw: string;\n}\n\n/**\n * Canonical normalizer. Accepts a 0x address OR a SuiNS name; returns\n * a structured `NormalizedAddress`. Throws:\n * - `InvalidAddressError` if the input matches neither shape.\n * - `SuinsNotRegisteredError` if the SuiNS name is well-formed but\n * resolves to null (= not registered).\n * - `SuinsRpcError` if the RPC fails.\n *\n * Every read tool that accepts a user-supplied `address` parameter MUST\n * call this helper before any downstream lookup. Doing the check inline\n * (1) duplicates the regex, (2) silently rejects SuiNS names, (3) makes\n * cache keys inconsistent across tools (some lowercase, some not).\n */\nexport async function normalizeAddressInput(\n value: string,\n ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<NormalizedAddress> {\n const trimmed = value.trim();\n if (SUI_ADDRESS_REGEX.test(trimmed)) {\n return { address: trimmed.toLowerCase(), suinsName: null, raw: value };\n }\n if (looksLikeSuiNs(trimmed)) {\n const name = trimmed.toLowerCase();\n const address = await resolveSuinsViaRpc(name, ctx);\n if (!address) {\n throw new SuinsNotRegisteredError(name);\n }\n return { address: address.toLowerCase(), suinsName: name, raw: value };\n }\n throw new InvalidAddressError(value);\n}\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, requireAgent } from './utils.js';\nimport type { McpClientManager } from '../mcp-client.js';\nimport { NAVI_SERVER_NAME, NaviTools } from '../navi-config.js';\nimport {\n parseMcpJson,\n transformPositions,\n transformRewards,\n} from '../navi-transforms.js';\nimport {\n fetchAddressPortfolio,\n fetchAddressDefiPortfolio,\n type AddressPortfolio,\n type DefiSummary,\n} from '../blockvision-prices.js';\nimport { fetchAudricPortfolio, type AudricPortfolioResult } from '../audric-api.js';\nimport { normalizeAddressInput } from '../sui-address.js';\n\nconst GAS_RESERVE_SUI = 0.05;\n\n// vSUI (Volo's liquid-staked SUI). BlockVision sometimes lacks a price for\n// this token — when missing we read the official Volo exchange rate and\n// derive vSUI = rate × SUI price. See [v1.4.1 — M1'] for the rewrite that\n// mutates the portfolio in place.\nconst VSUI_COIN_TYPE =\n '0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT';\nconst SUI_COIN_TYPE = '0x2::sui::SUI';\nconst VSUI_FALLBACK_RATE = 1.05;\n\nasync function callNavi<T = unknown>(\n manager: McpClientManager,\n tool: string,\n args: Record<string, unknown> = {},\n): Promise<T> {\n const result = await manager.callTool(NAVI_SERVER_NAME, tool, args);\n if (result.isError) {\n const msg = result.content\n .filter((c: { type: string; text?: string }) => c.type === 'text' && c.text)\n .map((c: { type: string; text?: string }) => c.text!)\n .join(' ');\n throw new Error(`NAVI MCP error (${tool}): ${msg || 'unknown error'}`);\n }\n return parseMcpJson<T>(result.content);\n}\n\n/**\n * [v1.4.1 — M1'] Mutates `portfolio` in place to fill in the vSUI USD\n * price/value when BlockVision returned no price for it. Reads the\n * canonical exchange rate from Volo's public stats endpoint and falls\n * back to a hardcoded 1.05× SUI multiplier if the call fails.\n *\n * No-op when the wallet doesn't hold vSUI or BlockVision already returned\n * a price.\n */\nasync function applyVsuiPriceFallback(portfolio: AddressPortfolio): Promise<void> {\n const vsuiIdx = portfolio.coins.findIndex((c) => c.coinType === VSUI_COIN_TYPE);\n if (vsuiIdx === -1) return;\n const vsui = portfolio.coins[vsuiIdx];\n if (vsui.price != null) return;\n\n const suiCoin = portfolio.coins.find((c) => c.coinType === SUI_COIN_TYPE);\n const suiPrice = suiCoin?.price ?? null;\n if (suiPrice == null) return;\n\n let rate = VSUI_FALLBACK_RATE;\n try {\n const statsRes = await fetch('https://open-api.naviprotocol.io/api/volo/stats', {\n signal: AbortSignal.timeout(5_000),\n });\n if (statsRes.ok) {\n const json = (await statsRes.json()) as {\n data?: { exchange_rate?: number; exchangeRate?: number };\n exchange_rate?: number;\n exchangeRate?: number;\n };\n const data = json.data ?? json;\n rate = data.exchange_rate ?? data.exchangeRate ?? VSUI_FALLBACK_RATE;\n }\n } catch {\n // Network error — keep the hardcoded fallback rate.\n }\n\n const price = rate * suiPrice;\n const amount = Number(vsui.balance) / 10 ** vsui.decimals;\n const usdValue = Number.isFinite(amount) ? amount * price : null;\n const previousUsd = vsui.usdValue ?? 0;\n portfolio.coins[vsuiIdx] = { ...vsui, price, usdValue };\n if (usdValue != null) {\n portfolio.totalUsd = portfolio.totalUsd - previousUsd + usdValue;\n }\n}\n\nasync function loadPortfolio(\n address: string,\n blockvisionApiKey: string | undefined,\n fallbackRpcUrl: string | undefined,\n cache: Map<string, AddressPortfolio> | undefined,\n // [SPEC 8 v0.5.1 B3.2] Forward the per-tool retry counter so any\n // BlockVision retries during the wallet read surface as `attemptCount`\n // on the eventual `tool_result` event.\n retryStats?: { attemptCount: number },\n): Promise<AddressPortfolio> {\n if (cache) {\n const hit = cache.get(address);\n if (hit) return hit;\n }\n const portfolio = await fetchAddressPortfolio(address, blockvisionApiKey, fallbackRpcUrl, { retryStats });\n if (cache) cache.set(address, portfolio);\n return portfolio;\n}\n\nexport const balanceCheckTool = buildTool({\n name: 'balance_check',\n description:\n 'Get the full balance breakdown for the signed-in user OR any public Sui address or SuiNS name. Returns wallet holdings (tokens the address owns — NOT savings), NAVI savings deposits (USDC and/or USDsui deposited into NAVI Protocol earning yield), outstanding debt, pending rewards, gas reserve, total net worth, saveableUsdc (USDC wallet balance available to save), and saveableUsdsui (USDsui wallet balance available to save — surfaces only when > 0). IMPORTANT: wallet holdings like GOLD, SUI, USDT, USDe are NOT savings positions and are NOT saveable — only USDC and USDsui can be saved/borrowed. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v1.4 BlockVision] Wallet contents change after every send / swap /\n // save / etc. and the price half of this result is sourced from\n // BlockVision's Indexer REST API. Microcompact must NEVER dedupe these\n // calls — each one reflects a different on-chain + market snapshot.\n cacheable: false,\n\n async call(input, context) {\n /**\n * [v0.49] Address-scope: tool now accepts an optional `address` param\n * so the LLM can inspect any public Sui wallet (contacts, watched\n * addresses, etc.). Pre-v0.49 the tool only ever queried\n * `context.walletAddress`, which masked any contact-balance question\n * by silently returning the signed-in user's data instead. Falls back\n * to `context.walletAddress` when the param is absent. Stamps\n * `address` + `isSelfQuery` on the result so the UI can title cards\n * appropriately when rendering a non-self balance.\n *\n * The host-provided `positionFetcher(address)` takes an address\n * argument and works for any wallet, so savings / debt / rewards\n * automatically scope correctly. Empty wallets and unknown addresses\n * surface honestly (zero balance) rather than failing.\n */\n // [v1.2 SuiNS] Normalize the user-supplied address. Accepts both 0x\n // hex and *.sui names; throws structured errors when the input is\n // malformed or the SuiNS name doesn't resolve. Stamps `suinsName` on\n // the result so the host card can render \"Balance · alex.sui · 0x12…ab\"\n // instead of just the truncated hex.\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n if (hasNaviMcpGlobal(context)) {\n if (!targetAddress) {\n throw new Error('No wallet address provided. Sign in or pass `address` to inspect a public wallet.');\n }\n const address = targetAddress;\n const mgr = getMcpManager(context);\n\n // [v0.47] When a host-side `positionFetcher` is configured (Audric\n // production), savings/debt/rewards come from the host instead of\n // NAVI MCP. Skip those MCP calls entirely — they were previously\n // fetched in parallel and then discarded.\n const hasPositionFetcher = !!context.positionFetcher;\n\n // [single-source-of-truth — Apr 2026] When the engine runs inside\n // audric (T2000_AUDRIC_API / AUDRIC_INTERNAL_API_URL set), prefer\n // audric's canonical `/api/portfolio` so the LLM, dashboard, and\n // daily cron all read identical numbers. Returns null in\n // CLI / MCP / standalone mode → falls back to the BlockVision +\n // NAVI MCP path below.\n const audricPortfolio = await fetchAudricPortfolio(\n address,\n context.env,\n context.signal,\n );\n\n // [v1.4 BlockVision] Single BlockVision call returns coins +\n // balances + prices in one shot, replacing the parallel\n // (Sui RPC fetchWalletCoins + DefiLlama fetchTokenPrices) pair.\n // Run alongside positions / rewards / positionFetcher so total\n // wall time is bound by the slowest of the four.\n //\n // [v0.50.2] DeFi portfolio fetch added as a 5th parallel leg —\n // hits BlockVision /account/defiPortfolio for the 9 most-used Sui\n // DeFi protocols (Cetus, Suilend, Scallop, Bluefin, Aftermath,\n // Haedal, Suistake, SuiNS-staking, Walrus). Excludes NAVI to avoid\n // double-counting against positionFetcher/MCP savings. v0.50.1\n // briefly fanned out to all 26 BV protocols but the resulting\n // burst caused the wallet `/account/coins` call to occasionally\n // 429 and silently degrade to RPC (where non-stables are unpriced)\n // — so wallet display showed $0 for users with non-stable\n // holdings. v0.50.2 walks back to 9 (1 wallet + 9 DeFi = 10 burst,\n // safely below BV burst caps). Cached 60s, parallel-fanout, 5xx\n // on one protocol drops just that protocol. See\n // blockvision-prices.ts header for the generic-walker design.\n // When audric returned a canonical snapshot we already have\n // wallet + positions in one shot — short-circuit the parallel\n // BlockVision + NAVI fan-out so we don't double-pay the latency\n // and so the numbers in the result match audric's API exactly.\n const usingAudricSnapshot = audricPortfolio !== null;\n const audric: AudricPortfolioResult | null = audricPortfolio;\n\n const [portfolio, positions, rewards, serverPositions, defiPortfolio] = await Promise.all([\n usingAudricSnapshot\n ? Promise.resolve(audric!.portfolio)\n : loadPortfolio(\n address,\n context.blockvisionApiKey,\n context.suiRpcUrl,\n context.portfolioCache,\n context.retryStats,\n ).catch((err) => {\n console.warn('[balance_check] portfolio fetch failed, returning empty:', err);\n const fallback: AddressPortfolio = {\n coins: [],\n totalUsd: 0,\n pricedAt: Date.now(),\n source: 'sui-rpc-degraded',\n };\n return fallback;\n }),\n usingAudricSnapshot || hasPositionFetcher\n ? Promise.resolve(null)\n : callNavi(mgr, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }).catch((err) => {\n console.warn('[balance_check] NAVI GET_POSITIONS failed:', err);\n return null;\n }),\n usingAudricSnapshot || hasPositionFetcher\n ? Promise.resolve(null)\n : callNavi(mgr, NaviTools.GET_AVAILABLE_REWARDS, { address }).catch((err) => {\n console.warn('[balance_check] NAVI GET_AVAILABLE_REWARDS failed:', err);\n return null;\n }),\n usingAudricSnapshot\n ? Promise.resolve(audric!.positions)\n : hasPositionFetcher\n ? context.positionFetcher!(address).catch((err) => {\n console.warn('[balance_check] positionFetcher failed:', err);\n return null;\n })\n : Promise.resolve(null),\n // [v0.50] DeFi leg — independent of NAVI (excluded) and the wallet\n // portfolio (which only has coin holdings). Failure here surfaces\n // as defi.totalUsd === 0 and `source: 'degraded'`, leaving the\n // rest of balance_check unaffected. The fetcher fills its own\n // prices via fetchTokenPrices for any coin types it discovers.\n fetchAddressDefiPortfolio(address, context.blockvisionApiKey, {}, { retryStats: context.retryStats }).catch((err) => {\n console.warn('[balance_check] defi fetch failed:', err);\n const fallback: DefiSummary = {\n totalUsd: 0,\n perProtocol: {},\n pricedAt: Date.now(),\n source: 'degraded',\n };\n return fallback;\n }),\n ]);\n\n // [v1.4.1 — M1'] vSUI workaround mutates the portfolio in place\n // (BlockVision occasionally lacks a price for vSUI; we derive it\n // from the SUI price + Volo exchange rate). No-op when the wallet\n // doesn't hold vSUI.\n await applyVsuiPriceFallback(portfolio);\n\n // [v1.4.1 — M2'] NAVI MCP `GET_COINS` fallback removed. Previously\n // when Sui RPC returned an empty coin list we'd hit NAVI as a\n // tertiary source; with BlockVision as the primary and Sui RPC\n // already serving as the degraded fallback inside\n // `fetchAddressPortfolio`, the third tier added complexity without\n // real coverage (NAVI's coin endpoint shares infrastructure with\n // its already-failing positions endpoint). An empty wallet now\n // surfaces honestly to the user rather than silently swapping\n // sources mid-render.\n\n let availableUsd = 0;\n let stablesUsd = 0;\n let gasReserveUsd = 0;\n\n const STABLE_SYMBOLS = new Set(['USDC', 'USDT', 'USDe', 'USDsui', 'wUSDC', 'wUSDT']);\n const holdings: Array<{ symbol: string; coinType: string; balance: number; usdValue: number }> = [];\n\n for (const coin of portfolio.coins) {\n const balance = Number(coin.balance) / 10 ** coin.decimals;\n const price = coin.price ?? 0;\n\n if (coin.symbol === 'SUI' || coin.coinType === SUI_COIN_TYPE) {\n const reserveAmount = Math.min(balance, GAS_RESERVE_SUI);\n gasReserveUsd = reserveAmount * price;\n availableUsd += (balance - reserveAmount) * price;\n } else {\n availableUsd += balance * price;\n if (STABLE_SYMBOLS.has(coin.symbol)) {\n stablesUsd += balance * price;\n }\n }\n\n if (balance > 0) {\n holdings.push({\n symbol: coin.symbol || coin.coinType.split('::').pop() || coin.coinType,\n coinType: coin.coinType,\n balance,\n usdValue: balance * price,\n });\n }\n }\n\n let savings: number;\n let debt: number;\n let pendingRewardsUsd: number;\n\n if (serverPositions) {\n savings = serverPositions.savings;\n debt = serverPositions.borrows;\n pendingRewardsUsd = serverPositions.pendingRewards;\n } else {\n const posEntries = transformPositions(positions);\n const rewardEntries = transformRewards(rewards);\n savings = posEntries\n .filter((p) => p.type === 'supply')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n debt = posEntries\n .filter((p) => p.type === 'borrow')\n .reduce((sum, p) => sum + p.valueUsd, 0);\n pendingRewardsUsd = rewardEntries.reduce((sum, r) => sum + r.valueUsd, 0);\n }\n\n const visibleHoldings = holdings\n .filter((h) => h.usdValue >= 0.01)\n .sort((a, b) => b.usdValue - a.usdValue);\n\n const usdcHolding = holdings.find((h) => h.symbol === 'USDC');\n const saveableUsdc = usdcHolding ? usdcHolding.balance : 0;\n // [v0.51.0] USDsui is the second permitted saveable asset. Surface its\n // balance separately so the LLM can answer \"how much can I save?\" with\n // both stables, and so the displayText flags it (saveable) instead of\n // letting the LLM treat it as a generic holding. Not rolled into\n // `saveableUsdc` — the field name is canonical for USDC and downstream\n // permission/Tier resolvers depend on it.\n const usdsuiHolding = holdings.find((h) => h.symbol === 'USDsui');\n const saveableUsdsui = usdsuiHolding ? usdsuiHolding.balance : 0;\n\n // [v0.50] DeFi summary already resolved in the parallel fan-out\n // above. The fetcher fills its own prices via fetchTokenPrices for\n // any coin types found in DeFi positions that aren't stables.\n // Long-tail LP partner tokens that BlockVision's price list\n // doesn't cover may under-count — acceptable Phase 1 trade-off.\n const defi: DefiSummary = defiPortfolio;\n\n const bal = {\n available: availableUsd,\n savings,\n debt,\n pendingRewards: pendingRewardsUsd,\n gasReserve: gasReserveUsd,\n defi: defi.totalUsd,\n defiByProtocol: defi.perProtocol,\n defiSource: defi.source,\n // [v0.54] Forward the DeFi entry's pricedAt so the BalanceCard\n // can render \"cached Nm ago\" when source === 'partial-stale'.\n // Always populated; consumers ignore unless source is stale.\n defiPricedAt: defi.pricedAt,\n total: availableUsd + savings + gasReserveUsd + pendingRewardsUsd + defi.totalUsd - debt,\n stables: stablesUsd,\n holdings: visibleHoldings,\n saveableUsdc,\n saveableUsdsui,\n priceSource: portfolio.source,\n address,\n isSelfQuery,\n suinsName,\n };\n\n const holdingsList = visibleHoldings.map((h) => `${h.symbol}: ${h.balance < 1 ? h.balance.toFixed(6) : h.balance.toFixed(2)} ($${h.usdValue.toFixed(2)})`).join(', ');\n const subjectLabel = suinsName ?? `${address.slice(0, 6)}…${address.slice(-4)}`;\n const subjectPrefix = isSelfQuery ? 'Balance' : `Balance for ${subjectLabel}`;\n // Surface the DeFi fetch state so the LLM can answer accurately:\n // - `blockvision` + total > 0 → list protocols and dollar value\n // - `blockvision` + total === 0 → genuinely no positions in the 9 covered protocols\n // - `partial` → at least one protocol failed; total may under-count\n // - `degraded` → no API key OR every protocol failed; total UNKNOWN, not zero\n // Pre-v0.50.3 we silently emitted `''` for zero/degraded, which let\n // the LLM confidently assert \"no DeFi positions\" when in reality the\n // fetcher had been short-circuited by a missing BLOCKVISION_API_KEY.\n const defiSummaryText = (() => {\n if (defi.source === 'degraded') {\n return ' DeFi positions (Bluefin / Suilend / Cetus / etc.): UNAVAILABLE — DeFi data source is currently unreachable. Do NOT assert \"no DeFi positions\"; tell the user this slice is temporarily unknown and the total above EXCLUDES DeFi.';\n }\n if (defi.source === 'partial-stale' && defi.totalUsd > 0) {\n // [v0.54] Sticky-positive cache fallback — fresh BlockVision\n // call failed but we have a recent positive value. The total\n // INCLUDES this stale value (it's the most accurate number\n // we have right now), but mention provenance honestly.\n const ageMin = Math.round((Date.now() - defi.pricedAt) / 60_000);\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)} (last refresh ${ageMin}m ago — live BlockVision call failed, using cached value).`;\n }\n if (defi.totalUsd > 0) {\n const partialNote = defi.source === 'partial' ? ' (partial — one or more protocols failed; value may under-count)' : '';\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)}${partialNote}.`;\n }\n if (defi.source === 'partial') {\n // [v0.53.4] Stronger wording. Pre-fix this returned a soft\n // \"caveat that the picture may be incomplete\", which the\n // LLM consistently dropped from its narration when at least\n // one major protocol (Bluefin/Suilend/Cetus) 429'd during a\n // burst. The narration would then claim \"$X total\" with NO\n // mention of the missing slice, even when the same address\n // 30s later (cache miss → fresh fetch) showed thousands of\n // dollars in DeFi via the timeline canvas. Reworded to be\n // an explicit instruction matching the `degraded` branch.\n // (v0.54 reduces how often this branch fires by adding the\n // sticky-positive fallback above — partial+0 with a recent\n // positive cache now resolves to `partial-stale` instead.)\n return ' DeFi positions: UNKNOWN — at least one protocol failed to respond. The total above EXCLUDES any DeFi the failing protocols may hold. Do NOT assert \"no DeFi positions\" or \"DeFi: $0\"; tell the user DeFi is temporarily unreachable for this address.';\n }\n return '';\n })();\n const saveableSummary = saveableUsdsui > 0\n ? `Saveable: ${saveableUsdc.toFixed(2)} USDC + ${saveableUsdsui.toFixed(saveableUsdsui < 1 ? 4 : 2)} USDsui (only USDC and USDsui can be saved/borrowed).`\n : `Saveable USDC (only USDC and USDsui can be saved): ${saveableUsdc.toFixed(2)} USDC.`;\n return {\n data: bal,\n displayText: `${subjectPrefix}: $${bal.total.toFixed(2)} total. Wallet holdings (NOT savings): ${holdingsList || 'none'}. NAVI savings deposits: $${bal.savings.toFixed(2)}.${defiSummaryText} ${saveableSummary}`,\n };\n }\n\n // SDK agent fallback — only meaningful for the signed-in user (the\n // SDK's `balance()` method is bound to the agent's own wallet). If\n // the LLM passed a different address (post-normalization), refuse\n // rather than silently returning the agent's own balance.\n if (\n targetAddress &&\n context.walletAddress &&\n targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()\n ) {\n throw new Error(\n `Cannot inspect ${targetAddress.slice(0, 8)}… without NAVI MCP enabled. Configure NAVI MCP to enable third-party address reads.`,\n );\n }\n const agent = requireAgent(context);\n // [v0.50] In the SDK fallback path (CLI-only, self-query) we also\n // fan out to BlockVision /account/defiPortfolio so the CLI matches\n // engine + audric numbers. No-op when blockvisionApiKey is unset\n // (returns DefiSummary with source: 'degraded' and totalUsd: 0).\n const fetchAddress = (targetAddress ?? context.walletAddress) as string;\n const [balance, defi] = await Promise.all([\n agent.balance(),\n fetchAddressDefiPortfolio(fetchAddress, context.blockvisionApiKey, {}, { retryStats: context.retryStats }).catch((err) => {\n console.warn('[balance_check] sdk-path defi fetch failed:', err);\n const fallback: DefiSummary = {\n totalUsd: 0,\n perProtocol: {},\n pricedAt: Date.now(),\n source: 'degraded',\n };\n return fallback;\n }),\n ]);\n\n const gasReserveUsd = typeof balance.gasReserve === 'number'\n ? balance.gasReserve\n : (balance.gasReserve as { usdEquiv: number }).usdEquiv ?? 0;\n const stablesTotal = typeof balance.stables === 'number'\n ? balance.stables\n : Object.values(balance.stables as Record<string, number>).reduce((a: number, b: number) => a + b, 0);\n\n const sdkHoldings = (balance as unknown as Record<string, unknown>).holdings;\n const holdingsArr = Array.isArray(sdkHoldings) ? sdkHoldings : [];\n\n const usdcHolding = holdingsArr.find((h: { symbol?: string }) => h.symbol === 'USDC');\n const sdkSaveableUsdc = usdcHolding ? ((usdcHolding as { balance?: number }).balance ?? 0) : 0;\n const usdsuiHolding = holdingsArr.find((h: { symbol?: string }) => h.symbol === 'USDsui');\n const sdkSaveableUsdsui = usdsuiHolding ? ((usdsuiHolding as { balance?: number }).balance ?? 0) : 0;\n\n const sdkDefiSummaryText = (() => {\n if (defi.source === 'degraded') {\n return ' DeFi positions: UNAVAILABLE — data source unreachable. Do NOT claim \"no DeFi positions\"; report this slice as temporarily unknown and the total above EXCLUDES DeFi.';\n }\n if (defi.source === 'partial-stale' && defi.totalUsd > 0) {\n // [v0.54] Mirror of MCP-path sticky-positive narration.\n const ageMin = Math.round((Date.now() - defi.pricedAt) / 60_000);\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)} (last refresh ${ageMin}m ago — live BlockVision call failed, using cached value).`;\n }\n if (defi.totalUsd > 0) {\n const partialNote = defi.source === 'partial' ? ' (partial — one or more protocols failed; value may under-count)' : '';\n return ` Other DeFi positions (LPs/staking/lending across ${Object.keys(defi.perProtocol).join('/')}): $${defi.totalUsd.toFixed(2)}${partialNote}.`;\n }\n if (defi.source === 'partial') {\n // [v0.53.4] Mirror of the MCP-path strengthening — see the\n // companion comment ~70 lines up for full rationale.\n return ' DeFi positions: UNKNOWN — at least one protocol failed to respond. The total above EXCLUDES any DeFi the failing protocols may hold. Do NOT assert \"no DeFi positions\" or \"DeFi: $0\"; tell the user DeFi is temporarily unreachable for this wallet.';\n }\n return '';\n })();\n const sdkTotal = balance.total + defi.totalUsd;\n\n return {\n data: {\n available: balance.available,\n savings: balance.savings,\n debt: balance.debt,\n pendingRewards: balance.pendingRewards,\n gasReserve: gasReserveUsd,\n defi: defi.totalUsd,\n defiByProtocol: defi.perProtocol,\n defiSource: defi.source,\n // [v0.54] Same staleness provenance as the MCP path above.\n defiPricedAt: defi.pricedAt,\n total: sdkTotal,\n stables: stablesTotal,\n holdings: holdingsArr,\n saveableUsdc: sdkSaveableUsdc,\n saveableUsdsui: sdkSaveableUsdsui,\n address: targetAddress ?? '',\n isSelfQuery: true,\n suinsName,\n },\n displayText: `Balance: $${sdkTotal.toFixed(2)} total. Wallet: $${balance.available.toFixed(2)} available. NAVI savings deposits: $${balance.savings.toFixed(2)}.${sdkDefiSummaryText} ${sdkSaveableUsdsui > 0 ? `Saveable: ${sdkSaveableUsdc.toFixed(2)} USDC + ${sdkSaveableUsdsui.toFixed(sdkSaveableUsdsui < 1 ? 4 : 2)} USDsui (only USDC and USDsui can be saved/borrowed).` : `Saveable USDC (only USDC and USDsui can be saved): ${sdkSaveableUsdc.toFixed(2)} USDC.`}`,\n };\n },\n});\n","// ---------------------------------------------------------------------------\n// NaviCacheStore — pluggable cache backend for NAVI MCP composite reads\n// ---------------------------------------------------------------------------\n//\n// Why this module exists\n// ----------------------\n// PR 4 of the scaling spec adds a 30s cache for `savings_info` and\n// `health_check` reads, and a 5-minute cache for `rates_info`. Without\n// it, every `savings_info` / `health_check` call in a chat turn issues\n// 2–4 NAVI MCP round-trips (~200–500ms each). At 500 DAU sustained, this\n// puts visible pressure on NAVI's endpoint and adds 400–1000ms of tail\n// latency to those tools every turn.\n//\n// The cache is keyed by `navi:<endpoint>:<address>` for address-scoped\n// reads and `navi:rates` for the global rates table:\n// - `navi:savings:<address>` — 30s TTL\n// - `navi:health:<address>` — 30s TTL\n// - `navi:rates` — 300s (5 min) TTL\n//\n// The default `InMemoryNaviCacheStore` is per-process (CLI/tests/dev).\n// Audric injects `UpstashNaviCacheStore` at engine init via\n// `init-engine-stores.ts` so all Vercel instances share one cache.\n//\n// Store contract\n// --------------\n// The store is a dumb typed key-value with TTL. Cache freshness logic\n// (when to re-fetch, when to serve stale) lives in the FETCHER so\n// implementations can be swapped without re-implementing policy. `get`\n// returns `null` on miss, expiry, or backend error. `set` swallows errors.\n// ---------------------------------------------------------------------------\n\n/** Cache entry shape. `cachedAt` is the wall-clock ms at write time. */\nexport interface NaviCacheEntry {\n data: unknown;\n /** Wall-clock ms when the entry was written. Used by callers for freshness math. */\n cachedAt: number;\n}\n\n/**\n * Pluggable cache backend for NAVI MCP reads.\n *\n * All methods are async to accommodate Redis-backed implementations.\n * `get` must return `null` (not throw) on backend failure.\n * `set` must swallow errors.\n */\nexport interface NaviCacheStore {\n get(key: string): Promise<NaviCacheEntry | null>;\n set(key: string, entry: NaviCacheEntry, ttlSec: number): Promise<void>;\n delete(key: string): Promise<void>;\n clear(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — default for CLI, tests, and pre-injection use\n// ---------------------------------------------------------------------------\n\nexport class InMemoryNaviCacheStore implements NaviCacheStore {\n private readonly store = new Map<string, { entry: NaviCacheEntry; expiresAt: number }>();\n\n async get(key: string): Promise<NaviCacheEntry | null> {\n const slot = this.store.get(key);\n if (!slot) return null;\n if (Date.now() >= slot.expiresAt) {\n this.store.delete(key);\n return null;\n }\n return slot.entry;\n }\n\n async set(key: string, entry: NaviCacheEntry, ttlSec: number): Promise<void> {\n this.store.set(key, {\n entry,\n expiresAt: Date.now() + ttlSec * 1000,\n });\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level injection slot\n// ---------------------------------------------------------------------------\n\nlet activeStore: NaviCacheStore = new InMemoryNaviCacheStore();\n\n/** Swap the active NAVI cache store. Called once at engine init by Audric. */\nexport function setNaviCacheStore(store: NaviCacheStore): void {\n activeStore = store;\n}\n\n/** Returns the currently active store. Used by navi-reads.ts. */\nexport function getNaviCacheStore(): NaviCacheStore {\n return activeStore;\n}\n\n/** Restore the default in-memory store. Used by test teardowns. */\nexport function resetNaviCacheStore(): void {\n activeStore = new InMemoryNaviCacheStore();\n}\n\n// ---------------------------------------------------------------------------\n// Cache key helpers\n// ---------------------------------------------------------------------------\n\n/** 30s TTL for address-scoped reads (savings, health). */\nexport const NAVI_ADDR_TTL_SEC = 30;\n\n/** 300s (5 min) TTL for the global rates table. */\nexport const NAVI_RATES_TTL_SEC = 300;\n\nexport const naviKey = {\n rates: () => 'navi:rates',\n savings: (address: string) => `navi:savings:${address.toLowerCase()}`,\n health: (address: string) => `navi:health:${address.toLowerCase()}`,\n} as const;\n","import type { McpClientManager, McpCallResult } from './mcp-client.js';\nimport { NAVI_SERVER_NAME, NaviTools } from './navi-config.js';\nimport {\n parseMcpJson,\n transformBalance,\n transformHealthFactor,\n transformPositions,\n transformRates,\n transformRewards,\n transformSavings,\n type BalanceResult,\n type HealthFactorResult,\n type PendingReward,\n type PositionEntry,\n type RatesResult,\n type SavingsResult,\n} from './navi-transforms.js';\nimport {\n getNaviCacheStore,\n naviKey,\n NAVI_ADDR_TTL_SEC,\n NAVI_RATES_TTL_SEC,\n} from './navi-cache.js';\nimport { getTelemetrySink } from './telemetry.js';\n\n// ---------------------------------------------------------------------------\n// Options for composite reads\n// ---------------------------------------------------------------------------\n\nexport interface NaviReadOptions {\n /** MCP server name override (default: 'navi'). */\n serverName?: string;\n /** Skip the cache for this call (default: false). Useful for post-write refreshes. */\n skipCache?: boolean;\n}\n\nfunction sn(opts?: NaviReadOptions): string {\n return opts?.serverName ?? NAVI_SERVER_NAME;\n}\n\n// ---------------------------------------------------------------------------\n// Circuit breaker (PR 4)\n//\n// NAVI MCP can return errors (rate limits, 5xx) under load. A process-local\n// CB mirrors the BlockVision pattern: open after NAVI_CB_THRESHOLD errors\n// in NAVI_CB_WINDOW_MS, suppress retries for NAVI_CB_COOLDOWN_MS.\n// Per-process state is intentional — same rationale as BV CB.\n// ---------------------------------------------------------------------------\nconst NAVI_CB_WINDOW_MS = 5_000;\nconst NAVI_CB_THRESHOLD = 10;\nconst NAVI_CB_COOLDOWN_MS = 30_000;\n\nlet naviCb429Timestamps: number[] = [];\nlet naviCbOpenUntil = 0;\n\nfunction naviCbIsOpen(now: number): boolean {\n return now < naviCbOpenUntil;\n}\n\nfunction naviCbRecordError(now: number): void {\n naviCb429Timestamps.push(now);\n naviCb429Timestamps = naviCb429Timestamps.filter((t) => now - t < NAVI_CB_WINDOW_MS);\n if (naviCb429Timestamps.length >= NAVI_CB_THRESHOLD && !naviCbIsOpen(now)) {\n naviCbOpenUntil = now + NAVI_CB_COOLDOWN_MS;\n getTelemetrySink().gauge('navi.cb_open', 1);\n console.warn(\n `[navi-reads] circuit breaker OPEN — ${NAVI_CB_THRESHOLD} errors in ${NAVI_CB_WINDOW_MS}ms, retries disabled for ${NAVI_CB_COOLDOWN_MS / 1000}s`,\n );\n naviCb429Timestamps = [];\n }\n}\n\n/** Test seam — reset NAVI CB state between tests. */\nexport function _resetNaviCircuitBreaker(): void {\n naviCb429Timestamps = [];\n naviCbOpenUntil = 0;\n}\n\n// ---------------------------------------------------------------------------\n// Retry config\n// ---------------------------------------------------------------------------\nconst NAVI_RETRY_MAX_ATTEMPTS = 3;\nconst NAVI_RETRY_BASE_DELAY_MS = 200;\nconst NAVI_RETRY_BACKOFF_FACTOR = 3;\n\n// ---------------------------------------------------------------------------\n// Helper: call NAVI tool with retry and circuit breaker\n// ---------------------------------------------------------------------------\n\nasync function callNavi<T = unknown>(\n manager: McpClientManager,\n tool: string,\n args: Record<string, unknown> = {},\n opts?: NaviReadOptions,\n): Promise<T> {\n const result: McpCallResult = await manager.callTool(sn(opts), tool, args);\n if (result.isError) {\n const msg = result.content\n .filter((c) => c.type === 'text' && c.text)\n .map((c) => c.text!)\n .join(' ');\n throw new Error(`NAVI MCP error (${tool}): ${msg || 'unknown error'}`);\n }\n return parseMcpJson<T>(result.content);\n}\n\nasync function callNaviWithRetry<T = unknown>(\n manager: McpClientManager,\n tool: string,\n args: Record<string, unknown> = {},\n opts?: NaviReadOptions,\n): Promise<T> {\n const sink = getTelemetrySink();\n const now = () => Date.now();\n\n if (naviCbIsOpen(now())) {\n sink.counter('navi.requests', { tool, status: 'cb_open' });\n throw new Error(`[navi-reads] circuit breaker open — skipping ${tool}`);\n }\n\n let lastError: Error | undefined;\n for (let attempt = 0; attempt < NAVI_RETRY_MAX_ATTEMPTS; attempt++) {\n if (attempt > 0) {\n const delay = NAVI_RETRY_BASE_DELAY_MS * Math.pow(NAVI_RETRY_BACKOFF_FACTOR, attempt - 1);\n await new Promise<void>((r) => setTimeout(r, delay));\n }\n try {\n const result = await callNavi<T>(manager, tool, args, opts);\n sink.counter('navi.requests', { tool, status: '2xx', attempt: String(attempt) });\n return result;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n sink.counter('navi.requests', { tool, status: '5xx', attempt: String(attempt) });\n naviCbRecordError(now());\n\n if (naviCbIsOpen(now())) {\n throw lastError;\n }\n }\n }\n throw lastError ?? new Error(`NAVI MCP: ${tool} failed after ${NAVI_RETRY_MAX_ATTEMPTS} attempts`);\n}\n\n// ---------------------------------------------------------------------------\n// Cache helpers\n// ---------------------------------------------------------------------------\n\nasync function cacheGet<T>(key: string): Promise<T | null> {\n try {\n const entry = await getNaviCacheStore().get(key);\n if (entry !== null) {\n getTelemetrySink().counter('navi.cache_hit', { key_prefix: key.split(':').slice(0, 2).join(':'), freshness: 'fresh' });\n return entry.data as T; // safe cast: we control what we write\n }\n getTelemetrySink().counter('navi.cache_hit', { key_prefix: key.split(':').slice(0, 2).join(':'), freshness: 'miss' });\n return null;\n } catch {\n return null;\n }\n}\n\nasync function cacheSet<T>(key: string, data: T, ttlSec: number): Promise<void> {\n try {\n await getNaviCacheStore().set(key, { data, cachedAt: Date.now() }, ttlSec);\n } catch {\n // swallow — cache miss is always tolerable\n }\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: rates\n// ---------------------------------------------------------------------------\n\nexport async function fetchRates(\n manager: McpClientManager,\n opts?: NaviReadOptions,\n): Promise<RatesResult> {\n const key = naviKey.rates();\n if (!opts?.skipCache) {\n const cached = await cacheGet<RatesResult>(key);\n if (cached) return cached;\n }\n\n const pools = await callNaviWithRetry(manager, NaviTools.GET_POOLS, {}, opts);\n const result = transformRates(pools);\n await cacheSet(key, result, NAVI_RATES_TTL_SEC);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: health factor (enriched with positions)\n// ---------------------------------------------------------------------------\n\nexport async function fetchHealthFactor(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<HealthFactorResult> {\n const key = naviKey.health(address);\n if (!opts?.skipCache) {\n const cached = await cacheGet<HealthFactorResult>(key);\n if (cached) return cached;\n }\n\n const [hfRaw, posRaw] = await Promise.all([\n callNaviWithRetry(manager, NaviTools.GET_HEALTH_FACTOR, { address }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }, opts),\n ]);\n\n const result = transformHealthFactor(hfRaw, posRaw);\n await cacheSet(key, result, NAVI_ADDR_TTL_SEC);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: balance breakdown\n// ---------------------------------------------------------------------------\n\nexport async function fetchBalance(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<BalanceResult> {\n const [coins, positions, rewards, pools] = await Promise.all([\n callNaviWithRetry(manager, NaviTools.GET_COINS, { address }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }, opts),\n callNaviWithRetry(manager, NaviTools.GET_AVAILABLE_REWARDS, { address }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POOLS, {}, opts),\n ]);\n\n const rates = transformRates(pools);\n const prices: Record<string, number> = {};\n for (const [symbol, rate] of Object.entries(rates)) {\n prices[symbol] = rate.price;\n }\n\n return transformBalance(coins, positions, rewards, prices);\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: savings info (positions + pool APYs)\n// ---------------------------------------------------------------------------\n\nexport async function fetchSavings(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<SavingsResult> {\n const key = naviKey.savings(address);\n if (!opts?.skipCache) {\n const cached = await cacheGet<SavingsResult>(key);\n if (cached) return cached;\n }\n\n const [positions, pools] = await Promise.all([\n callNaviWithRetry(manager, NaviTools.GET_POSITIONS, {\n address,\n protocols: 'navi',\n format: 'json',\n }, opts),\n callNaviWithRetry(manager, NaviTools.GET_POOLS, {}, opts),\n ]);\n\n const result = transformSavings(positions, pools);\n await cacheSet(key, result, NAVI_ADDR_TTL_SEC);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: positions only\n// ---------------------------------------------------------------------------\n\nexport async function fetchPositions(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions & { protocols?: string },\n): Promise<PositionEntry[]> {\n const raw = await callNaviWithRetry(\n manager,\n NaviTools.GET_POSITIONS,\n { address, protocols: opts?.protocols ?? 'navi', format: 'json' },\n opts,\n );\n return transformPositions(raw);\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: available rewards\n// ---------------------------------------------------------------------------\n\nexport async function fetchAvailableRewards(\n manager: McpClientManager,\n address: string,\n opts?: NaviReadOptions,\n): Promise<PendingReward[]> {\n const raw = await callNaviWithRetry(\n manager,\n NaviTools.GET_AVAILABLE_REWARDS,\n { address },\n opts,\n );\n return transformRewards(raw);\n}\n\n// ---------------------------------------------------------------------------\n// Composite read: protocol stats\n// ---------------------------------------------------------------------------\n\nexport interface ProtocolStats {\n tvl: number;\n totalBorrowUsd: number;\n utilization: number;\n maxApy: number;\n totalUsers: number;\n}\n\nexport async function fetchProtocolStats(\n manager: McpClientManager,\n opts?: NaviReadOptions,\n): Promise<ProtocolStats> {\n const raw = await callNaviWithRetry<{\n tvl?: number;\n totalBorrowUsd?: number;\n averageUtilization?: number;\n maxApy?: number;\n userAmount?: number;\n }>(manager, NaviTools.GET_PROTOCOL_STATS, {}, opts);\n\n return {\n tvl: raw?.tvl ?? 0,\n totalBorrowUsd: raw?.totalBorrowUsd ?? 0,\n utilization: raw?.averageUtilization ?? 0,\n maxApy: raw?.maxApy ?? 0,\n totalUsers: raw?.userAmount ?? 0,\n };\n}\n","import { z } from 'zod';\nimport { fetchSavings } from '../navi-reads.js';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, requireAgent } from './utils.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { PositionEntry, SavingsResult } from '../navi-transforms.js';\nimport type { ServerPositionData } from '../types.js';\n\nconst DUST_THRESHOLD_USD = 0.01;\n\nfunction buildSavingsFromPositions(sp: ServerPositionData): SavingsResult {\n const positions: PositionEntry[] = [\n ...sp.supplies\n .filter((s) => s.amountUsd >= DUST_THRESHOLD_USD)\n .map((s) => ({\n protocol: s.protocol,\n type: 'supply' as const,\n symbol: s.asset,\n amount: s.amount,\n valueUsd: s.amountUsd,\n apy: s.apy,\n liquidationThreshold: 0,\n })),\n ...sp.borrows_detail\n .filter((b) => b.amountUsd >= DUST_THRESHOLD_USD)\n .map((b) => ({\n protocol: b.protocol,\n type: 'borrow' as const,\n symbol: b.asset,\n amount: b.amount,\n valueUsd: b.amountUsd,\n apy: b.apy,\n liquidationThreshold: 0,\n })),\n ];\n\n const supplied = sp.savings;\n const weightedApy = supplied > 0 ? sp.savingsRate : 0;\n const dailyEarning = (supplied * weightedApy) / 365;\n\n return {\n positions,\n earnings: {\n totalYieldEarned: 0,\n currentApy: weightedApy,\n dailyEarning,\n supplied,\n },\n fundStatus: {\n supplied,\n apy: weightedApy,\n earnedToday: dailyEarning,\n earnedAllTime: 0,\n projectedMonthly: dailyEarning * 30,\n },\n };\n}\n\nfunction formatSavingsDisplay(\n result: SavingsResult,\n isSelfQuery: boolean = true,\n address?: string,\n suinsName?: string | null,\n): string {\n const { positions, earnings, fundStatus } = result;\n const supplies = positions.filter((p) => p.type === 'supply');\n const borrows = positions.filter((p) => p.type === 'borrow');\n\n const subjectLabel = suinsName ?? (address ? `${address.slice(0, 6)}…${address.slice(-4)}` : null);\n const subjectPrefix = isSelfQuery || !subjectLabel ? '' : `${subjectLabel} — `;\n\n const lines: string[] = [];\n if (supplies.length > 0) {\n lines.push(`${subjectPrefix}Savings: $${fundStatus.supplied.toFixed(2)} at ${(earnings.currentApy * 100).toFixed(2)}% blended APY`);\n for (const s of supplies) {\n lines.push(` ${s.symbol}: ${s.amount.toFixed(s.amount < 1 ? 6 : 2)} ($${s.valueUsd.toFixed(2)}) at ${(s.apy * 100).toFixed(2)}% APY`);\n }\n } else {\n lines.push(`${subjectPrefix}No savings positions.`);\n }\n if (borrows.length > 0) {\n const totalDebt = borrows.reduce((s, b) => s + b.valueUsd, 0);\n lines.push(`Debt: $${totalDebt.toFixed(2)}`);\n }\n lines.push(`Daily earnings: $${fundStatus.earnedToday.toFixed(4)}`);\n lines.push(`Monthly projected: $${fundStatus.projectedMonthly.toFixed(4)}`);\n return lines.join('\\n');\n}\n\nexport const savingsInfoTool = buildTool({\n name: 'savings_info',\n description:\n 'Get detailed savings positions and earnings for the signed-in user OR any public Sui address or SuiNS name: current deposits by protocol, APY, total yield earned, daily earning rate, and projected monthly returns. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v1.5.1] NAVI deposits change on save_deposit / withdraw / claim.\n // Each call reflects a fresh on-chain snapshot — never dedupe.\n cacheable: false,\n\n async call(input, context) {\n /**\n * [v0.49] Address-scope: tool now accepts an optional `address` param\n * so the LLM can inspect any public Sui wallet's NAVI deposits.\n * Pre-v0.49 the tool only ever queried `context.walletAddress`,\n * silently returning the signed-in user's positions for \"How much\n * has funkii saved?\" type questions. Falls back to\n * `context.walletAddress` when the param is absent. Stamps `address`\n * + `isSelfQuery` on the result.\n */\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n if (context.positionFetcher && targetAddress) {\n const sp = await context.positionFetcher(targetAddress);\n const result = buildSavingsFromPositions(sp);\n const stamped = { ...result, address: targetAddress, isSelfQuery, suinsName };\n return { data: stamped, displayText: formatSavingsDisplay(result, isSelfQuery, targetAddress, suinsName) };\n }\n\n if (hasNaviMcpGlobal(context) && targetAddress) {\n const savings = await fetchSavings(getMcpManager(context), targetAddress);\n savings.positions = savings.positions.filter((p) => p.valueUsd >= DUST_THRESHOLD_USD);\n const stamped = { ...savings, address: targetAddress, isSelfQuery, suinsName };\n return { data: stamped, displayText: formatSavingsDisplay(savings, isSelfQuery, targetAddress, suinsName) };\n }\n\n if (\n targetAddress &&\n context.walletAddress &&\n targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()\n ) {\n throw new Error(\n `Cannot inspect ${targetAddress.slice(0, 8)}… without NAVI MCP or a positionFetcher. Configure NAVI MCP to enable third-party address reads.`,\n );\n }\n const agent = requireAgent(context);\n const [posResult, earnings, fundStatus] = await Promise.all([\n agent.positions(),\n agent.earnings(),\n agent.fundStatus(),\n ]);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const positions = (posResult.positions ?? []).map((p: any) => ({\n protocol: (p.protocol ?? 'navi') as string,\n type: p.type === 'borrow' ? ('borrow' as const) : ('supply' as const),\n symbol: ((p.asset ?? p.symbol) ?? 'UNKNOWN') as string,\n amount: (p.amount ?? 0) as number,\n valueUsd: ((p.amountUsd ?? p.valueUsd) ?? 0) as number,\n apy: (p.apy ?? 0) as number,\n liquidationThreshold: (p.liquidationThreshold ?? 0) as number,\n })).filter((p: PositionEntry) => p.valueUsd >= DUST_THRESHOLD_USD);\n\n const result: SavingsResult = {\n positions,\n earnings: {\n totalYieldEarned: earnings.totalYieldEarned,\n currentApy: earnings.currentApy,\n dailyEarning: earnings.dailyEarning,\n supplied: earnings.supplied,\n },\n fundStatus: {\n supplied: fundStatus.supplied,\n apy: fundStatus.apy,\n earnedToday: fundStatus.earnedToday,\n earnedAllTime: fundStatus.earnedAllTime,\n projectedMonthly: fundStatus.projectedMonthly,\n },\n };\n\n const stamped = { ...result, address: targetAddress ?? '', isSelfQuery: true, suinsName };\n return { data: stamped, displayText: formatSavingsDisplay(result, true, undefined, suinsName) };\n },\n});\n","import { z } from 'zod';\nimport { fetchHealthFactor } from '../navi-reads.js';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, requireAgent } from './utils.js';\nimport { normalizeAddressInput } from '../sui-address.js';\n\n/**\n * Anything below this threshold is treated as \"no real debt\" — NAVI can\n * accrue dust between blocks (sub-cent) even after a full repay, and we\n * don't want a $0.000018 phantom borrow flipping the user from \"Healthy\"\n * to \"Warning\" or worse.\n */\nconst DEBT_DUST_USD = 0.01;\n\nfunction hfStatus(hf: number, borrowed: number): string {\n // Zero (or dust-only) debt accounts are maximally safe — math says HF=∞,\n // but the SDK sometimes returns 0 as a sentinel for that case. Treating\n // it as \"critical\" is a pure UI bug (the user has no liquidation risk).\n if (borrowed <= DEBT_DUST_USD) return 'healthy';\n if (hf >= 2.0) return 'healthy';\n if (hf >= 1.5) return 'moderate';\n if (hf >= 1.2) return 'warning';\n return 'critical';\n}\n\n/**\n * Normalise a health factor for transport. JSON.stringify(Infinity) ===\n * \"null\", and the LLM / UI both end up coercing that null to 0, which\n * then renders as the misleading \"Critical 0.00\" status. We therefore\n * collapse any non-finite (or no-debt) value to `null` deliberately so\n * that consumers can branch on `borrowed <= dust || healthFactor == null`\n * to render \"∞\" / \"Healthy\" rather than a misleading numeric value.\n */\nfunction serializeHf(hf: number | null | undefined, borrowed: number): number | null {\n if (borrowed <= DEBT_DUST_USD) return null;\n if (hf == null || !Number.isFinite(hf)) return null;\n return hf;\n}\n\nfunction displayHfText(\n hf: number | null,\n borrowed: number,\n status: string,\n isSelfQuery: boolean = true,\n address?: string,\n suinsName?: string | null,\n): string {\n const subjectLabel = suinsName ?? (address ? `${address.slice(0, 6)}…${address.slice(-4)}` : null);\n const subject = isSelfQuery || !subjectLabel\n ? 'Health Factor'\n : `Health Factor for ${subjectLabel}`;\n if (hf == null) {\n return `${subject}: ∞ (${status} — no debt)`;\n }\n return `${subject}: ${hf.toFixed(2)} (${status})`;\n}\n\nexport const healthCheckTool = buildTool({\n name: 'health_check',\n description:\n 'Check the lending health factor for the signed-in user OR any public Sui address or SuiNS name: current HF ratio, total supplied collateral, total borrowed, max additional borrow capacity, and liquidation threshold. HF < 1.5 is risky, < 1.2 is critical. When the address has no debt the tool returns healthFactor=null (semantically infinity) — render that as \"Healthy\" / ∞, never as 0 or \"Critical\". Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v1.5.1] Health factor changes on every borrow / repay / collateral\n // movement and even passively as oracle prices update. Never dedupe.\n cacheable: false,\n\n async call(input, context) {\n /**\n * [v0.49] Address-scope: tool now accepts an optional `address` param\n * so the LLM can inspect any public Sui wallet's NAVI lending\n * position. Pre-v0.49 the tool only ever queried\n * `context.walletAddress`, which silently returned the signed-in\n * user's HF for \"How is funkii's account health?\" type questions.\n * Falls back to `context.walletAddress` when the param is absent.\n * Stamps `address` + `isSelfQuery` on the result.\n */\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n if (context.positionFetcher && targetAddress) {\n const sp = await context.positionFetcher(targetAddress);\n const borrowed = sp.borrows;\n const rawHf = sp.healthFactor ?? (borrowed > 0 ? 0 : Infinity);\n const status = hfStatus(rawHf, borrowed);\n const transportHf = serializeHf(rawHf, borrowed);\n return {\n data: {\n healthFactor: transportHf,\n supplied: sp.savings,\n borrowed,\n maxBorrow: sp.maxBorrow,\n liquidationThreshold: 0,\n status,\n address: targetAddress,\n isSelfQuery,\n suinsName,\n },\n displayText: displayHfText(transportHf, borrowed, status, isSelfQuery, targetAddress, suinsName),\n };\n }\n\n if (hasNaviMcpGlobal(context) && targetAddress) {\n const hf = await fetchHealthFactor(getMcpManager(context), targetAddress);\n const borrowed = hf.borrowed;\n const status = hfStatus(hf.healthFactor, borrowed);\n const transportHf = serializeHf(hf.healthFactor, borrowed);\n return {\n data: { ...hf, healthFactor: transportHf, status, address: targetAddress, isSelfQuery, suinsName },\n displayText: displayHfText(transportHf, borrowed, status, isSelfQuery, targetAddress, suinsName),\n };\n }\n\n // SDK agent fallback — only meaningful for the signed-in user (the\n // SDK's `healthFactor()` method is bound to the agent's own wallet).\n if (\n targetAddress &&\n context.walletAddress &&\n targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()\n ) {\n throw new Error(\n `Cannot inspect ${targetAddress.slice(0, 8)}… without NAVI MCP or a positionFetcher. Configure NAVI MCP to enable third-party address reads.`,\n );\n }\n const agent = requireAgent(context);\n const hf = await agent.healthFactor();\n const borrowed = hf.borrowed;\n const status = hfStatus(hf.healthFactor, borrowed);\n const transportHf = serializeHf(hf.healthFactor, borrowed);\n\n return {\n data: {\n healthFactor: transportHf,\n supplied: hf.supplied,\n borrowed,\n maxBorrow: hf.maxBorrow,\n liquidationThreshold: hf.liquidationThreshold,\n status,\n address: targetAddress ?? '',\n isSelfQuery: true,\n suinsName,\n },\n displayText: displayHfText(transportHf, borrowed, status, true, undefined, suinsName),\n };\n },\n});\n","import { z } from 'zod';\nimport { fetchRates } from '../navi-reads.js';\nimport { buildTool } from '../tool.js';\nimport { hasNaviMcpGlobal, getMcpManager, hasAgent, requireAgent } from './utils.js';\n\n// [v1.4 — Day 3] DefiLlama fallback removed. The two upstream tiers\n// (NAVI MCP + SDK agent) cover every authenticated and read-only-system\n// path the harness exercises in production. The Tier 3 DefiLlama lookup\n// was a leftover from when SDK agent rates weren't reliable; the SDK\n// path has been stable for ~v0.45+ and the DefiLlama supply-only payload\n// (no borrow APYs) was already a degraded experience. Honest \"rates\n// unavailable\" is better than a half-correct mark from a deprecated\n// vendor. Audited and accepted as a regression in the Day-3 deletion\n// pass — see AUDRIC_HARNESS_INTELLIGENCE_SPEC_v1.4.1.md.\n\n/**\n * [v0.46.6] Stablecoin allow-list used by the `stableOnly` filter.\n *\n * Lower-cased symbol matching — covers the canonical USDC/USDT family\n * and the Sui-native synthetic stables (USDSUI, USDY, suiUSDT, USDe,\n * AUSD, FDUSD, BUCK). Excludes XAUm (gold-pegged, not USD-pegged) and\n * any LST/LRT.\n */\nconst STABLECOIN_SYMBOLS = new Set<string>([\n 'usdc',\n 'wusdc',\n 'usdt',\n 'wusdt',\n 'suiusdt',\n 'usdy',\n 'usdsui',\n 'usde',\n 'ausd',\n 'fdusd',\n 'buck',\n]);\n\ntype RateMap = Record<string, { saveApy: number; borrowApy: number }>;\n\nfunction isStable(symbol: string): boolean {\n return STABLECOIN_SYMBOLS.has(symbol.toLowerCase());\n}\n\n/**\n * [Bug — 2026-04-28] Token alias expansion for the `assets` filter.\n *\n * NAVI mainnet lists multiple variants for the same underlying asset:\n * - USDT family: `wUSDT` (Wormhole), `suiUSDT` (Sui-native), and the\n * legacy `USDT` Portal symbol.\n * - USDC family: `USDC` (canonical), `wUSDC` (Wormhole legacy).\n * - USDe family: `USDe`, `suiUSDe` (Sui-native).\n *\n * Pre-fix the filter did exact-string lowercase match: a user asking for\n * `usdt` got back nothing because NAVI's pool list returns `suiUSDT`\n * (lowercased: `suiusdt`), not `usdt`. The LLM then hallucinated a\n * factually wrong narration (\"USDT: not actively listed on NAVI\") to\n * explain the empty payload — the worst possible UX.\n *\n * The map is intentionally narrow: only the well-known stablecoin\n * synonyms that the user's mental model treats as \"the same asset\". We\n * do NOT alias e.g. SUI → vSUI / haSUI because those are distinct yield\n * positions with their own APY profiles — collapsing them would HIDE\n * meaningful rate differences.\n */\nconst TOKEN_ALIASES: Record<string, string[]> = {\n usdt: ['usdt', 'wusdt', 'suiusdt'],\n usdc: ['usdc', 'wusdc'],\n usde: ['usde', 'suiusde', 'sui_usde'],\n usdsui: ['usdsui'],\n};\n\nfunction expandAliases(symbols: string[]): Set<string> {\n const out = new Set<string>();\n for (const s of symbols) {\n const norm = s.toLowerCase();\n const aliases = TOKEN_ALIASES[norm] ?? [norm];\n for (const a of aliases) out.add(a);\n }\n return out;\n}\n\nfunction applyFilters(\n rates: RateMap,\n opts: { assets?: string[]; stableOnly?: boolean; topN?: number },\n): RateMap {\n let entries = Object.entries(rates);\n if (opts.assets && opts.assets.length) {\n const wanted = expandAliases(opts.assets);\n entries = entries.filter(([sym]) => wanted.has(sym.toLowerCase()));\n } else if (opts.stableOnly) {\n entries = entries.filter(([sym]) => isStable(sym));\n }\n // Sort by save APY desc so `topN` picks the best yields when no\n // explicit `assets` filter was supplied.\n entries.sort(([, a], [, b]) => b.saveApy - a.saveApy);\n if (opts.topN && opts.topN > 0) {\n entries = entries.slice(0, opts.topN);\n }\n return Object.fromEntries(entries);\n}\n\nfunction formatRatesSummary(rates: RateMap): string {\n return Object.entries(rates)\n .map(([asset, r]) => `${asset}: Save ${(r.saveApy * 100).toFixed(2)}% / Borrow ${(r.borrowApy * 100).toFixed(2)}%`)\n .join(', ');\n}\n\nexport const ratesInfoTool = buildTool({\n name: 'rates_info',\n description:\n '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).',\n inputSchema: z.object({\n assets: z\n .array(z.string())\n .optional()\n .describe('Filter to specific asset symbols (e.g. [\"USDC\"], [\"USDC\",\"USDT\",\"USDSUI\"]). Case-insensitive.'),\n stableOnly: z\n .boolean()\n .optional()\n .describe('When true, return only stablecoin markets (USDC, USDT, USDSUI, USDY, suiUSDT, etc.). Ignored when `assets` is supplied.'),\n topN: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe('Cap the number of rows in the card (default 8). Use 50 to render the full NAVI catalog.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n assets: {\n type: 'array',\n items: { type: 'string' },\n description: 'Filter to specific asset symbols (case-insensitive).',\n },\n stableOnly: {\n type: 'boolean',\n description: 'When true, return only stablecoin markets. Ignored when `assets` is supplied.',\n },\n topN: {\n type: 'number',\n description: 'Cap the number of rows in the card (default 8, max 50).',\n },\n },\n required: [],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const opts = {\n assets: input.assets,\n stableOnly: input.stableOnly,\n topN: input.topN ?? 8,\n };\n\n if (hasNaviMcpGlobal(context)) {\n const all = await fetchRates(getMcpManager(context));\n const filtered = applyFilters(all, opts);\n return { data: filtered, displayText: formatRatesSummary(filtered) };\n }\n\n if (hasAgent(context)) {\n const agent = requireAgent(context);\n const all = await agent.rates();\n const filtered = applyFilters(all, opts);\n return { data: filtered, displayText: formatRatesSummary(filtered) };\n }\n\n // [v1.4 — Day 3] No third tier. Both upstream paths are unavailable\n // — surface that honestly so the LLM can route the user (e.g. \"try\n // again in a moment\") instead of fabricating a number from a\n // deprecated vendor.\n throw new Error(\n 'rates_info: NAVI lending data is currently unavailable. Try again shortly.',\n );\n },\n});\n\n// Exported for testing.\nexport const _internal = { applyFilters, isStable, STABLECOIN_SYMBOLS, expandAliases, TOKEN_ALIASES };\n","import { z } from 'zod';\nimport {\n classifyTransaction,\n extractTransferDetails,\n type ClassifyBalanceChange,\n type TxDirection,\n} from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\nimport { fetchAudricHistory } from '../audric-api.js';\nimport { normalizeAddressInput } from '../sui-address.js';\n\ntype RpcBalanceChange = ClassifyBalanceChange;\n\ninterface RpcTxBlock {\n digest: string;\n timestampMs?: string;\n transaction?: unknown;\n effects?: { gasUsed?: { computationCost: string; storageCost: string; storageRebate: string } };\n balanceChanges?: RpcBalanceChange[];\n}\n\ninterface TxRecord {\n digest: string;\n /**\n * [v1.4] Coarse bucket — one of `'send' | 'lending' | 'swap' |\n * 'transaction'`. Used by the ACI `action` filter and persisted\n * downstream queries depend on these values, so they are STABLE.\n */\n action: string;\n /**\n * [v1.5.3] Finer-grained display label derived from the\n * Move-call function name (e.g. `'deposit'`, `'withdraw'`,\n * `'payment_link'`, `'on-chain'`). Optional — frontends should\n * fall back to `action` when missing. Never used by filters.\n */\n label?: string;\n amount?: number;\n asset?: string;\n recipient?: string;\n /**\n * [v0.46.2] Direction of the user's principal balance change on\n * this tx (`'in'` → user received, `'out'` → user spent). Lets the\n * card render the correct sign without parsing the textual label.\n */\n direction?: TxDirection;\n timestamp: number;\n date?: string;\n gasCost?: number;\n}\n\nfunction parseRpcTx(tx: RpcTxBlock, address: string): TxRecord {\n const gasUsed = tx.effects?.gasUsed;\n const gasCost = gasUsed\n ? (Number(gasUsed.computationCost) + Number(gasUsed.storageCost) - Number(gasUsed.storageRebate)) / 1e9\n : undefined;\n\n const moveCallTargets: string[] = [];\n const commandTypes: string[] = [];\n try {\n /**\n * Sui JSON-RPC `suix_queryTransactionBlocks` returns the\n * ProgrammableTransaction body with the legacy field name\n * `transactions` (plural). Newer SDK-side types refer to the same\n * data as `commands`. Cover both — the v1.5.3 engine path was\n * only checking `commands`, which always returned empty for prod\n * RPC responses, so every row in the transaction history card\n * fell back to `label: 'on-chain'`.\n */\n const data = (tx.transaction as Record<string, unknown>)?.data as Record<string, unknown> | undefined;\n const inner = data?.transaction as Record<string, unknown> | undefined;\n const commands = (inner?.commands ?? inner?.transactions) as Record<string, unknown>[] | undefined;\n if (Array.isArray(commands)) {\n for (const cmd of commands) {\n if (cmd.MoveCall) {\n const mc = cmd.MoveCall as { package: string; module: string; function: string };\n moveCallTargets.push(`${mc.package}::${mc.module}::${mc.function}`);\n commandTypes.push('MoveCall');\n } else if (cmd.TransferObjects) {\n commandTypes.push('TransferObjects');\n }\n }\n }\n } catch { /* best effort */ }\n\n const changes = tx.balanceChanges ?? [];\n const { amount, asset, recipient, direction } = extractTransferDetails(changes, address);\n\n const timestampMs = Number(tx.timestampMs ?? 0);\n const { action, label } = classifyTransaction(moveCallTargets, commandTypes, changes, address);\n\n return {\n digest: tx.digest,\n action,\n label,\n amount,\n asset,\n recipient,\n direction,\n timestamp: timestampMs,\n date: timestampMs > 0 ? new Date(timestampMs).toISOString() : undefined,\n gasCost,\n };\n}\n\n/**\n * RPC query direction. `from` queries `FromAddress` (txs the address sent /\n * signed); `to` queries `ToAddress` (txs the address received). Pre-v0.48\n * the tool only used `from`, which silently dropped pure-receive\n * transactions (someone pays you, no balance-affecting outbound from your\n * account) — so user-reported counts like \"I had 15 txs that day, you\n * showed 13\" lined up with the missing inbound rows. The dual-direction\n * query parallelizes both filters and dedupes by `digest` since txs\n * involving two of the user's own addresses (rare) or self-sends would\n * appear in both result sets.\n */\ntype QueryDirection = 'from' | 'to';\n\nasync function queryHistoryPage(\n rpcUrl: string,\n address: string,\n direction: QueryDirection,\n limit: number,\n cursor: string | null,\n): Promise<{ data: RpcTxBlock[]; nextCursor: string | null; hasNextPage: boolean }> {\n const filter = direction === 'from' ? { FromAddress: address } : { ToAddress: address };\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'suix_queryTransactionBlocks',\n params: [\n { filter, options: { showEffects: true, showInput: true, showBalanceChanges: true } },\n cursor,\n limit,\n true,\n ],\n }),\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!res.ok) throw new Error(`Sui RPC error: ${res.status}`);\n const json = (await res.json()) as {\n result?: { data: RpcTxBlock[]; nextCursor: string | null; hasNextPage: boolean };\n error?: { message: string };\n };\n if (json.error) throw new Error(`RPC error: ${json.error.message}`);\n return {\n data: json.result?.data ?? [],\n nextCursor: json.result?.nextCursor ?? null,\n hasNextPage: json.result?.hasNextPage ?? false,\n };\n}\n\n/**\n * Merge two arrays of RPC txs by `digest`, preserving the most-recent\n * timestamp ordering. Each digest appears at most once in the output.\n */\nfunction mergeAndDedupe(a: RpcTxBlock[], b: RpcTxBlock[]): RpcTxBlock[] {\n const byDigest = new Map<string, RpcTxBlock>();\n for (const tx of [...a, ...b]) {\n if (!byDigest.has(tx.digest)) byDigest.set(tx.digest, tx);\n }\n return [...byDigest.values()].sort((x, y) => Number(y.timestampMs ?? 0) - Number(x.timestampMs ?? 0));\n}\n\nasync function queryHistoryRpc(rpcUrl: string, address: string, limit: number): Promise<TxRecord[]> {\n // Over-fetch each direction by `limit` (Sui RPC caps page size, but most\n // active wallets won't hit it) so the merged set still has at least\n // `limit` rows after dedupe.\n const [fromPage, toPage] = await Promise.all([\n queryHistoryPage(rpcUrl, address, 'from', limit, null).catch(() => ({ data: [] as RpcTxBlock[], nextCursor: null, hasNextPage: false })),\n queryHistoryPage(rpcUrl, address, 'to', limit, null).catch(() => ({ data: [] as RpcTxBlock[], nextCursor: null, hasNextPage: false })),\n ]);\n const merged = mergeAndDedupe(fromPage.data, toPage.data);\n return merged.slice(0, limit).map((tx) => parseRpcTx(tx, address));\n}\n\n/**\n * Paginate backwards through transaction history (both directions in\n * parallel) to find transactions on a specific calendar day. Returns up\n * to `limit` transactions from that day. Each direction stops paginating\n * once it reaches a tx older than `dayStart` — the merge happens at the\n * end so neither direction exits the loop early just because the OTHER\n * direction's page contained newer rows.\n */\nasync function queryHistoryByDate(\n rpcUrl: string,\n address: string,\n targetDate: string,\n limit: number,\n): Promise<TxRecord[]> {\n const target = new Date(targetDate);\n const dayStart = new Date(target.getFullYear(), target.getMonth(), target.getDate()).getTime();\n const dayEnd = dayStart + 86_400_000;\n const MAX_PAGES = 20;\n const PAGE_SIZE = 50;\n\n async function paginateDirection(direction: QueryDirection): Promise<RpcTxBlock[]> {\n const collected: RpcTxBlock[] = [];\n let cursor: string | null = null;\n\n for (let page = 0; page < MAX_PAGES; page++) {\n let res: Awaited<ReturnType<typeof queryHistoryPage>>;\n try {\n res = await queryHistoryPage(rpcUrl, address, direction, PAGE_SIZE, cursor);\n } catch {\n break;\n }\n if (res.data.length === 0) break;\n\n let reachedOld = false;\n for (const tx of res.data) {\n const ts = Number(tx.timestampMs ?? 0);\n if (ts === 0) continue;\n if (ts < dayStart) { reachedOld = true; break; }\n if (ts >= dayStart && ts < dayEnd) collected.push(tx);\n }\n\n if (reachedOld || !res.hasNextPage || !res.nextCursor) break;\n cursor = res.nextCursor;\n }\n return collected;\n }\n\n const [fromTxs, toTxs] = await Promise.all([\n paginateDirection('from'),\n paginateDirection('to'),\n ]);\n const merged = mergeAndDedupe(fromTxs, toTxs);\n return merged.slice(0, limit).map((tx) => parseRpcTx(tx, address));\n}\n\n/**\n * [v1.4 ACI] Allowed values for the `action` filter — kept in sync with\n * `classifyAction` above (the labels it can return).\n */\nconst HISTORY_ACTIONS = ['send', 'lending', 'swap', 'transaction'] as const;\ntype HistoryAction = (typeof HISTORY_ACTIONS)[number];\n\nconst DEFAULT_LOOKBACK_DAYS = 30;\n\n// [v1.2 SuiNS] The local SUI_ADDRESS_REGEX has moved to `sui-address.ts`\n// (canonical normalizer). The Zod schema below accepts both 0x addresses\n// and *.sui names; `normalizeAddressInput` validates and resolves at the\n// top of `call()`.\n\nexport const transactionHistoryTool = buildTool({\n name: 'transaction_history',\n description:\n 'Retrieve recent transaction history (last 30 days by default): sends, saves, withdrawals, borrows, repayments, swaps, and rewards claims. Renders a rich transaction card.\\n\\n' +\n 'By default, queries the SIGNED-IN USER\\'S history. To inspect another wallet (a saved contact, a watched address, any public Sui address), pass `address` — e.g. user asks \"show funkii\\'s recent transactions\" with funkii at 0x40cd…3e62, call with `address: \"0x40cd…3e62\"`. To filter the user\\'s own history to a specific counterparty (user asks \"show transactions WITH funkii\"), pass `counterparty` — keeps the query rooted in the user\\'s wallet but shows only rows where funkii is the recipient or sender.\\n\\n' +\n 'Filter args: `date` (YYYY-MM-DD), `action` (send/lending/swap), `minUsd` (minimum amount in USD — 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 — never re-list the rows in narration.\\n\\n' +\n 'Internally queries both `FromAddress` and `ToAddress` filters in parallel and dedupes by digest, so pure-receive transactions (someone sends to the queried address with no balance-affecting outbound) are no longer dropped.',\n inputSchema: z.object({\n limit: z.number().int().min(1).max(50).optional(),\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (e.g. \"alex.sui\") to query history FOR. When omitted, defaults to the signed-in user\\'s wallet. Pass this when the user asks about a contact\\'s, watched address\\'s, or any other public wallet\\'s history.'),\n counterparty: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (e.g. \"alex.sui\") to filter rows by — only transactions where the queried address sent to or received from this counterparty are returned. Use for \"show transactions with <contact>\" queries. Compares against `tx.recipient` (case-insensitive).'),\n date: z.string().optional().describe('Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day.'),\n action: z.enum(HISTORY_ACTIONS).optional().describe('Filter by action: send, lending, swap, or transaction.'),\n minUsd: z.number().min(0).optional().describe('Minimum transaction amount in USD. Use this for \"transactions over $X\" — the amount is converted to USD using the asset price snapshot.'),\n assetSymbol: z.string().optional().describe('Filter to a single asset symbol (case-insensitive, e.g. \"USDC\", \"SUI\", \"LOFI\"). Matches `tx.asset` exactly.'),\n direction: z.enum(['in', 'out']).optional().describe('Filter by user-side balance flow: \"in\" = received, \"out\" = spent.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n limit: {\n type: 'number',\n description: 'Maximum number of transactions to return (1-50, default 10)',\n },\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui) to query history FOR (defaults to the signed-in user when omitted). The engine resolves SuiNS names to addresses before querying. Use for queries about a contact\\'s, watched address\\'s, or any other wallet\\'s history.',\n },\n counterparty: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui) to filter rows by — only transactions where the queried address sent to or received from this counterparty are returned. Use for \"show transactions with <contact>\" queries.',\n },\n date: {\n type: 'string',\n description: 'Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day.',\n },\n action: {\n type: 'string',\n enum: [...HISTORY_ACTIONS],\n description: 'Filter results by action category: send, lending, swap, or transaction.',\n },\n minUsd: {\n type: 'number',\n description: 'Minimum transaction amount in USD. Use this for \"transactions over $X\" queries.',\n },\n assetSymbol: {\n type: 'string',\n description: 'Filter to a single asset symbol (case-insensitive, e.g. \"USDC\", \"SUI\").',\n },\n direction: {\n type: 'string',\n enum: ['in', 'out'],\n description: 'Filter by direction of user balance change: \"in\" = received, \"out\" = spent.',\n },\n },\n },\n isReadOnly: true,\n maxResultSizeChars: 8_000,\n // [v1.5.1] New transactions land continuously. Even with an explicit\n // `date` filter the dedupe is wrong post-write because the just-\n // executed write may now be in history. Never dedupe.\n cacheable: false,\n /**\n * [v1.5.2] Custom truncation that preserves the structured shape.\n *\n * The default `budgetToolResult` slices the JSON string at the byte\n * limit, appends a \"[Truncated…]\" note, and tries `JSON.parse` — which\n * always fails for sliced JSON, so the engine falls back to returning\n * the raw string. The frontend's `transaction_history` card renderer\n * then sees `typeof data !== 'object'` and bails, so the rich card\n * never renders even though the LLM has the full text.\n *\n * Strategy: progressively halve the `transactions` array until the\n * serialized payload fits, then stamp `_truncated: true` and the\n * original length so the LLM knows to recall with `limit` if it needs\n * older entries. Result is always valid JSON, always object-shaped.\n */\n summarizeOnTruncate(serialized, maxChars) {\n type ParsedHistory = {\n transactions: unknown[];\n count: number;\n [k: string]: unknown;\n };\n let parsed: ParsedHistory;\n try {\n parsed = JSON.parse(serialized) as ParsedHistory;\n } catch {\n return JSON.stringify({\n transactions: [],\n count: 0,\n _truncated: true,\n _note: 'Result exceeded size budget and could not be summarized.',\n });\n }\n const original = Array.isArray(parsed.transactions) ? parsed.transactions : [];\n let trimmed = original.slice();\n let payload = JSON.stringify({ ...parsed, transactions: trimmed, _truncated: true, _originalCount: original.length });\n while (payload.length > maxChars && trimmed.length > 1) {\n trimmed = trimmed.slice(0, Math.max(1, Math.floor(trimmed.length / 2)));\n payload = JSON.stringify({ ...parsed, transactions: trimmed, _truncated: true, _originalCount: original.length });\n }\n return payload;\n },\n\n async call(\n input,\n context,\n ): Promise<{ data: Record<string, unknown>; displayText: string }> {\n const limit = input.limit ?? 10;\n const action = input.action as HistoryAction | undefined;\n const assetSymbol = input.assetSymbol?.toLowerCase();\n const direction = input.direction;\n const minUsd = input.minUsd;\n\n /**\n * [v1.2 SuiNS] Normalize both the primary address and counterparty\n * (each accepts a 0x address OR a *.sui name). Uses `Promise.all`\n * so a SuiNS round-trip on either field doesn't add up serially.\n */\n const [normalizedAddress, normalizedCounterparty] = await Promise.all([\n input.address\n ? normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n })\n : Promise.resolve(null),\n input.counterparty\n ? normalizeAddressInput(input.counterparty, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n })\n : Promise.resolve(null),\n ]);\n\n const suinsName = normalizedAddress?.suinsName ?? null;\n const counterpartySuinsName = normalizedCounterparty?.suinsName ?? null;\n const counterpartyLower = normalizedCounterparty?.address.toLowerCase();\n\n /**\n * Resolve the address whose history we're fetching. Normalized\n * `input.address` (when present) takes precedence; falls back to\n * the signed-in user. Tracking `isSelfQuery` lets the result payload\n * advertise whether the rows belong to the user or a third party,\n * which the frontend card uses to title itself (\"Recent\n * Transactions\" vs \"alex.sui — Recent Transactions\" vs \"0x40cd…3e62\n * — Recent Transactions\") and which the LLM uses to narrate\n * correctly without re-typing the address.\n */\n const targetAddress = normalizedAddress?.address ?? context.walletAddress;\n const isSelfQuery =\n !!targetAddress &&\n !!context.walletAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n /**\n * [v0.46.6] Price snapshot for `minUsd` filtering. Sourced from the\n * session-injected token-price map (populated by the prefetch step\n * in audric's engine-factory). Falls back to \"no USD value known\"\n * when the asset isn't in the snapshot — those rows skip the\n * `minUsd` filter rather than being silently dropped, since we\n * don't have ground truth.\n */\n const prices: Record<string, number> | undefined = (\n context as unknown as { tokenPrices?: Record<string, number> }\n ).tokenPrices;\n const priceFor = (sym: string | undefined): number | undefined => {\n if (!sym || !prices) return undefined;\n return prices[sym.toUpperCase()] ?? prices[sym.toLowerCase()] ?? prices[sym];\n };\n\n /**\n * [v1.4] After fetching, narrow by `action` (when supplied), and trim\n * to a `DEFAULT_LOOKBACK_DAYS` window when no explicit date is given —\n * keeps results recent and bounded so the LLM doesn't over-summarize.\n *\n * [v0.46.6] Now also honors `assetSymbol`, `direction`, and `minUsd`\n * so single questions like \"show transactions over $5\" or \"show my\n * USDC sends\" produce a card whose rows already match the question —\n * the LLM never needs to filter in narration.\n */\n const finalize = (records: TxRecord[]): TxRecord[] => {\n let scoped = records;\n if (action) scoped = scoped.filter((r) => r.action === action);\n if (assetSymbol) {\n scoped = scoped.filter((r) => r.asset?.toLowerCase() === assetSymbol);\n }\n if (direction) {\n scoped = scoped.filter((r) => r.direction === direction);\n }\n if (counterpartyLower) {\n // [v0.48] The `counterparty` filter is intentionally narrow: it\n // matches `tx.recipient` (the parsed counterparty extracted from\n // balance changes by `extractTransferDetails`) — not raw RPC\n // sender/receiver fields, since those reflect signer addresses\n // (often sponsor wallets) rather than the actual fund flow.\n // Rows with no counterparty (e.g. NAVI lending operations against\n // a shared object) are excluded — the user asked \"show\n // transactions with <X>\", and a NAVI deposit isn't with anyone.\n scoped = scoped.filter((r) => r.recipient?.toLowerCase() === counterpartyLower);\n }\n if (minUsd != null && minUsd > 0) {\n scoped = scoped.filter((r) => {\n if (r.amount == null) return false;\n // For USD-pegged assets we treat the unit amount as USD value.\n // For others, multiply by the snapshot price when known.\n const sym = r.asset?.toUpperCase() ?? '';\n const isStableLike =\n sym === 'USDC' || sym === 'USDT' || sym === 'WUSDC' || sym === 'WUSDT' ||\n sym === 'SUIUSDT' || sym === 'USDY' || sym === 'USDSUI' || sym === 'USDE' ||\n sym === 'AUSD' || sym === 'FDUSD' || sym === 'BUCK';\n const usd = isStableLike ? r.amount : (priceFor(sym) ?? 0) * r.amount;\n // When we genuinely don't know the price, KEEP the row rather\n // than silently dropping it — better to over-include than to\n // hide transactions the user expects to see.\n if (!isStableLike && priceFor(sym) == null) return true;\n return usd >= minUsd;\n });\n }\n return scoped.slice(0, limit);\n };\n\n const filterMeta = {\n date: input.date ?? null,\n action: action ?? null,\n minUsd: minUsd ?? null,\n assetSymbol: input.assetSymbol ?? null,\n direction: direction ?? null,\n // Pre-resolved counterparty address (for the LLM/UI). Original\n // SuiNS name is preserved in `counterpartySuinsName` below.\n counterparty: normalizedCounterparty?.address ?? null,\n counterpartySuinsName,\n address: targetAddress ?? null,\n isSelfQuery,\n suinsName,\n };\n\n /**\n * The agent path (used in CLI / SDK direct-tool mode) doesn't\n * support arbitrary-address queries today — the agent's `history()`\n * call is hardwired to its own wallet. Reject explicit `address`\n * usage here rather than silently returning the wrong rows. Callers\n * needing third-party history should use the RPC path (web).\n */\n if (context.agent) {\n if (input.address && !isSelfQuery) {\n throw new Error(\n 'transaction_history `address` parameter is not supported in CLI/SDK agent mode — only the signed-in user\\'s history is available. Use the web client for third-party address queries.',\n );\n }\n const agent = requireAgent(context);\n const records = await agent.history({ limit: input.date ? limit : Math.max(limit * 4, 50) });\n const filtered = finalize(records);\n return {\n data: { transactions: filtered, count: filtered.length, ...filterMeta },\n displayText: `${filtered.length} recent transaction(s)`,\n };\n }\n\n if (!targetAddress) {\n throw new Error('Transaction history requires a wallet address');\n }\n\n // [single-source-of-truth — Apr 2026] Try audric's canonical\n // `/api/history` first. The route already merges FromAddress +\n // ToAddress, dedupes by digest, and runs the same `parseSuiRpcTx`\n // parser the engine uses, so the wire shape is a 1:1 match. Returns\n // null in CLI / MCP / standalone mode → falls through to the\n // existing Sui-RPC path below.\n //\n // Note: the date-paginated path (`input.date`) keeps using direct\n // RPC because audric's `/api/history` doesn't currently expose a\n // date filter. Same goes for the standalone-engine fallback.\n if (!input.date) {\n const audricRecords = await fetchAudricHistory(\n targetAddress,\n { limit: Math.max(limit * 4, 50) },\n context.env,\n context.signal,\n );\n if (audricRecords) {\n const cutoffMs = Date.now() - DEFAULT_LOOKBACK_DAYS * 86_400_000;\n const recent = audricRecords.filter((r) => r.timestamp >= cutoffMs);\n const filtered = finalize(recent);\n return {\n data: {\n transactions: filtered,\n count: filtered.length,\n ...filterMeta,\n lookbackDays: DEFAULT_LOOKBACK_DAYS,\n },\n displayText: `${filtered.length} transaction(s) in the last ${DEFAULT_LOOKBACK_DAYS} days`,\n };\n }\n }\n\n if (!context.suiRpcUrl) {\n throw new Error('Transaction history requires a Sui RPC URL when audric API is unavailable');\n }\n\n if (input.date) {\n const records = await queryHistoryByDate(\n context.suiRpcUrl,\n targetAddress,\n input.date,\n Math.max(limit * 4, 50),\n );\n const filtered = finalize(records);\n const dateLabel = new Date(input.date).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });\n return {\n data: { transactions: filtered, count: filtered.length, ...filterMeta },\n displayText: filtered.length > 0\n ? `${filtered.length} transaction(s) on ${dateLabel}`\n : `No transactions found on ${dateLabel}`,\n };\n }\n\n // No date — last 30 days. Over-fetch then trim by lookback window.\n const cutoffMs = Date.now() - DEFAULT_LOOKBACK_DAYS * 86_400_000;\n const records = await queryHistoryRpc(\n context.suiRpcUrl,\n targetAddress,\n Math.max(limit * 4, 50),\n );\n const recent = records.filter((r) => r.timestamp >= cutoffMs);\n const filtered = finalize(recent);\n return {\n data: {\n transactions: filtered,\n count: filtered.length,\n ...filterMeta,\n lookbackDays: DEFAULT_LOOKBACK_DAYS,\n },\n displayText: `${filtered.length} transaction(s) in the last ${DEFAULT_LOOKBACK_DAYS} days`,\n };\n },\n});\n","import { z } from 'zod';\nimport { assertAllowedAsset } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n// [v0.51.0] Allowed save assets — keep in sync with OPERATION_ASSETS.save in\n// @t2000/sdk. We assert via `assertAllowedAsset('save', ...)` at runtime, but\n// the description + preflight + JSON schema also need to surface the allowed\n// set so the LLM picks correctly without trial-and-error.\nconst SAVE_ASSETS = ['USDC', 'USDsui'] as const;\n\nexport const saveDepositTool = buildTool({\n name: 'save_deposit',\n description:\n 'Deposit USDC or USDsui into NAVI savings to earn yield. ONLY these two stables are accepted. ' +\n 'If the user asks to save/deposit any other token (GOLD, SUI, USDT, USDe, ETH, etc.), do NOT call this tool ' +\n 'and do NOT automatically swap their tokens and deposit. Instead, tell the user that only USDC and USDsui ' +\n 'deposits are supported and ask if they would like to swap first. Let the user decide — never auto-chain ' +\n 'swap + deposit. ' +\n 'When the user says \"save 10 USDC\" pass asset=\"USDC\". When they say \"save 10 USDsui\" pass asset=\"USDsui\". ' +\n 'When they say \"save 10\" with no asset, ALWAYS call balance_check first and ask which stable they want to ' +\n 'deposit (or default to whichever they hold more of, with a one-line note). Never silently substitute USDsui ' +\n 'for USDC or vice versa.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.enum(SAVE_ASSETS).optional().describe('\"USDC\" or \"USDsui\". Defaults to USDC when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n description: 'Exact amount to deposit (in units of the chosen asset)',\n },\n asset: {\n type: 'string',\n enum: ['USDC', 'USDsui'],\n description: 'Stable to deposit. \"USDC\" or \"USDsui\". Defaults to USDC when omitted.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n preflight: (input) => {\n if (input.asset) {\n const allowed = (SAVE_ASSETS as readonly string[]).map((a) => a.toUpperCase());\n if (!allowed.includes(input.asset.toUpperCase())) {\n return { valid: false, error: `Only USDC or USDsui deposits are supported. Got: \"${input.asset}\"` };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n assertAllowedAsset('save', input.asset);\n\n const agent = requireAgent(context);\n // [v0.51.0] Pass asset through — pre-v0.51 the SDK silently rewrote any\n // asset to 'USDC'. The runtime allow-list (assertAllowedAsset above) still\n // gates the input set, so this is safe.\n const asset = (input.asset as 'USDC' | 'USDsui' | undefined) ?? 'USDC';\n const result = await agent.save({ amount: input.amount, asset });\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset,\n apy: result.apy,\n fee: result.fee,\n gasCost: result.gasCost,\n savingsBalance: result.savingsBalance,\n },\n displayText: `Saved ${result.amount.toFixed(result.amount < 1 ? 6 : 2)} ${asset} at ${(result.apy * 100).toFixed(2)}% APY (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const withdrawTool = buildTool({\n name: 'withdraw',\n description:\n 'Withdraw from NAVI lending back to wallet. Defaults to USDC; also withdraws USDsui (the second active saveable stable). Legacy positions in other assets (USDe, SUI) can still be withdrawn if the user has them — but only USDC and USDsui are eligible to be re-deposited via save_deposit.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.string().optional().describe('Asset to withdraw (default: USDC). Active: USDsui. Legacy positions: USDe, SUI.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n description: 'Exact amount to withdraw in token units',\n },\n asset: {\n type: 'string',\n description: 'Asset to withdraw (default: USDC). Active: USDsui. Legacy positions: USDe, SUI.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, affectsHealth: true },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.withdraw({\n amount: input.amount,\n asset: input.asset,\n });\n\n const withdrawnAsset = (result as { asset?: string }).asset ?? input.asset ?? 'USDC';\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset: withdrawnAsset,\n gasCost: result.gasCost,\n },\n displayText: `Withdrew ${result.amount.toFixed(result.amount < 1 ? 6 : 2)} ${withdrawnAsset} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { ALL_NAVI_ASSETS, SUPPORTED_ASSETS, type SupportedAsset } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n/**\n * Tokens send_transfer can move. Mirrors `SUPPORTED_ASSETS` so a new\n * coin in the SDK constants is automatically settable here without\n * touching the tool.\n *\n * The history of this tool: it was originally USDC-only (description\n * literally said \"Send USDC...\"). When the LLM was asked to send a\n * non-USDC token (e.g. just-swapped SUI), it would call send_transfer\n * with the SUI amount, and the tool would silently ship USDC instead —\n * the user lost real money. See the audric-send-safety-and-auth follow-up:\n * \"Done! Swapped 1 USDC for 1.0561 SUI and sent it all to Wallet 1.\" was\n * the LLM's hallucinated success while only USDC actually moved.\n */\nconst ASSET_LIST = ALL_NAVI_ASSETS.map((a) => String(a)).join(', ');\n\nexport const sendTransferTool = buildTool({\n name: 'send_transfer',\n description:\n `Send ANY supported token (${ASSET_LIST}) to another Sui address or contact name. Validates the address, checks balance, and executes the on-chain transfer. ` +\n `MUST set the \\`asset\\` field to the token symbol you want to send (case-insensitive). If \\`asset\\` is omitted, USDC is assumed — only do this when the user explicitly asks for USDC. ` +\n `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. ` +\n `Returns tx hash, gas cost, and updated balance.`,\n inputSchema: z.object({\n to: z.string().min(1),\n amount: z.number().positive(),\n asset: z.string().optional(),\n memo: z.string().optional(),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n to: {\n type: 'string',\n description: 'Sui address (0x…) or saved contact name',\n },\n amount: {\n type: 'number',\n 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.',\n },\n asset: {\n type: 'string',\n 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.`,\n },\n memo: {\n type: 'string',\n description: 'Optional note attached to the transfer (shown in transaction receipt)',\n },\n },\n required: ['to', 'amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true, irreversible: true },\n preflight: (input) => {\n if (input.to.startsWith('0x') && !/^0x[a-fA-F0-9]{64}$/.test(input.to)) {\n return { valid: false, error: `Invalid Sui address format: \"${input.to}\". Must be 0x followed by 64 hex characters.` };\n }\n const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000000000000000000000000000';\n if (input.to === ZERO_ADDRESS) {\n return { valid: false, error: 'This is the zero address (burn address). Sending funds here will permanently destroy them. If you really intend to burn tokens, please confirm explicitly.' };\n }\n if (input.amount <= 0) {\n return { valid: false, error: 'Amount must be positive.' };\n }\n if (input.asset !== undefined) {\n const normalized = String(input.asset).toUpperCase();\n if (!(normalized in SUPPORTED_ASSETS)) {\n return {\n valid: false,\n error: `Unsupported asset \"${input.asset}\". send_transfer accepts: ${ASSET_LIST}.`,\n };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const asset = input.asset\n ? (String(input.asset).toUpperCase() as SupportedAsset)\n : 'USDC';\n const result = await agent.send({ to: input.to, amount: input.amount, asset });\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset,\n to: result.to,\n contactName: result.contactName,\n gasCost: result.gasCost,\n balance: result.balance,\n memo: input.memo ?? null,\n },\n displayText: `Sent ${result.amount} ${asset} to ${result.contactName ?? `${result.to.slice(0, 10)}…`} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { assertAllowedAsset } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n// [v0.51.0] Allowed borrow assets — keep in sync with OPERATION_ASSETS.borrow.\nconst BORROW_ASSETS = ['USDC', 'USDsui'] as const;\n\nexport const borrowTool = buildTool({\n name: 'borrow',\n description:\n 'Borrow USDC or USDsui against savings collateral. ONLY these two stables are supported. ' +\n 'Requires existing savings deposits as collateral. Checks max safe borrow and health factor. ' +\n 'Returns tx hash, fee, asset borrowed, and post-borrow health factor. ' +\n 'When the user says \"borrow 10 USDC\" pass asset=\"USDC\". When they say \"borrow 10 USDsui\" pass asset=\"USDsui\". ' +\n 'When they say \"borrow 10\" with no asset, default to USDC unless the user has only USDsui collateral.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.enum(BORROW_ASSETS).optional().describe('\"USDC\" or \"USDsui\". Defaults to USDC when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n type: 'number',\n description: 'Amount to borrow (in units of the chosen asset)',\n },\n asset: {\n type: 'string',\n enum: ['USDC', 'USDsui'],\n description: 'Stable to borrow. \"USDC\" or \"USDsui\". Defaults to USDC when omitted.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, affectsHealth: true },\n preflight: (input) => {\n if (input.asset) {\n const allowed = (BORROW_ASSETS as readonly string[]).map((a) => a.toUpperCase());\n if (!allowed.includes(input.asset.toUpperCase())) {\n return { valid: false, error: `Only USDC or USDsui borrows are supported. Got: \"${input.asset}\"` };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n assertAllowedAsset('borrow', input.asset);\n\n const agent = requireAgent(context);\n // [v0.51.0] Pass asset through — pre-v0.51 the SDK silently rewrote any\n // asset to 'USDC'. The runtime allow-list (assertAllowedAsset above) still\n // gates the input set, so this is safe.\n const asset = (input.asset as 'USDC' | 'USDsui' | undefined) ?? 'USDC';\n const result = await agent.borrow({ amount: input.amount, asset });\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset: result.asset ?? asset,\n fee: result.fee,\n healthFactor: result.healthFactor,\n gasCost: result.gasCost,\n },\n displayText: `Borrowed ${result.amount.toFixed(2)} ${asset} — HF: ${result.healthFactor.toFixed(2)} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nconst REPAY_ASSETS = ['USDC', 'USDsui'] as const;\n\nexport const repayDebtTool = buildTool({\n name: 'repay_debt',\n description:\n 'Repay outstanding USDC or USDsui debt. Always call balance_check first to know the debt amount + which asset is owed (savings_info shows per-asset borrow positions). ' +\n 'Pass asset=\"USDC\" or asset=\"USDsui\" to target a specific debt. When omitted, repays the highest-APY borrow first. ' +\n 'Important: a USDsui debt MUST be repaid with USDsui (and USDC debt with USDC) — the SDK fetches the correct coin type for the targeted asset, but the user must hold enough of that stable in their wallet. ' +\n 'If the user has only the wrong stable, do NOT auto-swap — tell them to swap manually first. Returns tx hash, amount repaid, asset, and remaining debt.',\n inputSchema: z.object({\n amount: z.number().positive(),\n asset: z.enum(REPAY_ASSETS).optional().describe('\"USDC\" or \"USDsui\". When omitted, repays the highest-APY borrow first.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: {\n description: 'Exact amount to repay (in units of the chosen asset; call balance_check first)',\n },\n asset: {\n type: 'string',\n enum: ['USDC', 'USDsui'],\n description: 'Asset of the borrow being repaid. When omitted, picks the highest-APY borrow.',\n },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n preflight: (input) => {\n if (input.asset) {\n const allowed = (REPAY_ASSETS as readonly string[]).map((a) => a.toUpperCase());\n if (!allowed.includes(input.asset.toUpperCase())) {\n return { valid: false, error: `Only USDC or USDsui repays are supported. Got: \"${input.asset}\"` };\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const asset = input.asset as 'USDC' | 'USDsui' | undefined;\n const result = await agent.repay({ amount: input.amount, asset });\n const repaidAsset = (result as { asset?: string }).asset ?? asset ?? 'USDC';\n\n return {\n data: {\n success: result.success,\n tx: result.tx,\n amount: result.amount,\n asset: repaidAsset,\n remainingDebt: result.remainingDebt,\n gasCost: result.gasCost,\n },\n displayText: `Repaid ${result.amount.toFixed(2)} ${repaidAsset} — remaining debt: $${result.remainingDebt.toFixed(2)} (tx: ${result.tx.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\n/**\n * Format an amount with adaptive precision so a 0.0165 vSUI claim\n * doesn't get stringified as \"0.02\" and the LLM can narrate the\n * actual on-chain credit accurately.\n */\nfunction formatAmount(amount: number): string {\n if (!Number.isFinite(amount) || amount <= 0) return '0';\n if (amount >= 1) return amount.toFixed(4).replace(/\\.?0+$/, '');\n if (amount >= 0.0001) return amount.toFixed(6).replace(/\\.?0+$/, '');\n return amount.toExponential(2);\n}\n\nexport const claimRewardsTool = buildTool({\n name: 'claim_rewards',\n description:\n 'Claim all pending protocol rewards across lending adapters. Returns the claimed reward breakdown (per-asset symbol + amount), total USD value (best effort — may be 0 when oracle prices are unavailable), and the on-chain tx hash. When the rewards list is empty the response will explicitly say \"no pending rewards\"; when it is non-empty narrate the per-symbol amounts even if totalValueUsd is 0 (the on-chain credit still happened).',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true },\n\n async call(_input, context) {\n const agent = requireAgent(context);\n const result = await agent.claimRewards();\n\n // The SDK adapter doesn't have access to a price oracle, so\n // `estimatedValueUsd` is always 0 from upstream. The engine, however,\n // has a `priceCache` populated by the harness (symbol → USD), so we\n // enrich here. This means the card / LLM can report \"$0.04 vSUI\"\n // instead of \"$0.00\" whenever a price is known, while still gracefully\n // degrading to per-symbol amounts when it isn't.\n const priceCache = context.priceCache;\n const enrichedRewards = result.rewards.map((r) => {\n if (r.estimatedValueUsd > 0) return r;\n const price = priceCache?.get(r.symbol.toUpperCase());\n if (!price || !Number.isFinite(price) || price <= 0) return r;\n return { ...r, estimatedValueUsd: r.amount * price };\n });\n\n const totalValueUsd = enrichedRewards.reduce(\n (s, r) => s + (Number.isFinite(r.estimatedValueUsd) ? r.estimatedValueUsd : 0),\n 0,\n );\n\n const txShort = result.tx ? `${result.tx.slice(0, 8)}…` : '';\n let displayText: string;\n\n if (enrichedRewards.length === 0) {\n displayText = 'No pending rewards to claim.';\n } else {\n // Always include per-symbol amounts so the narration is grounded\n // in the actual on-chain credit even when USD pricing is missing.\n const breakdown = enrichedRewards\n .map((r) => `${formatAmount(r.amount)} ${r.symbol}`)\n .join(', ');\n const usdSuffix = totalValueUsd > 0 ? ` (~$${totalValueUsd.toFixed(2)})` : '';\n const txSuffix = txShort ? ` (tx: ${txShort})` : '';\n displayText = `Claimed ${breakdown}${usdSuffix}${txSuffix}`;\n }\n\n return {\n data: {\n success: result.success,\n tx: result.tx || null,\n rewards: enrichedRewards,\n totalValueUsd,\n gasCost: result.gasCost,\n },\n displayText,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nconst MPP_GATEWAY = 'https://mpp.t2000.ai';\n\nconst SERVICE_PRICES: [RegExp, number][] = [\n [/\\/fal\\//, 0.03],\n [/\\/googlemaps\\//, 0.01],\n [/\\/perplexity\\//, 0.01],\n [/\\/firecrawl\\//, 0.01],\n [/\\/serpapi\\//, 0.01],\n [/\\/openweather\\//, 0.005],\n [/\\/brave\\//, 0.005],\n [/\\/serper\\//, 0.005],\n [/\\/newsapi\\//, 0.005],\n [/\\/coingecko\\//, 0.005],\n [/\\/alphavantage\\//, 0.005],\n [/\\/exchangerate\\//, 0.005],\n [/\\/deepl\\//, 0.005],\n [/\\/jina\\//, 0.005],\n [/\\/resend\\//, 0.005],\n];\n\nexport function estimatePayApiCost(url: string): number {\n for (const [pattern, price] of SERVICE_PRICES) {\n if (pattern.test(url)) return price;\n }\n return 0.005;\n}\n\nexport const payApiTool = buildTool({\n name: 'pay_api',\n description: `Execute any MPP gateway service via on-chain USDC micropayment. The gateway at ${MPP_GATEWAY} hosts 40+ services (88 endpoints). Payment is handled automatically.\n\nUse mpp_services tool first to discover available services and get the correct endpoint URL, required body parameters, and pricing. Then call this tool with the full URL and JSON body.\n\nAlways use POST. Construct the URL from the gateway base + service path. Pass parameters as a JSON string in body.\n\nCRITICAL — non-retryable errors: If the result contains \"doNotRetry\": true or \"paymentConfirmed\": true, the user has ALREADY been charged. NEVER call pay_api again for the same request. Report the error to the user.\n\nLob (postcards/letters) — MULTI-STEP, NEVER skip:\n1. Generate design image FIRST via fal/fal-ai/flux/dev ($0.03). Show the image to the user as markdown ![design](url).\n2. Ask the user to confirm before mailing (\"Here's the design. Print and mail for $1.00?\").\n3. ONLY after user confirms: call lob/v1/postcards with the image URL in the front HTML (<img src=\"URL\" style=\"width:100%;height:100%;object-fit:cover\"/>).\nAlways use ISO-3166 country codes (GB not UK, US not USA). A return address (\"from\") is added automatically — do not include one.`,\n inputSchema: z.object({\n url: z.string().url(),\n method: z.enum(['GET', 'POST', 'PUT', 'DELETE']).optional(),\n body: z.string().optional(),\n headers: z.record(z.string()).optional(),\n maxPrice: z.number().positive().optional(),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'Full MPP endpoint URL (e.g. https://mpp.t2000.ai/openweather/v1/weather)' },\n method: { type: 'string', description: 'HTTP method (always POST for MPP gateway)' },\n body: { type: 'string', description: 'JSON request body as string' },\n headers: { type: 'object', description: 'Additional HTTP headers' },\n maxPrice: { type: 'number', description: 'Maximum price in USD willing to pay (default: service price)' },\n },\n required: ['url'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true, costAware: true, producesArtifact: true, maxRetries: 1 },\n preflight: (input) => {\n if (!input.url.startsWith(MPP_GATEWAY)) {\n return { valid: false, error: `URL must start with ${MPP_GATEWAY}. Got: \"${input.url}\"` };\n }\n if (input.body) {\n try {\n JSON.parse(input.body);\n } catch {\n return { valid: false, error: 'body must be valid JSON.' };\n }\n if (input.url.includes('lob/')) {\n const body = JSON.parse(input.body) as Record<string, unknown>;\n const to = body.to as Record<string, unknown> | undefined;\n const country = to?.address_country;\n if (typeof country === 'string' && country.length !== 2) {\n return { valid: false, error: `Country must be ISO-3166 2-letter code (got \"${country}\")` };\n }\n }\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.pay({\n url: input.url,\n method: input.method,\n body: input.body,\n headers: input.headers,\n maxPrice: input.maxPrice,\n });\n\n return {\n data: {\n status: result.status,\n body: result.body,\n paid: result.paid,\n cost: result.cost,\n receipt: result.receipt,\n },\n displayText: result.paid\n ? `API call completed — paid $${result.cost?.toFixed(4) ?? '?'} (status: ${result.status})`\n : `API call completed — free (status: ${result.status})`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst MPP_GATEWAY = 'https://mpp.t2000.ai';\nconst CATALOG_URL = `${MPP_GATEWAY}/api/services`;\nconst CACHE_TTL = 120_000;\n\ninterface GatewayEndpoint {\n method: string;\n path: string;\n description: string;\n price: string;\n}\n\ninterface GatewayService {\n id: string;\n name: string;\n serviceUrl: string;\n description: string;\n categories: string[];\n endpoints: GatewayEndpoint[];\n}\n\nlet catalogCache: { data: GatewayService[]; ts: number } | null = null;\n\nasync function fetchCatalog(): Promise<GatewayService[]> {\n if (catalogCache && Date.now() - catalogCache.ts < CACHE_TTL) {\n return catalogCache.data;\n }\n const res = await fetch(CATALOG_URL, { signal: AbortSignal.timeout(10_000) });\n if (!res.ok) throw new Error(`MPP catalog fetch failed: HTTP ${res.status}`);\n const data = (await res.json()) as GatewayService[];\n catalogCache = { data, ts: Date.now() };\n return data;\n}\n\nfunction renderServices(catalog: GatewayService[]) {\n return catalog.map((s) => ({\n id: s.id,\n name: s.name,\n description: s.description,\n categories: s.categories,\n endpoints: s.endpoints.map((e) => ({\n url: `${MPP_GATEWAY}/${s.id}${e.path}`,\n method: e.method,\n description: e.description,\n price: `$${e.price}`,\n })),\n }));\n}\n\nfunction matchesQuery(service: GatewayService, q: string): boolean {\n const lower = q.toLowerCase();\n return (\n service.id.toLowerCase().includes(lower) ||\n service.name.toLowerCase().includes(lower) ||\n service.description.toLowerCase().includes(lower) ||\n service.categories.some((c) => c.toLowerCase().includes(lower)) ||\n service.endpoints.some((e) => e.description.toLowerCase().includes(lower))\n );\n}\n\nexport const mppServicesTool = buildTool({\n name: 'mpp_services',\n description:\n 'Discover available MPP gateway services. Returns service names, descriptions, endpoints with required parameters, and pricing. Use BEFORE calling pay_api. With no args, returns the FULL catalog as a single card (default behavior — covers \"show me available MPP services\", \"what services exist\", \"show me all MPP services\"). Use `query` to keyword-search a specific need (\"translate\", \"weather\", \"postcard\"). Use `category` to filter to one category. Use `mode: \"summary\"` only if you explicitly want a category-counts overview without the full list.',\n inputSchema: z.object({\n query: z\n .string()\n .optional()\n .describe('Filter by keyword (e.g. \"postcard\", \"translate\", \"weather\"). Returns matching services in one card.'),\n category: z\n .string()\n .optional()\n .describe('Filter by category exactly (e.g. \"weather\", \"image\"). Use mode:\"summary\" first if you need to see the category list.'),\n mode: z\n .enum(['summary', 'full'])\n .optional()\n .describe('\"full\" (default) returns the entire catalog in one card. \"summary\" returns category counts only — use this only when the user explicitly asks for a category overview.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Filter by keyword (e.g. \"postcard\", \"translate\", \"weather\").',\n },\n category: {\n type: 'string',\n description: 'Filter by category exactly (e.g. \"weather\", \"image\").',\n },\n mode: {\n type: 'string',\n enum: ['summary', 'full'],\n description: '\"full\" (default) returns the entire catalog in one card. \"summary\" returns category counts only.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n // [v0.46.6] Bumped to fit the full catalog (~40 services) in one\n // shot when `mode: 'full'` is used. The summarizeOnTruncate path\n // still applies if the catalog ever exceeds the budget.\n maxResultSizeChars: 12_000,\n\n async call(input): Promise<{ data: Record<string, unknown>; displayText: string }> {\n const catalog = await fetchCatalog();\n\n // [v0.46.7] Default behavior is now \"return the full catalog as a card.\"\n // Previously no-args returned a `_refine` payload that nudged the model to\n // re-call with a category — but in practice the model often re-called with\n // a category that returned 0 services, leaving an empty card. The full\n // catalog is small (~40 services, ~10KB) and fits comfortably in the\n // result budget, so there's no real cost to making it the default.\n //\n // The \"summary\" path (category counts only) is still available via the\n // explicit `mode:'summary'` opt-in for the rare case the user really wants\n // a category overview rather than the full list.\n if (input.mode !== 'summary' && !input.query && !input.category) {\n const services = renderServices(catalog);\n return {\n data: { services, total: services.length, mode: 'full' },\n displayText: `Full MPP catalog: ${services.length} services.`,\n };\n }\n\n if (input.mode === 'summary' && !input.query && !input.category) {\n const counts = new Map<string, number>();\n for (const svc of catalog) {\n for (const cat of svc.categories) {\n counts.set(cat, (counts.get(cat) ?? 0) + 1);\n }\n }\n const categories = [...counts.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([category, services]) => ({ category, services }));\n return {\n data: {\n _refine: {\n reason: 'Category summary (mode:\"summary\"). Re-call with a category or omit mode for the full catalog.',\n suggestedParams: { category: categories[0]?.category ?? 'weather' },\n allModes: ['summary', 'full'],\n },\n categories,\n totalServices: catalog.length,\n },\n displayText: `${catalog.length} services across ${categories.length} categories.`,\n };\n }\n\n let filtered = catalog;\n if (input.category) {\n const cat = input.category.toLowerCase();\n filtered = filtered.filter((s) => s.categories.some((c) => c.toLowerCase() === cat));\n }\n if (input.query) {\n filtered = filtered.filter((s) => matchesQuery(s, input.query!));\n }\n\n const services = renderServices(filtered);\n\n const filterDesc = [\n input.query ? `query \"${input.query}\"` : null,\n input.category ? `category \"${input.category}\"` : null,\n ].filter(Boolean).join(' + ');\n const summary = `Found ${services.length} service(s) matching ${filterDesc}`;\n\n return {\n data: { services, total: services.length },\n displayText: summary,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const swapExecuteTool = buildTool({\n name: 'swap_execute',\n description:\n 'Swap tokens on Sui via Cetus Aggregator (20+ DEXs). Supports any token pair with liquidity. Use user-friendly names (SUI, USDC, CETUS, DEEP, etc.) or full coin types.',\n inputSchema: z.object({\n from: z.string().describe('Source token (e.g. \"SUI\", \"USDC\", or full coin type)'),\n to: z.string().describe('Target token (e.g. \"USDC\", \"CETUS\", or full coin type)'),\n amount: z.number().positive().describe('Amount to swap'),\n byAmountIn: z.boolean().optional().describe('true = fixed input amount (default), false = fixed output amount'),\n slippage: z.number().min(0.001).max(0.05).optional().describe('Max slippage (default 0.01 = 1%, max 5%)'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n from: { type: 'string', description: 'Source token name or coin type' },\n to: { type: 'string', description: 'Target token name or coin type' },\n amount: { type: 'number', description: 'Amount to swap' },\n byAmountIn: { type: 'boolean', description: 'true = fixed input (default), false = fixed output' },\n slippage: { type: 'number', description: 'Max slippage (0.01 = 1%)' },\n },\n required: ['from', 'to', 'amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n preflight: (input) => {\n if (input.from.toLowerCase() === input.to.toLowerCase()) {\n return { valid: false, error: `Cannot swap ${input.from} to itself.` };\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.swap({\n from: input.from,\n to: input.to,\n amount: input.amount,\n byAmountIn: input.byAmountIn,\n slippage: input.slippage,\n });\n\n return {\n data: {\n tx: result.tx,\n fromToken: result.fromToken,\n toToken: result.toToken,\n fromAmount: result.fromAmount,\n toAmount: result.toAmount,\n priceImpact: result.priceImpact,\n route: result.route,\n gasCost: result.gasCost,\n },\n displayText: `Swapped ${result.fromAmount} ${result.fromToken} for ${result.toAmount.toFixed(4)} ${result.toToken} (tx: ${result.tx.slice(0, 8)}...)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { getSwapQuote } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\nimport { getWalletAddress } from './utils.js';\n\nexport const swapQuoteTool = buildTool({\n name: 'swap_quote',\n description:\n 'Get a swap quote without executing. Shows expected output amount, price impact, and route. Use before swap_execute to preview a trade.',\n inputSchema: z.object({\n from: z.string().describe('Source token (e.g. \"SUI\", \"USDC\", or full coin type)'),\n to: z.string().describe('Target token (e.g. \"USDC\", \"CETUS\", or full coin type)'),\n amount: z.number().positive().describe('Amount to swap'),\n byAmountIn: z.boolean().optional().describe('true = fixed input (default), false = fixed output'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n from: { type: 'string', description: 'Source token name or coin type' },\n to: { type: 'string', description: 'Target token name or coin type' },\n amount: { type: 'number', description: 'Amount to swap' },\n byAmountIn: { type: 'boolean', description: 'true = fixed input (default), false = fixed output' },\n },\n required: ['from', 'to', 'amount'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const walletAddress = context.agent\n ? (context.agent as { address(): string }).address()\n : getWalletAddress(context);\n\n const result = await getSwapQuote({\n walletAddress,\n from: input.from,\n to: input.to,\n amount: input.amount,\n byAmountIn: input.byAmountIn,\n });\n\n return {\n data: result,\n displayText: `${result.fromAmount} ${result.fromToken} → ${result.toAmount.toFixed(4)} ${result.toToken} (impact: ${(result.priceImpact * 100).toFixed(2)}%, via ${result.route})`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const voloStakeTool = buildTool({\n name: 'volo_stake',\n description:\n 'Stake SUI for vSUI via VOLO liquid staking. Earn ~3-5% APY. Rewards compound automatically via exchange rate — no claiming needed. Minimum 1 SUI.',\n inputSchema: z.object({\n amount: z.number().min(1).describe('Amount of SUI to stake (minimum 1)'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { type: 'number', description: 'Amount of SUI to stake' },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true, requiresBalance: true },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.stakeVSui({ amount: input.amount });\n\n return {\n data: {\n tx: result.tx,\n amountSui: result.amountSui,\n vSuiReceived: result.vSuiReceived,\n apy: result.apy,\n gasCost: result.gasCost,\n },\n displayText: `Staked ${result.amountSui} SUI for ${result.vSuiReceived.toFixed(4)} vSUI at ${(result.apy * 100).toFixed(2)}% APY (tx: ${result.tx.slice(0, 8)}...)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { requireAgent } from './utils.js';\n\nexport const voloUnstakeTool = buildTool({\n name: 'volo_unstake',\n description:\n 'Unstake vSUI back to SUI. Returns SUI including accumulated yield. Use amount in vSUI units or \"all\" to unstake entire position.',\n inputSchema: z.object({\n amount: z.union([z.number().positive(), z.literal('all')]).describe('Amount of vSUI to unstake, or \"all\"'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { description: 'Amount of vSUI to unstake, or the string \"all\"' },\n },\n required: ['amount'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n flags: { mutating: true },\n\n async call(input, context) {\n const agent = requireAgent(context);\n const result = await agent.unstakeVSui({ amount: input.amount });\n\n return {\n data: {\n tx: result.tx,\n vSuiAmount: result.vSuiAmount,\n suiReceived: result.suiReceived,\n gasCost: result.gasCost,\n },\n displayText: `Unstaked ${result.vSuiAmount.toFixed(4)} vSUI, received ${result.suiReceived.toFixed(4)} SUI (tx: ${result.tx.slice(0, 8)}...)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst VOLO_STATS_URL = 'https://open-api.naviprotocol.io/api/volo/stats';\n\nexport const voloStatsTool = buildTool({\n name: 'volo_stats',\n description:\n 'Get current VOLO liquid staking stats: vSUI APY, exchange rate, total staked SUI, and total vSUI supply.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {} },\n isReadOnly: true,\n\n async call() {\n const res = await fetch(VOLO_STATS_URL);\n if (!res.ok) throw new Error(`VOLO API returned ${res.status}`);\n\n const json = (await res.json()) as Record<string, unknown>;\n const data = (json.data ?? json) as {\n apy?: number;\n exchange_rate?: number;\n exchangeRate?: number;\n total_staked?: number;\n totalStaked?: number;\n total_vsui?: number;\n totalVSui?: number;\n };\n\n const stats = {\n apy: data.apy ?? 0,\n exchangeRate: data.exchange_rate ?? data.exchangeRate ?? 0,\n totalStaked: data.total_staked ?? data.totalStaked ?? 0,\n totalVSui: data.total_vsui ?? data.totalVSui ?? 0,\n };\n\n return {\n data: stats,\n displayText: `vSUI APY: ${(stats.apy * 100).toFixed(2)}%, Rate: 1 SUI = ${(1 / stats.exchangeRate).toFixed(4)} vSUI, Total staked: ${stats.totalStaked.toLocaleString()} SUI`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nexport const saveContactTool = buildTool({\n name: 'save_contact',\n description:\n 'Save a contact with a friendly name and Sui address so the user can send to them by name later.',\n inputSchema: z.object({\n name: z.string().describe('Friendly name for the contact (e.g. \"Alex\", \"Mom\")'),\n address: z.string().describe('Full Sui address (0x...)'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Friendly name for the contact' },\n address: { type: 'string', description: 'Full Sui address (0x...)' },\n },\n required: ['name', 'address'],\n },\n isReadOnly: false,\n permissionLevel: 'confirm',\n\n async call(input) {\n return {\n data: { saved: true, name: input.name, address: input.address },\n displayText: `Saved contact \"${input.name}\" (${input.address.slice(0, 8)}…)`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst BRAVE_API = 'https://api.search.brave.com/res/v1/web/search';\n\nconst inputSchema = z.object({\n query: z.string().describe('Search query'),\n count: z.number().optional().default(5).describe('Number of results (1-10)'),\n});\n\ninterface SearchResult {\n title: string;\n url: string;\n description: string;\n}\n\ninterface WebSearchData {\n results: SearchResult[];\n error?: string;\n}\n\nexport const webSearchTool = buildTool({\n name: 'web_search',\n description:\n 'Search the web for real-time information. Use for news, token info, project details, protocol documentation, or any question that needs current web data. Free for users.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Search query' },\n count: { type: 'number', description: 'Number of results (1-10)', default: 5 },\n },\n required: ['query'],\n },\n isReadOnly: true,\n maxResultSizeChars: 8_000,\n async call(input, context): Promise<{ data: WebSearchData; displayText: string }> {\n // [PR-B2] Hosts MUST pass `BRAVE_API_KEY` through `ToolContext.env`.\n // Direct `process.env` reads are banned in apps consuming the engine\n // (env-validation-gate.mdc) — the engine respects that contract by\n // routing every external secret through the typed context only.\n const apiKey = context.env?.BRAVE_API_KEY;\n if (!apiKey) {\n return {\n data: { results: [], error: 'Web search not configured' },\n displayText: 'Web search is not available.',\n };\n }\n\n const count = Math.min(Math.max(input.count ?? 5, 1), 10);\n const url = `${BRAVE_API}?q=${encodeURIComponent(input.query)}&count=${count}&text_decorations=false`;\n\n const res = await fetch(url, {\n headers: {\n 'Accept': 'application/json',\n 'Accept-Encoding': 'gzip',\n 'X-Subscription-Token': apiKey,\n },\n signal: AbortSignal.timeout(8_000),\n });\n\n if (!res.ok) {\n throw new Error(`Brave Search API error: HTTP ${res.status}`);\n }\n\n const json = await res.json() as {\n web?: { results?: Array<{ title: string; url: string; description: string }> };\n };\n\n const results: SearchResult[] = (json.web?.results ?? []).slice(0, count).map((r) => ({\n title: r.title,\n url: r.url,\n description: r.description,\n }));\n\n const displayText = results.length > 0\n ? results.map((r, i) => `${i + 1}. ${r.title}\\n ${r.url}\\n ${r.description}`).join('\\n\\n')\n : 'No results found.';\n\n return { data: { results }, displayText };\n },\n});\n","import { z } from 'zod';\nimport { getDecimalsForCoinType, resolveSymbol } from '@t2000/sdk';\nimport { buildTool } from '../tool.js';\n\nconst inputSchema = z.object({\n digest: z.string().describe('Sui transaction digest to explain'),\n});\n\ninterface TxEffect {\n type: string;\n description: string;\n}\n\ninterface ExplainedTx {\n digest: string;\n sender: string;\n status: string;\n gasUsed: string;\n timestamp?: string;\n effects: TxEffect[];\n summary: string;\n}\n\nexport const explainTxTool = buildTool({\n name: 'explain_tx',\n description:\n 'Explain a Sui transaction in plain English. Provide a transaction digest and get a human-readable breakdown of what happened — transfers, swaps, deposits, etc.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n digest: { type: 'string', description: 'Sui transaction digest' },\n },\n required: ['digest'],\n },\n isReadOnly: true,\n async call(input, context) {\n const rpcUrl = context.suiRpcUrl ?? 'https://fullnode.mainnet.sui.io:443';\n\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'sui_getTransactionBlock',\n params: [\n input.digest,\n {\n showInput: true,\n showEffects: true,\n showEvents: true,\n showBalanceChanges: true,\n showObjectChanges: true,\n },\n ],\n }),\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!res.ok) throw new Error(`Sui RPC error: HTTP ${res.status}`);\n const json = await res.json() as { result?: Record<string, unknown>; error?: { message: string } };\n\n if (json.error) throw new Error(json.error.message);\n if (!json.result) throw new Error('Transaction not found');\n\n const tx = json.result;\n const txInput = tx.transaction as Record<string, unknown> | undefined;\n const effects = tx.effects as Record<string, unknown> | undefined;\n const balanceChanges = tx.balanceChanges as Array<{ owner: Record<string, string>; coinType: string; amount: string }> | undefined;\n const events = tx.events as Array<{ type: string; parsedJson?: Record<string, unknown> }> | undefined;\n\n const txData = txInput?.data as Record<string, unknown> | undefined;\n const sender = txData?.sender as string ?? 'unknown';\n const gasData = txData?.gasData as Record<string, unknown> | undefined;\n const gasPayer = gasData?.owner as string ?? sender;\n const status = (effects?.status as Record<string, string>)?.status ?? 'unknown';\n const gasUsed = effects?.gasUsed as Record<string, string> | undefined;\n const gasCost = gasUsed\n ? (Number(gasUsed.computationCost ?? 0) + Number(gasUsed.storageCost ?? 0) - Number(gasUsed.storageRebate ?? 0)) / 1e9\n : 0;\n const timestamp = tx.timestampMs ? new Date(Number(tx.timestampMs)).toISOString() : undefined;\n\n const txEffects: TxEffect[] = [];\n\n if (balanceChanges?.length) {\n for (const bc of balanceChanges) {\n const ownerAddr = bc.owner?.AddressOwner ?? bc.owner?.ObjectOwner ?? 'unknown';\n // Use the canonical token registry so user-facing symbols are\n // friendly (e.g. `0x...::cert::CERT` → `vSUI`). Falls back to the\n // last `::` segment when the coin isn't in the registry.\n const symbol = resolveSymbol(bc.coinType);\n const amount = Number(bc.amount);\n const isNegative = amount < 0;\n const decimals = getDecimalsForCoinType(bc.coinType);\n const absHuman = Math.abs(amount / 10 ** decimals);\n\n if (bc.coinType.endsWith('::sui::SUI') && isNegative) {\n if (ownerAddr === gasPayer) {\n const netTransfer = absHuman - gasCost;\n if (netTransfer < 0.0001) continue;\n txEffects.push({\n type: 'send',\n description: `${ownerAddr.slice(0, 8)}...${ownerAddr.slice(-4)} sent ${netTransfer.toFixed(4)} ${symbol}`,\n });\n } else {\n txEffects.push({\n type: 'send',\n description: `${ownerAddr.slice(0, 8)}...${ownerAddr.slice(-4)} sent ${absHuman.toFixed(4)} ${symbol}`,\n });\n }\n continue;\n }\n\n txEffects.push({\n type: isNegative ? 'send' : 'receive',\n description: `${ownerAddr.slice(0, 8)}...${ownerAddr.slice(-4)} ${isNegative ? 'sent' : 'received'} ${absHuman.toFixed(decimals > 6 ? 4 : 2)} ${symbol}`,\n });\n }\n }\n\n if (events?.length) {\n for (const evt of events.slice(0, 5)) {\n const eventParts = evt.type.split('::');\n const eventName = eventParts[eventParts.length - 1] ?? evt.type;\n txEffects.push({\n type: 'event',\n description: `Event: ${eventName}`,\n });\n }\n }\n\n const summary = txEffects.length > 0\n ? txEffects.filter((e) => e.type !== 'event').map((e) => e.description).join('; ')\n : `Transaction ${status}`;\n\n const result: ExplainedTx = {\n digest: input.digest,\n sender,\n status,\n gasUsed: `${gasCost.toFixed(6)} SUI`,\n timestamp,\n effects: txEffects,\n summary,\n };\n\n return {\n data: result,\n displayText: `**Tx ${input.digest.slice(0, 8)}...** (${status})\\nSender: ${sender}\\nGas: ${result.gasUsed}\\n${summary}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport {\n fetchAddressPortfolio,\n fetchAddressDefiPortfolio,\n type AddressPortfolio,\n type DefiSummary,\n} from '../blockvision-prices.js';\nimport { fetchAudricPortfolio } from '../audric-api.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { ServerPositionData } from '../types.js';\n\nconst inputSchema = z.object({\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui) to analyze. Defaults to the signed-in wallet when omitted.'),\n});\n\ninterface AssetAllocation {\n symbol: string;\n amount: number;\n usdValue: number;\n percentage: number;\n}\n\ninterface PortfolioInsight {\n type: 'info' | 'warning' | 'suggestion';\n message: string;\n}\n\ninterface WeekChange {\n absoluteUsd: number;\n percentChange: number;\n}\n\ninterface PortfolioResult {\n totalValue: number;\n walletValue: number;\n savingsValue: number;\n /**\n * [Bug — 2026-04-28] Aggregated DeFi value across non-NAVI protocols\n * (Cetus LPs, Bluefin, Suilend, etc.) — same field that's been on\n * `balance_check` since v0.50. Pre-fix this tool ignored DeFi entirely:\n * a wallet with $1,569 in Cetus LPs reported a $228 totalValue\n * (wallet only), under-counting net worth by 87% and prompting the LLM\n * to misclassify the wallet as \"concentrated in FAITH\" when actually\n * the bulk was in liquidity pools. Same SSOT-divergence class the v0.54\n * cache work fixed for FullPortfolioCanvas, manifesting in a different\n * tool that was written before DeFi support was bolted on.\n */\n defiValue: number;\n /** Provenance of the DeFi read — used by the UI card to caveat partial/degraded. */\n defiSource: DefiSummary['source'];\n debtValue: number;\n healthFactor: number | null;\n allocations: AssetAllocation[];\n stablePercentage: number;\n insights: PortfolioInsight[];\n savingsApy?: number;\n dailyEarning?: number;\n weekChange?: WeekChange;\n priceSource: AddressPortfolio['source'];\n /** Resolved on-chain address (post SuiNS normalization). */\n address?: string;\n /** True when the resolved address matches the signed-in wallet. */\n isSelfQuery?: boolean;\n /**\n * Original SuiNS name when the user passed `address: \"alex.sui\"`,\n * otherwise null. Host cards use this to title the result with the\n * human-readable name instead of the truncated 0x address.\n */\n suinsName?: string | null;\n}\n\nconst STABLECOINS = new Set(['USDC', 'USDT', 'USDe', 'USDsui']);\n\nexport const portfolioAnalysisTool = buildTool({\n name: 'portfolio_analysis',\n description:\n 'Analyze portfolio allocation, risk exposure, and yield optimization for the signed-in user OR any public Sui address or SuiNS name. Shows asset breakdown, diversification score, health factor assessment, and actionable suggestions. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to analyze a contact / watched / public wallet.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n required: [],\n },\n isReadOnly: true,\n async call(input, context) {\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let address: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n address = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n address = context.walletAddress;\n }\n if (!address) {\n throw new Error('No wallet address provided. Sign in first.');\n }\n\n const DUST_USD = 0.01;\n\n // [single-source-of-truth — Apr 2026] Try audric's canonical\n // `/api/portfolio` first. When it returns a snapshot we already have\n // wallet + positions in one call so we skip the parallel BV +\n // positionFetcher fan-out below.\n const audricSnapshot = await fetchAudricPortfolio(\n address,\n context.env,\n context.signal,\n );\n\n // [v1.4 BlockVision] Fan out parallel fetches: BlockVision portfolio\n // (coins + balances + USD prices in one shot), positions (host\n // fetcher), 7-day portfolio history, AND non-NAVI DeFi positions\n // (Cetus/Bluefin/Suilend/etc.). Total wall time is bound by the\n // slowest. Re-uses the per-request portfolio cache so a sibling\n // `balance_check` in the same turn shares the response.\n //\n // [Bug — 2026-04-28] DeFi is now a first-class fetch: the audric\n // snapshot path uses the value the audric host already computed\n // (single source of truth), the standalone path falls back to a\n // direct fetchAddressDefiPortfolio call. This closes the gap where\n // portfolio_analysis ignored the $1,569 in Cetus LPs that\n // balance_check reported correctly.\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n const [portfolio, positions, weekHistResult, defiSummary]: [\n AddressPortfolio,\n ServerPositionData | null,\n { change?: WeekChange } | null,\n DefiSummary,\n ] = await Promise.all([\n audricSnapshot\n ? Promise.resolve(audricSnapshot.portfolio)\n : (async () => {\n if (context.portfolioCache) {\n const hit = context.portfolioCache.get(address);\n if (hit) return hit;\n }\n const fresh = await fetchAddressPortfolio(\n address,\n context.blockvisionApiKey,\n context.suiRpcUrl,\n { retryStats: context.retryStats },\n );\n context.portfolioCache?.set(address, fresh);\n return fresh;\n })().catch((err): AddressPortfolio => {\n console.warn('[portfolio_analysis] portfolio fetch failed:', err);\n return {\n coins: [],\n totalUsd: 0,\n pricedAt: Date.now(),\n source: 'sui-rpc-degraded',\n };\n }),\n audricSnapshot\n ? Promise.resolve(audricSnapshot.positions)\n : context.positionFetcher\n ? context.positionFetcher(address).catch((err) => {\n console.warn('[portfolio_analysis] positionFetcher failed:', err);\n return null;\n })\n : Promise.resolve(null),\n apiUrl\n ? fetch(\n `${apiUrl}/api/analytics/portfolio-history?days=7`,\n { headers: { 'x-sui-address': address }, signal: context.signal },\n )\n .then((res) => (res.ok ? res.json() as Promise<{ change?: WeekChange }> : null))\n .catch(() => null)\n : Promise.resolve(null),\n // DeFi fetch — prefer the audric snapshot's already-computed\n // value, but only when we can trust it. Two trust signals:\n // 1. `source === 'blockvision'` — fully successful fresh read\n // (even if value is 0, that's a confirmed empty position).\n // 2. `defiValueUsd > 0` — any positive value, regardless\n // of source. `partial-stale` with a positive total is fine,\n // `partial` with a positive total is the live equivalent.\n //\n // [Bug — 2026-04-28 round 2] Pre-fix the trust gate was\n // `defiSource !== 'degraded'`, which let `partial + 0` through\n // as authoritative. During a BlockVision 429 burst the audric\n // host's `/api/portfolio` returns `partial + 0` (some protocols\n // failed, the rest reported $0, no sticky-positive available\n // *in that process*) — but the engine's direct fetcher in the\n // chat route may have a sticky-positive in *this* Vercel\n // instance's cache. Trusting audric's $0 silently dropped the\n // DeFi line that `balance_check` (which always calls direct)\n // showed correctly on the same turn — same SSOT-divergence bug\n // class, manifested in a different layer.\n //\n // The new condition routes around audric's $0 in exactly that\n // case. When the direct fetch ALSO returns $0 the answer is\n // consistent across tools (both report degraded), which is the\n // honest UX during a real outage.\n (audricSnapshot &&\n (audricSnapshot.defiSource === 'blockvision' ||\n audricSnapshot.defiValueUsd > 0))\n ? Promise.resolve<DefiSummary>({\n totalUsd: audricSnapshot.defiValueUsd,\n perProtocol: {},\n pricedAt: Date.now(),\n source: audricSnapshot.defiSource,\n })\n : fetchAddressDefiPortfolio(address, context.blockvisionApiKey, {}, { retryStats: context.retryStats }).catch(\n (err): DefiSummary => {\n console.warn('[portfolio_analysis] defi fetch failed:', err);\n return { totalUsd: 0, perProtocol: {}, pricedAt: Date.now(), source: 'degraded' };\n },\n ),\n ]);\n\n let walletValue = 0;\n const allAllocations: AssetAllocation[] = [];\n\n for (const coin of portfolio.coins) {\n const amount = Number(coin.balance) / 10 ** coin.decimals;\n if (!Number.isFinite(amount) || amount <= 0) continue;\n const usdValue = coin.usdValue ?? (coin.price != null ? amount * coin.price : 0);\n walletValue += usdValue;\n allAllocations.push({ symbol: coin.symbol, amount, usdValue, percentage: 0 });\n }\n\n const allocations = allAllocations.filter((a) => a.usdValue >= DUST_USD);\n\n let savingsValue = 0;\n let debtValue = 0;\n let healthFactor: number | null = null;\n let savingsApy: number | undefined;\n let dailyEarning: number | undefined;\n\n if (positions) {\n savingsValue = positions.savings ?? 0;\n debtValue = positions.borrows ?? 0;\n healthFactor = positions.healthFactor ?? null;\n if (typeof positions.savingsRate === 'number' && positions.savingsRate > 0) {\n savingsApy = positions.savingsRate;\n dailyEarning = savingsValue * savingsApy / 365;\n }\n }\n\n let weekChange: WeekChange | undefined;\n if (weekHistResult?.change && weekHistResult.change.absoluteUsd !== 0) {\n weekChange = weekHistResult.change;\n }\n\n // [Bug — 2026-04-28] DeFi must be in totalValue. Pre-fix:\n // totalValue = walletValue + savingsValue\n // → a wallet with $228 wallet + $1,569 in Cetus LPs reported $228\n // total, dropping 87% of the user's actual net worth.\n const defiValue = defiSummary.totalUsd;\n\n // [Bug — 2026-04-28] Synthesize per-protocol DeFi entries as\n // allocations so the pie/MiniBar reflects the true breakdown. Each\n // protocol becomes one row labelled with a `<protocol> DeFi` symbol\n // (e.g. `Cetus DeFi`, `Bluefin DeFi`). `amount: 0` because there's\n // no single underlying token — these positions are LP-pair / staked\n // composites whose unit isn't meaningful at the analysis level.\n // Skipped when defiSource is 'degraded' (per-protocol map is empty).\n if (defiSummary.source !== 'degraded') {\n for (const [protocol, usdValue] of Object.entries(defiSummary.perProtocol)) {\n if (typeof usdValue === 'number' && usdValue >= DUST_USD) {\n // Title-case the protocol name for display: 'cetus' → 'Cetus DeFi'.\n const label = protocol.charAt(0).toUpperCase() + protocol.slice(1) + ' DeFi';\n allocations.push({ symbol: label, amount: 0, usdValue, percentage: 0 });\n }\n }\n } else if (defiValue > 0) {\n // Sticky-positive cache may give us a totalUsd without a protocol\n // breakdown — surface a single aggregate row so the pie still\n // includes DeFi mass even if we can't break it down.\n allocations.push({ symbol: 'DeFi (aggregate)', amount: 0, usdValue: defiValue, percentage: 0 });\n }\n\n const totalValue = walletValue + savingsValue + defiValue;\n\n for (const a of allocations) {\n a.percentage = totalValue > 0 ? (a.usdValue / totalValue) * 100 : 0;\n }\n allocations.sort((a, b) => b.usdValue - a.usdValue);\n\n const stableValue = allocations\n .filter((a) => STABLECOINS.has(a.symbol))\n .reduce((s, a) => s + a.usdValue, 0) + savingsValue;\n const stablePercentage = totalValue > 0 ? (stableValue / totalValue) * 100 : 0;\n\n const insights: PortfolioInsight[] = [];\n\n if (healthFactor !== null && healthFactor < 1.5) {\n insights.push({\n type: 'warning',\n message: `Health factor ${healthFactor.toFixed(2)} is dangerously low. Consider repaying debt or adding collateral.`,\n });\n } else if (healthFactor !== null && healthFactor < 2.5) {\n insights.push({\n type: 'warning',\n message: `Health factor ${healthFactor.toFixed(2)} is moderate. Monitor your positions.`,\n });\n }\n\n if (stablePercentage > 80) {\n insights.push({\n type: 'suggestion',\n message: `${stablePercentage.toFixed(0)}% stablecoins. Consider diversifying into yield-bearing positions.`,\n });\n }\n\n const idleCash = allocations.find((a) => a.symbol === 'USDC');\n if (idleCash && idleCash.usdValue > 10) {\n insights.push({\n type: 'suggestion',\n message: `$${idleCash.usdValue.toFixed(2)} USDC idle in wallet. Deposit into NAVI savings for ~4-5% APY.`,\n });\n }\n\n if (allocations.length === 1) {\n insights.push({\n type: 'info',\n message: 'Portfolio is concentrated in a single asset.',\n });\n }\n\n // [Bug — 2026-04-28] Caveat insight when DeFi was unreachable so the\n // LLM doesn't narrate the partial total as if it were complete.\n if (defiSummary.source === 'degraded') {\n insights.push({\n type: 'warning',\n message: 'DeFi positions could not be loaded — total may under-count any Cetus/Bluefin/Suilend value.',\n });\n } else if (defiSummary.source === 'partial') {\n insights.push({\n type: 'warning',\n message: 'DeFi data is partial — at least one protocol failed; total may under-count.',\n });\n }\n\n const result: PortfolioResult = {\n totalValue,\n walletValue,\n savingsValue,\n defiValue,\n defiSource: defiSummary.source,\n debtValue,\n healthFactor,\n allocations: allocations.slice(0, 10),\n stablePercentage,\n insights,\n savingsApy,\n dailyEarning,\n weekChange,\n priceSource: portfolio.source,\n address,\n isSelfQuery:\n !!context.walletAddress &&\n address.toLowerCase() === context.walletAddress.toLowerCase(),\n suinsName,\n };\n\n const defiSegment = defiValue > 0\n ? ` | DeFi: $${defiValue.toFixed(2)}${defiSummary.source === 'partial' ? ' (partial)' : ''}`\n : '';\n const topLine = `Total: $${totalValue.toFixed(2)} | Wallet: $${walletValue.toFixed(2)} | Savings: $${savingsValue.toFixed(2)}${defiSegment}`;\n const insightLines = insights.map((i) => `${i.type === 'warning' ? '⚠' : '→'} ${i.message}`).join('\\n');\n\n return {\n data: result,\n displayText: `${topLine}\\n${insightLines}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst LLAMA_API = 'https://api.llama.fi';\n\nconst SLUG_ALIASES: Record<string, string> = {\n 'navi': 'navi-lending',\n 'navi-protocol': 'navi-lending',\n 'scallop': 'scallop-lend',\n};\n\nconst inputSchema = z.object({\n protocol: z.string().describe('Protocol slug (e.g. \"navi-lending\", \"cetus\", \"scallop-lend\")'),\n});\n\ninterface ProtocolProfile {\n name: string;\n slug: string;\n category: string;\n chains: string[];\n tvl: number;\n tvlChange1d: number;\n tvlChange7d: number;\n tvlChange30d: number;\n mcap: number | null;\n fees24h: number | null;\n revenue24h: number | null;\n auditCount: number;\n auditLinks: string[];\n url: string;\n twitter: string | null;\n riskFactors: string[];\n safetyScore: string;\n}\n\nfunction extractCurrentTvl(proto: Record<string, unknown>): number {\n const chainTvls = proto.currentChainTvls;\n if (chainTvls && typeof chainTvls === 'object') {\n return Object.values(chainTvls as Record<string, number>)\n .filter((v) => typeof v === 'number' && v > 0)\n .reduce((sum, v) => sum + v, 0);\n }\n if (Array.isArray(proto.tvl) && proto.tvl.length > 0) {\n const last = proto.tvl[proto.tvl.length - 1] as { totalLiquidityUSD?: number };\n return last.totalLiquidityUSD ?? 0;\n }\n if (typeof proto.tvl === 'number') return proto.tvl;\n return 0;\n}\n\nfunction fmtTvl(tvl: number): string {\n if (tvl >= 1e9) return `$${(tvl / 1e9).toFixed(2)}B`;\n if (tvl >= 1e6) return `$${(tvl / 1e6).toFixed(1)}M`;\n if (tvl >= 1e3) return `$${(tvl / 1e3).toFixed(0)}K`;\n return `$${tvl.toFixed(0)}`;\n}\n\nexport const protocolDeepDiveTool = buildTool({\n name: 'protocol_deep_dive',\n description:\n 'Get a comprehensive safety and financial profile of a DeFi protocol. Includes TVL trends, revenue, audit status, and risk assessment. Use when users ask \"is X safe?\" or \"tell me about protocol Y\".',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n protocol: { type: 'string', description: 'Protocol slug (e.g. \"navi-lending\", \"cetus\")' },\n },\n required: ['protocol'],\n },\n isReadOnly: true,\n async call(input) {\n let slug = input.protocol.toLowerCase().replace(/\\s+/g, '-');\n slug = SLUG_ALIASES[slug] ?? slug;\n\n const [protocolRes, feesRes] = await Promise.allSettled([\n fetch(`${LLAMA_API}/protocol/${slug}`, { signal: AbortSignal.timeout(10_000) }).then((r) => {\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.json();\n }),\n fetch(`${LLAMA_API}/summary/fees/${slug}?dataType=dailyFees`, { signal: AbortSignal.timeout(8_000) }).then((r) => {\n if (!r.ok) return null;\n return r.json();\n }),\n ]);\n\n if (protocolRes.status === 'rejected') {\n throw new Error(`Protocol \"${slug}\" not found on DefiLlama.`);\n }\n\n const proto = protocolRes.value as Record<string, unknown>;\n\n const tvl = extractCurrentTvl(proto);\n const tvlChange1d = Number(proto.change_1d ?? 0);\n const tvlChange7d = Number(proto.change_7d ?? 0);\n const tvlChange30d = Number(proto.change_1m ?? 0);\n const chains = Array.isArray(proto.chains) ? (proto.chains as string[]) : [];\n const category = (proto.category ?? 'Unknown') as string;\n\n const auditCount = Number(proto.audits) || 0;\n const auditLinks = Array.isArray(proto.audit_links) ? (proto.audit_links as string[]) : [];\n const hasAudits = auditCount > 0 || auditLinks.length > 0;\n\n let fees24h: number | null = null;\n let revenue24h: number | null = null;\n if (feesRes.status === 'fulfilled' && feesRes.value) {\n const feesData = feesRes.value as Record<string, unknown>;\n fees24h = feesData.total24h != null ? Number(feesData.total24h) : null;\n revenue24h = feesData.totalRevenue24h != null ? Number(feesData.totalRevenue24h) : null;\n }\n\n const riskFactors: string[] = [];\n\n if (tvl < 1_000_000) riskFactors.push('TVL under $1M — low liquidity risk');\n else if (tvl < 10_000_000) riskFactors.push('TVL under $10M — moderate liquidity');\n if (tvlChange7d < -15) riskFactors.push(`TVL dropped ${tvlChange7d.toFixed(1)}% in 7 days`);\n if (chains.length === 1) riskFactors.push('Single-chain deployment');\n if (!hasAudits) riskFactors.push('No published audits found');\n else riskFactors.push(`${auditCount || auditLinks.length} audit(s) on file`);\n\n let safetyScore: string;\n if (tvl > 100_000_000 && hasAudits && tvlChange7d > -10) {\n safetyScore = 'High — established protocol with audits and significant TVL';\n } else if (tvl > 10_000_000 && tvlChange7d > -20) {\n safetyScore = 'Moderate — decent TVL, use with caution';\n } else {\n safetyScore = 'Low — small or declining TVL, proceed carefully';\n }\n\n const result: ProtocolProfile = {\n name: (proto.name ?? slug) as string,\n slug,\n category,\n chains,\n tvl,\n tvlChange1d,\n tvlChange7d,\n tvlChange30d,\n mcap: proto.mcap ? Number(proto.mcap) : null,\n fees24h,\n revenue24h,\n auditCount,\n auditLinks,\n url: (proto.url ?? '') as string,\n twitter: (proto.twitter ?? null) as string | null,\n riskFactors,\n safetyScore,\n };\n\n const feesStr = fees24h != null ? ` | Fees 24h: $${fees24h.toLocaleString()}` : '';\n\n return {\n data: result,\n displayText: `**${result.name}** (${category})\\nTVL: ${fmtTvl(tvl)} (7d: ${tvlChange7d > 0 ? '+' : ''}${tvlChange7d.toFixed(1)}%)${feesStr}\\nChains: ${chains.join(', ')}\\nSafety: ${safetyScore}\\nRisks: ${riskFactors.join('; ')}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\nconst PaymentLinkSchema = z.object({\n amount: z.number().positive().describe('Amount in USDC (required). Ask the user if not specified.'),\n label: z.string().optional().describe('Human-readable label e.g. \"Consulting fee March\"'),\n memo: z.string().optional().describe('Optional note shown to the payer'),\n expiresInHours: z.number().positive().optional().describe('Hours until the link expires. Omit for permanent links.'),\n});\n\nconst InvoiceSchema = z.object({\n amount: z.number().positive().describe('Total invoice amount in USDC'),\n label: z.string().describe('Invoice title e.g. \"Web design — March 2026\"'),\n memo: z.string().optional().describe('Optional note or payment terms'),\n recipientName: z.string().optional().describe('Name of the person or company being invoiced'),\n recipientEmail: z.string().optional().describe('Email address of the recipient'),\n dueDays: z.number().int().positive().optional().describe('Days until payment is due. Omit for no due date.'),\n items: z.array(z.object({\n description: z.string(),\n amount: z.number().positive(),\n })).optional().describe('Line items. If omitted, a single line item matching the total is implied.'),\n});\n\nfunction internalHeaders(context: { walletAddress?: string; env?: Record<string, string | undefined>; signal?: AbortSignal }) {\n const internalKey = context.env?.AUDRIC_INTERNAL_KEY;\n return {\n 'Content-Type': 'application/json',\n 'x-sui-address': context.walletAddress ?? '',\n ...(internalKey ? { 'x-internal-key': internalKey } : {}),\n };\n}\n\nexport const createPaymentLinkTool = buildTool({\n name: 'create_payment_link',\n description:\n 'Create a shareable payment link so someone can send USDC to the user. Amount is required — ask the user for the amount if not specified. Returns a URL the user can share. Payers can connect their wallet, scan a QR code, or send manually. Use when the user says \"create a payment link\", \"generate a payment link\", \"I want to get paid\", or similar.',\n inputSchema: PaymentLinkSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { type: 'number', description: 'Amount in USDC (required). Ask the user if not specified.' },\n label: { type: 'string', description: 'Human-readable label e.g. \"Consulting fee March\"' },\n memo: { type: 'string', description: 'Optional note shown to the payer' },\n expiresInHours: { type: 'number', description: 'Hours until the link expires. Omit for permanent links.' },\n },\n required: ['amount'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Payment link creation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'POST',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ ...input, type: 'link' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to create payment link.' };\n }\n\n const link = await res.json() as {\n slug: string;\n nonce: string;\n url: string;\n amount: number;\n currency: string;\n label: string | null;\n memo: string | null;\n expiresAt: string | null;\n };\n\n const amountStr = `$${link.amount.toFixed(2)} ${link.currency}`;\n return {\n data: link,\n displayText: `Payment link created for ${amountStr}${link.label ? ` — ${link.label}` : ''}. Payers can connect their wallet, scan the QR code, or send manually. Share: ${link.url}`,\n };\n } catch {\n return { data: null, displayText: 'Failed to create payment link.' };\n }\n },\n});\n\nexport const listPaymentLinksTool = buildTool({\n name: 'list_payment_links',\n description:\n 'List the user\\'s payment links — active, paid, expired, and cancelled. Use when the user asks \"show my payment links\", \"what payment links do I have\", or wants to check payment status.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: true,\n\n async call(_input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: { links: [] }, displayText: 'No payment links found.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments?type=link`, {\n signal: context.signal,\n headers: internalHeaders(context),\n });\n\n if (!res.ok) return { data: { links: [] }, displayText: 'Could not fetch payment links.' };\n\n const raw = await res.json() as { payments: unknown[] };\n const links = raw.payments;\n const count = links.length;\n return {\n data: { links },\n displayText: count === 0 ? 'No payment links yet.' : `${count} payment link${count !== 1 ? 's' : ''} found.`,\n };\n } catch {\n return { data: { links: [] }, displayText: 'Could not fetch payment links.' };\n }\n },\n});\n\nexport const createInvoiceTool = buildTool({\n name: 'create_invoice',\n description:\n 'Create a formal invoice that the user can share with a client or customer. Returns a URL for the invoice page. Payers can connect their wallet, scan a QR code, or send manually. Use when the user says \"create an invoice\", \"generate an invoice\", \"bill a client\", or similar.',\n inputSchema: InvoiceSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n amount: { type: 'number', description: 'Total invoice amount in USDC' },\n label: { type: 'string', description: 'Invoice title e.g. \"Web design — March 2026\"' },\n memo: { type: 'string', description: 'Optional note or payment terms' },\n recipientName: { type: 'string', description: 'Name of the person or company being invoiced' },\n recipientEmail: { type: 'string', description: 'Email address of the recipient' },\n dueDays: { type: 'number', description: 'Days until payment is due. Omit for no due date.' },\n items: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n description: { type: 'string' },\n amount: { type: 'number' },\n },\n required: ['description', 'amount'],\n },\n description: 'Line items. If omitted, a single line item matching the total is implied.',\n },\n },\n required: ['amount', 'label'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Invoice creation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'POST',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ ...input, type: 'invoice' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to create invoice.' };\n }\n\n const invoice = await res.json() as {\n slug: string;\n nonce: string;\n url: string;\n amount: number;\n currency: string;\n label: string;\n memo: string | null;\n dueDate: string | null;\n };\n\n const dueStr = invoice.dueDate ? ` due ${new Date(invoice.dueDate).toLocaleDateString()}` : '';\n return {\n data: invoice,\n displayText: `Invoice created for $${invoice.amount.toFixed(2)} ${invoice.currency}${dueStr} — ${invoice.label}. Payers can connect their wallet, scan the QR code, or send manually. Share: ${invoice.url}`,\n };\n } catch {\n return { data: null, displayText: 'Failed to create invoice.' };\n }\n },\n});\n\nexport const cancelPaymentLinkTool = buildTool({\n name: 'cancel_payment_link',\n description:\n 'Cancel an active payment link so it can no longer be used. Use when the user says \"cancel my payment link\", \"delete my payment link\", or \"remove the link [slug/label]\". Ask for the slug if ambiguous — use list_payment_links first to find it.',\n inputSchema: z.object({\n slug: z.string().describe('The slug of the payment link to cancel (e.g. \"LzLawhY7\")'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n slug: { type: 'string', description: 'The slug of the payment link to cancel' },\n },\n required: ['slug'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Payment link cancellation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'PATCH',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ slug: input.slug, action: 'cancel' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to cancel payment link.' };\n }\n\n const result = await res.json() as { slug: string; status: string };\n return {\n data: result,\n displayText: `Payment link ${result.slug} cancelled.`,\n };\n } catch {\n return { data: null, displayText: 'Failed to cancel payment link.' };\n }\n },\n});\n\nexport const cancelInvoiceTool = buildTool({\n name: 'cancel_invoice',\n description:\n 'Cancel an invoice that has not yet been paid. Use when the user says \"cancel my invoice\", \"delete invoice\", or refers to a specific invoice slug or label. Use list_invoices first if the slug is not known.',\n inputSchema: z.object({\n slug: z.string().describe('The slug of the invoice to cancel (e.g. \"xFYKBWy5\")'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n slug: { type: 'string', description: 'The slug of the invoice to cancel' },\n },\n required: ['slug'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: null, displayText: 'Invoice cancellation is not available.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments`, {\n method: 'PATCH',\n signal: context.signal,\n headers: internalHeaders(context),\n body: JSON.stringify({ slug: input.slug, action: 'cancel' }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n return { data: null, displayText: err.error ?? 'Failed to cancel invoice.' };\n }\n\n const result = await res.json() as { slug: string; status: string };\n return {\n data: result,\n displayText: `Invoice ${result.slug} cancelled.`,\n };\n } catch {\n return { data: null, displayText: 'Failed to cancel invoice.' };\n }\n },\n});\n\nexport const listInvoicesTool = buildTool({\n name: 'list_invoices',\n description:\n 'List the user\\'s invoices — pending, overdue, paid, and cancelled. Use when the user asks \"show my invoices\", \"what invoices do I have\", or wants to check invoice status.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: true,\n\n async call(_input, context) {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n if (!apiUrl || !context.walletAddress) {\n return { data: { invoices: [] }, displayText: 'No invoices found.' };\n }\n\n try {\n const res = await fetch(`${apiUrl}/api/internal/payments?type=invoice`, {\n signal: context.signal,\n headers: internalHeaders(context),\n });\n\n if (!res.ok) return { data: { invoices: [] }, displayText: 'Could not fetch invoices.' };\n\n const raw = await res.json() as { payments: unknown[] };\n const invoices = raw.payments;\n const count = invoices.length;\n return {\n data: { invoices },\n displayText: count === 0 ? 'No invoices yet.' : `${count} invoice${count !== 1 ? 's' : ''} found.`,\n };\n } catch {\n return { data: { invoices: [] }, displayText: 'Could not fetch invoices.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { ToolResult } from '../types.js';\n\n// ---------------------------------------------------------------------------\n// Template catalogue\n// ---------------------------------------------------------------------------\n\nexport const CANVAS_TEMPLATES = [\n 'activity_heatmap',\n 'portfolio_timeline',\n 'yield_projector',\n 'health_simulator',\n 'dca_planner',\n 'spending_breakdown',\n 'watch_address',\n 'full_portfolio',\n] as const;\n\nexport type CanvasTemplate = (typeof CANVAS_TEMPLATES)[number];\n\n/** Normalize savings rate: if < 1 treat as decimal → multiply by 100, else use as-is. Default 4.5%. */\nfunction normalizeSavingsRate(raw: number | undefined | null, fallback = 4.5): number {\n const r = raw ?? 0;\n if (r > 0 && r < 1) return r * 100;\n if (r > 0) return r;\n return fallback;\n}\n\nconst CANVAS_TITLES: Record<CanvasTemplate, string> = {\n activity_heatmap: 'On-Chain Activity',\n portfolio_timeline: 'Net Worth Over Time',\n yield_projector: 'Yield Projector',\n health_simulator: 'Health Factor Simulator',\n dca_planner: 'Savings Plan',\n spending_breakdown: 'Spending Breakdown',\n watch_address: 'Watch Address',\n full_portfolio: 'Full Portfolio Overview',\n};\n\n// ---------------------------------------------------------------------------\n// render_canvas tool\n// ---------------------------------------------------------------------------\n\nexport const renderCanvasTool = buildTool({\n name: 'render_canvas',\n description: `Renders an interactive financial canvas inline in the chat.\n\nUse when the user asks for a visual chart, simulator, or financial overview. Pick the most relevant template:\n\n- activity_heatmap — on-chain transaction history as a GitHub-style heatmap (WORKS NOW — accepts \\`params.address\\` to inspect any public Sui wallet; defaults to the signed-in user)\n- portfolio_timeline — net worth over time, wallet/savings/debt breakdown (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user)\n- yield_projector — compound yield simulator with amount/APY/period sliders (WORKS NOW — client-side, no address needed)\n- health_simulator — borrow health factor simulator with collateral/debt sliders (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user's current position)\n- dca_planner — savings plan curve for regular monthly deposits (WORKS NOW — client-side, no address needed)\n- spending_breakdown — spending by service category (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user)\n- watch_address — portfolio overview for any public Sui address (WORKS NOW — pass \\`params.address\\`)\n- full_portfolio — 4-panel overview: savings, health, activity, spending (WORKS NOW — accepts \\`params.address\\` for any public wallet; defaults to the signed-in user)\n\nWhen the user asks to inspect a saved contact or watched address — e.g. \"show funkii's activity heatmap\", \"what's funkii's portfolio look like\", \"spending breakdown for 0x40cd…\", \"give me a full portfolio overview of 0x40cd…\" — pass that wallet's address as \\`params.address\\`. Six of the eight templates (activity_heatmap, portfolio_timeline, spending_breakdown, watch_address, health_simulator, full_portfolio) will scope their data fetch to that address; only the pure client-side simulators (yield_projector, dca_planner) ignore params.address.\n\nAlways prefer the canvas for visualisation requests. After rendering, offer to explain what the user sees.`,\n inputSchema: z.object({\n template: z.enum(CANVAS_TEMPLATES).describe('Which canvas template to render'),\n params: z\n .object({\n period: z.enum(['1m', '3m', '6m', '1y']).optional().describe('Time period for time-based templates'),\n address: z\n .string()\n .optional()\n .describe(\n 'Sui address for the six address-aware templates (activity_heatmap, portfolio_timeline, spending_breakdown, watch_address, health_simulator, full_portfolio). Defaults to the signed-in user; pass an explicit address to inspect a contact, watched wallet, or any other public address.',\n ),\n })\n .optional(),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n template: {\n type: 'string',\n enum: CANVAS_TEMPLATES,\n description: 'Which canvas template to render',\n },\n params: {\n type: 'object',\n properties: {\n period: { type: 'string', enum: ['1m', '3m', '6m', '1y'] },\n address: { type: 'string' },\n },\n },\n },\n required: ['template'],\n },\n isReadOnly: true,\n\n async call(input, context): Promise<ToolResult<unknown>> {\n const { template, params } = input;\n const title = CANVAS_TITLES[template];\n\n /**\n * [v1.2 SuiNS] Pre-resolve `params.address` once at the top of\n * `call()` (instead of inside the per-template branches) so that\n * SuiNS names like \\`alex.sui\\` work for every address-aware\n * template without each branch having to thread normalization\n * through. Templates already index the resolved 0x for any\n * downstream API call; the original SuiNS name is preserved in\n * `suinsName` so the canvas can title itself with the human-readable\n * name (e.g. \"Activity for alex.sui\").\n *\n * SCOPE. Only normalize for the six address-aware templates. The\n * pure simulators (`yield_projector`, `dca_planner`) ignore\n * `params.address` entirely — running the normalizer for them would\n * regress to \"transient SuiNS RPC failure crashes a yield-projector\n * canvas the user didn't even ask to be address-scoped\".\n */\n const ADDRESS_AWARE_TEMPLATES = new Set<CanvasTemplate>([\n 'full_portfolio',\n 'watch_address',\n 'portfolio_timeline',\n 'spending_breakdown',\n 'activity_heatmap',\n 'health_simulator',\n ]);\n let suinsName: string | null = null;\n let resolvedParamAddress: string | null = null;\n if (params?.address && ADDRESS_AWARE_TEMPLATES.has(template)) {\n const normalized = await normalizeAddressInput(params.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n resolvedParamAddress = normalized.address;\n suinsName = normalized.suinsName;\n }\n\n /**\n * [v0.48] Address resolution for the four address-aware templates\n * (activity_heatmap, portfolio_timeline, spending_breakdown,\n * watch_address). Pre-v0.48 only `watch_address` consulted\n * `params.address`; the other three hardcoded `context.walletAddress`\n * which silently masked the watched-address case (the LLM passed\n * the right param, the canvas rendered the user's own data).\n *\n * Falls back to `context.walletAddress` when `params.address` is\n * absent. Returns `null` when neither is present so callers can\n * surface a \"needs an address\" error state.\n *\n * `isSelfRender` lets the result advertise whether the canvas\n * targets the signed-in user — the frontend ActivityHeatmapCanvas\n * uses it so cell clicks produce contextually correct chat prompts\n * (\"Show transactions for 0x40cd…\" vs \"Show my transactions\n * from…\"). Without this flag, a heatmap cell click on a watched\n * address routes back into the user's own transaction history.\n */\n const resolveAddressTarget = (): { address: string | null; isSelfRender: boolean; suinsName: string | null } => {\n const fromParams = resolvedParamAddress;\n const fromContext = context.walletAddress;\n const target = fromParams ?? fromContext ?? null;\n const isSelfRender = !!target && !!fromContext && target.toLowerCase() === fromContext.toLowerCase();\n return { address: target, isSelfRender, suinsName };\n };\n\n /**\n * [v1.2 SuiNS] Prefer the human-readable SuiNS name in titles +\n * narration when present; fall back to the truncated 0x address.\n * Used by every address-aware template's titleSuffix + displayText.\n */\n const formatAddrLabel = (address: string, suins: string | null): string =>\n suins ?? `${address.slice(0, 6)}…${address.slice(-4)}`;\n\n // Full portfolio — 4-panel capstone with live position data\n if (template === 'full_portfolio') {\n /**\n * [v0.49] When `params.address` is present and points to a wallet\n * other than the signed-in user, do NOT seed templateData with\n * `context.serverPositions` (those are the user's own positions\n * and would be misleading for a watched-address overview). The\n * frontend re-fetches per-panel data via the address-aware API\n * routes (`/api/balances`, `/api/savings`, etc.), so we just hand\n * it the address + isSelfRender flag.\n */\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Full Portfolio needs an address.' },\n },\n displayText: 'Full Portfolio requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n const pos = isSelfRender ? context.serverPositions : null;\n const rate = normalizeSavingsRate(pos?.savingsRate);\n const savings = pos?.savings ?? 0;\n const borrows = pos?.borrows ?? 0;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n currentSavings: savings,\n currentDebt: borrows,\n healthFactor: pos?.healthFactor ?? null,\n savingsRate: rate,\n },\n },\n displayText: isSelfRender\n ? `Opened Full Portfolio Overview.`\n : `Opened Full Portfolio Overview for ${addrLabel}.`,\n };\n }\n\n // Watch address — show balances for any public Sui address (or SuiNS name).\n if (template === 'watch_address') {\n // [v1.2 SuiNS] resolvedParamAddress comes from the top-of-call\n // normalization, so a SuiNS name like \"alex.sui\" resolves here.\n const targetAddress = resolvedParamAddress ?? '';\n if (!targetAddress) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Please provide a valid Sui address or SuiNS name to watch.' },\n },\n displayText: 'No valid address provided. Ask the user for a Sui address or SuiNS name.',\n };\n }\n const addrLabel = formatAddrLabel(targetAddress, suinsName);\n return {\n data: {\n __canvas: true,\n template,\n title: `Watch ${addrLabel}`,\n templateData: { available: true, address: targetAddress, suinsName },\n },\n displayText: `Opened Watch Address canvas for ${addrLabel}.`,\n };\n }\n\n // Portfolio timeline — fetches from /api/analytics/portfolio-history\n if (template === 'portfolio_timeline') {\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Portfolio Timeline needs an address.' },\n },\n displayText: 'Portfolio Timeline requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n },\n },\n displayText: isSelfRender\n ? `Opened Portfolio Timeline. Shows your net worth, savings, and debt over time.`\n : `Opened Portfolio Timeline for ${addrLabel}.`,\n };\n }\n\n // Spending breakdown — fetches from /api/analytics/spending\n if (template === 'spending_breakdown') {\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Spending Breakdown needs an address.' },\n },\n displayText: 'Spending Breakdown requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n },\n },\n displayText: isSelfRender\n ? `Opened Spending Breakdown. Shows your service spending by category.`\n : `Opened Spending Breakdown for ${addrLabel}.`,\n };\n }\n\n // Activity heatmap — client-side fetches from /api/analytics/activity-heatmap\n if (template === 'activity_heatmap') {\n const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n if (!address) {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Activity Heatmap needs an address.' },\n },\n displayText: 'Activity Heatmap requires an address.',\n };\n }\n const addrLabel = formatAddrLabel(address, resolvedSuins);\n const titleSuffix = isSelfRender ? '' : ` — ${addrLabel}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address,\n isSelfRender,\n suinsName: resolvedSuins,\n },\n },\n displayText: isSelfRender\n ? `Opened Activity Heatmap for your wallet. Click any day to explore transactions.`\n : `Opened Activity Heatmap for ${addrLabel}. Click any day to explore that address's transactions.`,\n };\n }\n\n // Strategy simulators — client-side, seed with live position data\n const positions = context.serverPositions;\n const savingsRate = normalizeSavingsRate(positions?.savingsRate);\n const healthFactor = positions?.healthFactor ?? null;\n const totalSavings = positions?.savings ?? 0;\n const totalBorrows = positions?.borrows ?? 0;\n\n if (template === 'yield_projector') {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: {\n available: true,\n initialAmount: totalSavings > 0 ? Math.round(totalSavings) : 1000,\n initialApy: savingsRate,\n },\n },\n displayText: `Opened Yield Projector. Current USDC deposit rate: ${savingsRate.toFixed(2)}% APY.`,\n };\n }\n\n if (template === 'health_simulator') {\n /**\n * [v0.49] When the user passes `params.address` for a watched\n * wallet, seed the simulator with neutral defaults instead of the\n * signed-in user's own position. The frontend re-fetches per\n * `address` via `/api/health` to populate the live HF readout,\n * so seeding here is just for the slider initial state.\n */\n const { address: targetAddress, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();\n const seedFromPos = isSelfRender;\n const seedSavings = seedFromPos ? totalSavings : 0;\n const seedBorrows = seedFromPos ? totalBorrows : 0;\n const seedHf = seedFromPos ? healthFactor : null;\n const roundedDebt = seedBorrows >= 1\n ? Math.round(seedBorrows)\n : (seedBorrows > 0 ? parseFloat(seedBorrows.toFixed(4)) : 0);\n const titleSuffix = !targetAddress || isSelfRender\n ? ''\n : ` — ${formatAddrLabel(targetAddress, resolvedSuins)}`;\n return {\n data: {\n __canvas: true,\n template,\n title: `${title}${titleSuffix}`,\n templateData: {\n available: true,\n address: targetAddress ?? '',\n isSelfRender,\n suinsName: resolvedSuins,\n initialCollateral: seedSavings > 0 ? Math.round(seedSavings) : 1500,\n initialDebt: roundedDebt > 0 ? roundedDebt : (seedSavings > 0 ? 0 : 500),\n currentHf: seedHf,\n },\n },\n displayText: isSelfRender\n ? `Opened Health Factor Simulator. Current HF: ${healthFactor !== null ? healthFactor.toFixed(2) : 'no active position'}.`\n : `Opened Health Factor Simulator${titleSuffix}. The simulator will fetch the current health factor for that wallet.`,\n };\n }\n\n if (template === 'dca_planner') {\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: {\n available: true,\n initialMonthly: 200,\n initialApy: savingsRate,\n },\n },\n displayText: `Opened Savings Plan. Current USDC deposit rate: ${savingsRate.toFixed(2)}% APY.`,\n };\n }\n\n // Fallback — should not reach here given exhaustive template enum\n return {\n data: {\n __canvas: true,\n template,\n title,\n templateData: { available: false, message: 'Unknown template.' },\n },\n displayText: `Canvas template \"${template}\" is not yet available.`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport type { ToolResult } from '../types.js';\n\ninterface SpendingResponse {\n period: string;\n totalSpent: number;\n requestCount: number;\n serviceCount: number;\n byService: unknown[];\n}\n\nexport const spendingAnalyticsTool = buildTool({\n name: 'spending_analytics',\n description:\n 'Returns MPP service spending breakdown for a period. Shows total spent, request count, and breakdown by service/category. Use when the user asks about their API spending, service usage, or costs.',\n inputSchema: z.object({\n period: z\n .enum(['week', 'month', 'year', 'all'])\n .optional()\n .describe('Time period. Defaults to current month.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n period: { type: 'string', enum: ['week', 'month', 'year', 'all'] },\n },\n },\n isReadOnly: true,\n\n async call(input, context): Promise<ToolResult<SpendingResponse>> {\n const period = input.period ?? 'month';\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n const address = context.walletAddress;\n const empty: SpendingResponse = { period, totalSpent: 0, requestCount: 0, serviceCount: 0, byService: [] };\n\n if (!apiUrl || !address) {\n return { data: empty, displayText: 'Spending analytics not available.' };\n }\n\n try {\n const res = await fetch(\n `${apiUrl}/api/analytics/spending?address=${address}&period=${period}`,\n {\n headers: { 'x-sui-address': address },\n signal: context.signal,\n },\n );\n\n if (!res.ok) {\n return { data: empty, displayText: `Could not fetch spending data (HTTP ${res.status}).` };\n }\n\n const data = (await res.json()) as SpendingResponse;\n const total = data.totalSpent ?? 0;\n const count = data.requestCount ?? 0;\n\n return {\n data,\n displayText: total > 0\n ? `You spent $${total.toFixed(2)} across ${count} request${count !== 1 ? 's' : ''} on ${data.serviceCount} service${data.serviceCount !== 1 ? 's' : ''} (${data.period}).`\n : `No service spending recorded for ${data.period}.`,\n };\n } catch {\n return { data: empty, displayText: 'Error fetching spending analytics.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport type { ToolResult } from '../types.js';\n\ninterface YieldSummary {\n today: number;\n thisWeek: number;\n thisMonth: number;\n allTime: number;\n currentApy: number;\n deposited: number;\n projectedYear: number;\n sparkline: number[];\n}\n\nexport const yieldSummaryTool = buildTool({\n name: 'yield_summary',\n description:\n 'Returns yield earnings breakdown: today, this week, this month, all-time, current APY, deposited amount, projected yearly earnings, and a monthly sparkline. Use when the user asks about yield, earnings, or how much they have earned.',\n inputSchema: z.object({}),\n jsonSchema: { type: 'object', properties: {}, required: [] },\n isReadOnly: true,\n\n async call(_input, context): Promise<ToolResult<YieldSummary>> {\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n const address = context.walletAddress;\n\n const empty: YieldSummary = {\n today: 0, thisWeek: 0, thisMonth: 0, allTime: 0,\n currentApy: 0, deposited: 0, projectedYear: 0, sparkline: [],\n };\n\n if (!apiUrl || !address) {\n return { data: empty, displayText: 'Yield summary not available.' };\n }\n\n try {\n const res = await fetch(\n `${apiUrl}/api/analytics/yield-summary?address=${address}`,\n { headers: { 'x-sui-address': address }, signal: context.signal },\n );\n\n if (!res.ok) {\n return { data: empty, displayText: `Could not fetch yield data (HTTP ${res.status}).` };\n }\n\n const data = (await res.json()) as YieldSummary;\n const apy = data.currentApy ?? 0;\n const apyPct = apy < 1 ? (apy * 100).toFixed(2) : apy.toFixed(2);\n\n return {\n data,\n displayText: data.allTime > 0\n ? `You've earned $${data.allTime.toFixed(2)} all-time ($${data.today.toFixed(4)} today). Current APY: ${apyPct}%. Deposited: $${data.deposited.toFixed(2)}. Projected: $${data.projectedYear.toFixed(2)}/year.`\n : `No yield earnings yet. Deposit USDC to start earning ${apyPct}% APY.`,\n };\n } catch {\n return { data: empty, displayText: 'Error fetching yield summary.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { normalizeAddressInput } from '../sui-address.js';\nimport type { ToolResult } from '../types.js';\n\ninterface ActionBreakdown {\n action: string;\n count: number;\n totalAmountUsd: number;\n}\n\ninterface ActivitySummary {\n period: string;\n totalTransactions: number;\n byAction: ActionBreakdown[];\n totalMovedUsd: number;\n netSavingsUsd: number;\n yieldEarnedUsd: number;\n address?: string;\n isSelfQuery?: boolean;\n suinsName?: string | null;\n}\n\nexport const activitySummaryTool = buildTool({\n name: 'activity_summary',\n description:\n 'Returns a categorised DeFi activity summary for the signed-in user OR any public Sui address or SuiNS name: transaction count, breakdown by action type (saves, sends, borrows, repayments, swaps, payments), total moved, net savings change, and yield earned. Use when the user asks about activity, transaction history summary, or what someone has done recently. Pass `address` as a 0x address OR a SuiNS name (e.g. \"alex.sui\") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',\n inputSchema: z.object({\n period: z\n .enum(['week', 'month', 'year', 'all'])\n .optional()\n .describe('Time period. Defaults to current month.'),\n address: z\n .string()\n .optional()\n .describe('Sui address (0x…) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n period: { type: 'string', enum: ['week', 'month', 'year', 'all'] },\n address: {\n type: 'string',\n description: 'Sui address (0x…) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet.',\n },\n },\n },\n isReadOnly: true,\n\n async call(input, context): Promise<ToolResult<ActivitySummary>> {\n const period = input.period ?? 'month';\n const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;\n\n // [v1.2 SuiNS] Normalize the user-supplied address (0x or *.sui).\n let suinsName: string | null = null;\n let targetAddress: string | undefined;\n if (input.address) {\n const normalized = await normalizeAddressInput(input.address, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n targetAddress = normalized.address;\n suinsName = normalized.suinsName;\n } else {\n targetAddress = context.walletAddress;\n }\n const isSelfQuery =\n !!context.walletAddress &&\n !!targetAddress &&\n targetAddress.toLowerCase() === context.walletAddress.toLowerCase();\n\n const empty: ActivitySummary = {\n period, totalTransactions: 0, byAction: [],\n totalMovedUsd: 0, netSavingsUsd: 0, yieldEarnedUsd: 0,\n address: targetAddress, isSelfQuery, suinsName,\n };\n\n if (!apiUrl || !targetAddress) {\n return { data: empty, displayText: 'Activity summary not available.' };\n }\n\n try {\n const callerHeader = context.walletAddress ?? targetAddress;\n const res = await fetch(\n `${apiUrl}/api/analytics/activity-summary?address=${targetAddress}&period=${period}`,\n { headers: { 'x-sui-address': callerHeader }, signal: context.signal },\n );\n\n if (!res.ok) {\n return { data: empty, displayText: `Could not fetch activity data (HTTP ${res.status}).` };\n }\n\n const raw = (await res.json()) as ActivitySummary;\n const data: ActivitySummary = { ...raw, address: targetAddress, isSelfQuery, suinsName };\n const sorted = [...(data.byAction ?? [])].sort((a, b) => b.count - a.count);\n const top = sorted\n .slice(0, 3)\n .map((a) => `${a.action} (${a.count})`)\n .join(', ');\n\n const periodLabel = data.period === 'all' ? 'all time' : `this ${data.period}`;\n const subjectLabel = suinsName ?? `${targetAddress.slice(0, 6)}…${targetAddress.slice(-4)}`;\n const subjectPrefix = isSelfQuery ? '' : `${subjectLabel} — `;\n\n return {\n data,\n displayText: data.totalTransactions > 0\n ? `${subjectPrefix}${data.totalTransactions} transactions ${periodLabel}. Top: ${top}. Total moved: $${data.totalMovedUsd.toFixed(2)}. Net savings: $${data.netSavingsUsd.toFixed(2)}.`\n : `${subjectPrefix}No activity recorded for ${periodLabel}.`,\n };\n } catch {\n return { data: empty, displayText: 'Error fetching activity summary.' };\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport {\n resolveSuinsViaRpc,\n resolveAddressToSuinsViaRpc,\n SUI_ADDRESS_REGEX,\n SUINS_NAME_REGEX,\n SuinsRpcError,\n} from '../sui-address.js';\n\n// ---------------------------------------------------------------------------\n// resolve_suins — SuiNS lookup primitive (forward + reverse)\n//\n// The six address-accepting read tools (balance/health/savings/history/\n// activity-summary/portfolio-analysis) call `normalizeAddressInput()`\n// internally so the LLM can pass `address: \"alex.sui\"` and get the\n// resolution for free. This tool is the *explicit* lookup primitive for\n// queries the LLM can't satisfy with another tool — primarily:\n//\n// FORWARD (name → address):\n// \"What's the address of obehi.sui?\" → returns the 0x address\n// \"Is bob.sui registered?\" → returns registered: false\n// \"Who owns alex.sui?\" → returns the address\n//\n// REVERSE (address → name):\n// \"What's the SuiNS for 0xa671..3244?\" → returns \"ossy.sui\"\n// \"Does this address have a SuiNS?\" → returns names[]\n// \"Show me the .sui name for 0x40cd...3e62\" → returns \"funkii.sui\"\n//\n// v1.3 adds the reverse direction (was forward-only in v1.2) so\n// \"what's the suins for 0x...\" stops bouncing the user to SuiScan.\n//\n// Single polymorphic input (`query`) keeps the schema tiny — the tool\n// detects direction by regex (0x prefix → reverse, .sui suffix →\n// forward). Without this tool the LLM was previously trying\n// `web_search` (which can't index SuiNS) or pointing the user at\n// third-party explorers, both of which are the wrong answer.\n// ---------------------------------------------------------------------------\n\nconst inputSchema = z.object({\n query: z\n .string()\n .describe(\n 'Either a SuiNS name (e.g. \"alex.sui\", \"team.alex.sui\") to FORWARD-resolve to its 0x address, ' +\n 'OR a Sui address (0x… 64 hex chars) to REVERSE-resolve to its registered SuiNS name(s). ' +\n 'The engine detects direction by input shape.',\n ),\n});\n\ninterface ResolveSuinsResult {\n /** Direction the lookup ran in. */\n direction: 'forward' | 'reverse';\n /** The original query, lowercased. */\n query: string;\n /** Forward only: the resolved 0x address (null when unregistered). */\n address?: string | null;\n /** Forward only: convenience flag for the LLM. */\n registered?: boolean;\n /** Reverse only: every SuiNS name pointing at this address (sorted by registry). */\n names?: string[];\n /** Reverse only: the first name in `names` (the conventional \"primary\"), or null. */\n primary?: string | null;\n}\n\nexport const resolveSuinsTool = buildTool({\n name: 'resolve_suins',\n description:\n 'Look up SuiNS records on-chain — works in BOTH directions. ' +\n 'FORWARD: pass a SuiNS name (e.g. \"alex.sui\") to get the 0x address it resolves to. ' +\n 'REVERSE: pass a Sui 0x address to get the SuiNS name(s) registered for it (returns the ' +\n 'primary name + the full list). ' +\n '\\n\\nUse this WHENEVER the user mentions a `.sui` name OR asks \"what\\'s the SuiNS for 0x…\", ' +\n '\"does 0x… have a name\", \"who is 0x…\". You MUST call this tool — never guess from saved ' +\n 'contacts (a contact named \"alex\" is NOT the same as the SuiNS name \"alex.sui\"; verify on-chain). ' +\n 'Never use `web_search` for SuiNS — web_search doesn\\'t index the SuiNS registry, but this tool ' +\n 'queries the canonical on-chain RPC. ' +\n '\\n\\nReturns `{ direction, address, registered }` for forward, ' +\n '`{ direction, names, primary }` for reverse. Empty `names: []` means the address has no SuiNS records. ' +\n '\\n\\nNOTE: For money-flow questions about a `.sui` name (\"what\\'s alex.sui\\'s balance / portfolio / ' +\n 'health / transactions\"), call the relevant read tool directly with `address: \"alex.sui\"` — those ' +\n 'tools normalize SuiNS internally, so an explicit `resolve_suins` round-trip is wasted.',\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description:\n 'A SuiNS name (e.g. \"alex.sui\") for forward resolution, OR a 0x Sui address for reverse resolution.',\n },\n },\n required: ['query'],\n },\n isReadOnly: true,\n // Lookups map to (address|name) pairs on a per-block basis. Cheap and\n // deterministic for a given block — safe to dedupe within a turn.\n cacheable: true,\n preflight: (input) => {\n const trimmed = input.query?.trim().toLowerCase();\n if (!trimmed) {\n return { valid: false, error: 'query is required' };\n }\n const isAddress = SUI_ADDRESS_REGEX.test(trimmed);\n const isName = SUINS_NAME_REGEX.test(trimmed);\n if (!isAddress && !isName) {\n return {\n valid: false,\n error:\n `\"${input.query}\" doesn't look like a SuiNS name or a Sui address. ` +\n `Pass either a name ending in .sui (e.g. alex.sui) or a 0x-prefixed hex address.`,\n };\n }\n return { valid: true };\n },\n\n async call(input, context) {\n const query = input.query.trim().toLowerCase();\n const isAddress = SUI_ADDRESS_REGEX.test(query);\n\n try {\n if (isAddress) {\n const names = await resolveAddressToSuinsViaRpc(query, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n const primary = names[0] ?? null;\n const result: ResolveSuinsResult = {\n direction: 'reverse',\n query,\n names,\n primary,\n };\n return {\n data: result,\n displayText: primary\n ? `\\`${query.slice(0, 10)}…${query.slice(-6)}\\` → ${primary}${names.length > 1 ? ` (+${names.length - 1} more)` : ''}`\n : `\\`${query.slice(0, 10)}…${query.slice(-6)}\\` has no SuiNS name registered.`,\n };\n }\n\n // Forward direction: name → address.\n const address = await resolveSuinsViaRpc(query, {\n suiRpcUrl: context.suiRpcUrl,\n signal: context.signal,\n });\n const result: ResolveSuinsResult = {\n direction: 'forward',\n query,\n address,\n registered: address !== null,\n };\n return {\n data: result,\n displayText: address\n ? `${query} → \\`${address.slice(0, 10)}…${address.slice(-6)}\\``\n : `${query} is not a registered SuiNS name.`,\n };\n } catch (err) {\n // Surface RPC failures as a tool-level error so the LLM can narrate\n // (\"the SuiNS service is temporarily unreachable, try again in a\n // moment\") instead of pretending the lookup returned empty.\n if (err instanceof SuinsRpcError) {\n throw err;\n }\n throw err;\n }\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\n\n// ---------------------------------------------------------------------------\n// update_todo — persistent per-turn todo list (SPEC 8 v0.5.1, P3.2 slice 2)\n//\n// The LLM calls this tool to declare or update its plan for the current\n// turn. Each call replaces the entire list — the tool is idempotent;\n// later calls overwrite earlier ones.\n//\n// The host renders the list as a sticky timeline block during the turn and\n// collapses it into \"✓ N-step plan completed\" once the turn ends. See\n// `spec/SPEC_8_INTERACTIVE_HARNESS.md` § \"Layer 2 — `update_todo` tool\".\n//\n// ## Why this is a tool and not a system-prompt convention\n//\n// Tools have typed inputs the LLM can't malform. A free-text \"<plan>...\n// </plan>\" convention would lose its shape under truncation, cache\n// invalidation, or model upgrade. Typed input means hosts get a structured\n// payload they can render, persist, or replay without parsing prose.\n//\n// ## Why this is exempt from `maxTurns`\n//\n// Calling `update_todo` documents work; it doesn't advance work. If the\n// LLM fires it 4× during a 5-tool plan, that's 4 of its 10 turns gone to\n// narration before any real action. The exemption (in `engine.ts`\n// agentLoop) detects iterations where every `tool_use` block was\n// `update_todo` and decrements `turns` so the budget stays for actual\n// progress. See engine.ts § \"[SPEC 8 v0.5.1] update_todo maxTurns\n// exemption\".\n//\n// ## Why the tool emits a side-channel `todo_update` event\n//\n// The host needs to render the persistent todo card the moment the tool\n// fires — before the LLM streams its next thought. A regular `tool_result`\n// event renders inline-after-the-stream-tool-block; the side channel lets\n// the host render directly to the timeline's sticky surface. Pattern\n// mirrors the existing `canvas` event (engine.ts ~line 805–816): the tool\n// result carries a magic `__todoUpdate: true` flag and the engine emits\n// the side-channel event in addition to the normal `tool_result`.\n//\n// ## Preflight rules (LLM-facing)\n//\n// - 1–8 items per call (no empty lists; 8 is the spec ceiling)\n// - Each label ≤ 80 chars (forces concision; longer text belongs in chat)\n// - Exactly 1 `in_progress` item (the user must always know \"what's\n// happening now\")\n// - All `id`s unique (host keys re-renders on id stability)\n// - `status` is one of the three known values\n//\n// Failed preflight returns the rule that broke as `error.error`; the LLM\n// re-asks with a corrected payload — same flow as every other write\n// tool's preflight.\n// ---------------------------------------------------------------------------\n\nconst todoStatusSchema = z.enum(['pending', 'in_progress', 'completed']);\n\nconst todoItemSchema = z.object({\n id: z\n .string()\n .min(1, 'id must be a non-empty string')\n .max(40, 'id must be ≤40 chars (use a slug, not a sentence)'),\n label: z\n .string()\n .min(1, 'label must be a non-empty string')\n .max(80, 'label must be ≤80 chars (the whole point of this tool is concision)'),\n status: todoStatusSchema,\n});\n\nconst inputSchema = z.object({\n items: z\n .array(todoItemSchema)\n .min(1, 'items must contain at least 1 entry')\n .max(8, 'items must contain at most 8 entries (SPEC 8 ceiling)'),\n});\n\nexport type TodoItem = z.infer<typeof todoItemSchema>;\nexport type UpdateTodoInput = z.infer<typeof inputSchema>;\n\nexport const updateTodoTool = buildTool({\n name: 'update_todo',\n description:\n \"Declare or replace your plan for the current turn as a structured todo list. \" +\n \"Call this when the user's ask is multi-step (≥3 tools, ≥2 reasoning hops) so \" +\n \"the user can see what you're doing as you do it. Each call replaces the entire \" +\n \"list — the tool is idempotent. \" +\n \"\\n\\nRules: 1–8 items, each label ≤80 chars, exactly 1 item must be `in_progress`. \" +\n \"Use stable `id`s across calls within the same turn so the UI can track item \" +\n \"transitions (e.g. `id: 'check-balance'` first as `pending`, later as `completed`). \" +\n \"\\n\\nDO NOT call this for single-step asks ('balance', 'rate') — it's wasted \" +\n \"tokens. DO call it before kicking off long flows where the user benefits from \" +\n \"seeing the plan unfold ('save my idle USDC' → check balance → check rates → \" +\n \"compute split → propose). \" +\n \"\\n\\nThis call doesn't count against your turn budget — re-narrating the plan \" +\n \"as items move from pending → in_progress → completed is encouraged.\",\n inputSchema,\n jsonSchema: {\n type: 'object',\n properties: {\n items: {\n type: 'array',\n minItems: 1,\n maxItems: 8,\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Stable identifier across calls within the same turn (e.g. \"check-balance\"). ≤40 chars.',\n },\n label: {\n type: 'string',\n description: 'What this step is doing, ≤80 chars. Concrete (e.g. \"Check USDC rate\") not abstract (\"Gather data\").',\n },\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'completed'],\n description: 'Lifecycle state. Exactly one item must be `in_progress` per call.',\n },\n },\n required: ['id', 'label', 'status'],\n },\n },\n },\n required: ['items'],\n },\n isReadOnly: true,\n // No I/O, just a pass-through that emits a side-channel event. Skip the\n // turn-read cache — every call is intentionally distinct (ids may match\n // but statuses change).\n cacheable: false,\n preflight: (input) => {\n const items = input.items ?? [];\n if (items.length === 0) {\n return { valid: false, error: 'items must contain at least 1 entry' };\n }\n if (items.length > 8) {\n return { valid: false, error: `items must contain at most 8 entries, got ${items.length}` };\n }\n const seenIds = new Set<string>();\n let inProgressCount = 0;\n for (const item of items) {\n if (!item.id || item.id.trim().length === 0) {\n return { valid: false, error: 'every item must have a non-empty id' };\n }\n if (item.id.length > 40) {\n return { valid: false, error: `item id \"${item.id.slice(0, 30)}…\" exceeds 40 chars` };\n }\n if (seenIds.has(item.id)) {\n return { valid: false, error: `duplicate item id \"${item.id}\" — ids must be unique within a list` };\n }\n seenIds.add(item.id);\n if (!item.label || item.label.trim().length === 0) {\n return { valid: false, error: `item \"${item.id}\" has empty label` };\n }\n if (item.label.length > 80) {\n return { valid: false, error: `item \"${item.id}\" label exceeds 80 chars (got ${item.label.length})` };\n }\n if (item.status === 'in_progress') {\n inProgressCount++;\n }\n }\n if (inProgressCount !== 1) {\n return {\n valid: false,\n error: `exactly 1 item must be in_progress, got ${inProgressCount}`,\n };\n }\n return { valid: true };\n },\n\n async call(input) {\n return {\n // The `__todoUpdate` flag tells the engine's agent loop to emit a\n // `todo_update` side-channel event (mirrors the `__canvas` magic\n // flag pattern). The LLM still gets a normal `tool_result` keyed\n // to its `tool_use_id` so the Anthropic protocol stays satisfied.\n data: {\n __todoUpdate: true,\n items: input.items,\n },\n displayText: `${input.items.length} step${input.items.length === 1 ? '' : 's'}: ${input.items\n .map((i) => `${i.status === 'completed' ? '✓' : i.status === 'in_progress' ? '→' : '·'} ${i.label}`)\n .join(' / ')}`,\n };\n },\n});\n","import { z } from 'zod';\nimport { buildTool } from '../tool.js';\nimport { fetchTokenPrices } from '../blockvision-prices.js';\n\n// ---------------------------------------------------------------------------\n// [v1.4 — Day 2] BlockVision-backed unified price tool.\n//\n// Replaces both deleted DefiLlama tools:\n// * `defillama_token_prices` — multi-token spot price\n// * `defillama_price_change` — single-token price + period change\n//\n// `defillama_price_change` previously supported 1h / 24h / 7d / 30d windows;\n// BlockVision only exposes 24h. Surfacing 24h is enough to answer the hot-\n// path question \"did X move today?\", and the LLM no longer has a tool that\n// silently lies about 7d/30d windows by re-running 24h. Accepted regression.\n//\n// `protocol_deep_dive` (lone surviving DefiLlama prod dependency) is\n// untouched — protocol-level safety data has no BlockVision equivalent.\n// ---------------------------------------------------------------------------\n\nexport const tokenPricesTool = buildTool({\n name: 'token_prices',\n description:\n 'Get current USD prices for Sui tokens, with optional 24h change. Accepts full coin type strings (e.g. \"0x2::sui::SUI\"). Returns price per token and (when requested) 24h change percentage. Use for \"what is X worth?\" or \"did Y move today?\". For balance + portfolio rendering, prefer balance_check / portfolio_analysis instead — they bundle the same prices into the standard cards.',\n inputSchema: z.object({\n coinTypes: z\n .array(z.string())\n .min(1)\n .max(10)\n .describe('Array of Sui coin type strings (max 10 per call).'),\n include24hChange: z\n .boolean()\n .optional()\n .describe('When true, include 24h change percentage per token in the output.'),\n }),\n jsonSchema: {\n type: 'object',\n properties: {\n coinTypes: {\n type: 'array',\n items: { type: 'string' },\n description: 'Sui coin type strings (max 10).',\n },\n include24hChange: {\n type: 'boolean',\n description: 'Include 24h change percentage per token.',\n },\n },\n required: ['coinTypes'],\n },\n isReadOnly: true,\n\n async call(input, context) {\n const prices = await fetchTokenPrices(input.coinTypes, context.blockvisionApiKey, { retryStats: context.retryStats });\n\n const results = input.coinTypes.map((coinType) => {\n const entry = prices[coinType];\n const symbol = coinType.split('::').pop() ?? coinType;\n if (!entry) {\n return {\n coinType,\n symbol,\n price: null,\n priceUnavailable: true,\n };\n }\n const out: {\n coinType: string;\n symbol: string;\n price: number;\n change24h?: number;\n } = {\n coinType,\n symbol,\n price: entry.price,\n };\n if (input.include24hChange && entry.change24h !== undefined) {\n out.change24h = entry.change24h;\n }\n return out;\n });\n\n return {\n data: results,\n displayText: results\n .map((r) => {\n if (r.price === null) return `${r.symbol}: price unavailable`;\n const change = (r as { change24h?: number }).change24h;\n return change !== undefined\n ? `${r.symbol}: $${r.price.toFixed(4)} (${change >= 0 ? '+' : ''}${change.toFixed(2)}% 24h)`\n : `${r.symbol}: $${r.price.toFixed(4)}`;\n })\n .join(', '),\n };\n },\n});\n","import type { Tool } from '../types.js';\nimport { applyToolFlags } from '../tool-flags.js';\nimport { balanceCheckTool } from './balance.js';\nimport { savingsInfoTool } from './savings.js';\nimport { healthCheckTool } from './health.js';\nimport { ratesInfoTool } from './rates.js';\nimport { transactionHistoryTool } from './history.js';\nimport { saveDepositTool } from './save.js';\nimport { withdrawTool } from './withdraw.js';\nimport { sendTransferTool } from './transfer.js';\nimport { borrowTool } from './borrow.js';\nimport { repayDebtTool } from './repay.js';\nimport { claimRewardsTool } from './claim.js';\nimport { payApiTool } from './pay.js';\nimport { mppServicesTool } from './mpp-services.js';\nimport { swapExecuteTool } from './swap.js';\nimport { swapQuoteTool } from './swap-quote.js';\nimport { voloStakeTool } from './volo-stake.js';\nimport { voloUnstakeTool } from './volo-unstake.js';\nimport { voloStatsTool } from './volo-stats.js';\nimport { saveContactTool } from './contacts.js';\nimport { webSearchTool } from './web-search.js';\nimport { explainTxTool } from './explain-tx.js';\nimport { portfolioAnalysisTool } from './portfolio-analysis.js';\nimport { protocolDeepDiveTool } from './protocol-deep-dive.js';\nimport {\n createPaymentLinkTool,\n listPaymentLinksTool,\n cancelPaymentLinkTool,\n createInvoiceTool,\n cancelInvoiceTool,\n listInvoicesTool,\n} from './receive.js';\nimport { renderCanvasTool } from './canvas.js';\nimport { spendingAnalyticsTool } from './spending.js';\nimport { yieldSummaryTool } from './yield-summary.js';\nimport { activitySummaryTool } from './activity-summary.js';\nimport { resolveSuinsTool } from './resolve-suins.js';\n// [SPEC 8 v0.5.1] update_todo is opt-in — NOT included in READ_TOOLS.\n// Hosts adopt by appending `updateTodoTool` to their tool list:\n// tools: [...getDefaultTools(), updateTodoTool]\n// This keeps the existing audric/web call sites zero-risk until the\n// SPEC 8 host wiring (P3.3) lands.\nimport { updateTodoTool } from './update-todo.js';\n// [v1.4 — Day 3] All 7 `defillama_*` LLM tools removed. The\n// BlockVision-backed `token_prices` tool covers spot prices; the\n// surviving DefiLlama dependency is `protocol_deep_dive`, which holds\n// onto its own `api.llama.fi` calls (TVL/fees/audit metadata) and is\n// the lone production consumer of the upstream API. See\n// AUDRIC_HARNESS_INTELLIGENCE_SPEC_v1.4.1.md §\"Day 3\" for context.\nimport { tokenPricesTool } from './token-prices.js';\n\n// [SIMPLIFICATION DAY 7] Removed 9 tools to align engine with chat-first thesis:\n// - allowance_status, toggle_allowance, update_daily_limit, update_permissions\n// (allowance contract dormant; agent autonomy under zkLogin was theatre)\n// - create_schedule, list_schedules, cancel_schedule\n// (DCA/scheduled actions can't execute without user online to sign)\n// - pause_pattern, pattern_status\n// (pattern detection as proposals removed; classifiers stay as pure fns)\n//\n// [v1.4 — Day 3] All 7 defillama_* LLM tools deleted (Day 2: prices/\n// change → BlockVision; Day 3: yield-pools/protocol-info/chain-tvl/\n// protocol-fees/sui-protocols deleted, no replacement). Current tool\n// count: 23 reads + 11 writes = 34 tools.\n\nexport const READ_TOOLS: Tool[] = [\n renderCanvasTool,\n balanceCheckTool,\n savingsInfoTool,\n healthCheckTool,\n ratesInfoTool,\n transactionHistoryTool,\n swapQuoteTool,\n voloStatsTool,\n mppServicesTool,\n webSearchTool,\n explainTxTool,\n portfolioAnalysisTool,\n protocolDeepDiveTool,\n tokenPricesTool,\n listPaymentLinksTool,\n cancelPaymentLinkTool,\n listInvoicesTool,\n cancelInvoiceTool,\n createPaymentLinkTool,\n createInvoiceTool,\n spendingAnalyticsTool,\n yieldSummaryTool,\n activitySummaryTool,\n resolveSuinsTool,\n];\n\nexport const WRITE_TOOLS: Tool[] = [\n saveDepositTool,\n withdrawTool,\n sendTransferTool,\n borrowTool,\n repayDebtTool,\n claimRewardsTool,\n payApiTool,\n swapExecuteTool,\n voloStakeTool,\n voloUnstakeTool,\n saveContactTool,\n];\n\nexport function getDefaultTools(): Tool[] {\n return applyToolFlags([...READ_TOOLS, ...WRITE_TOOLS]);\n}\n\nexport {\n renderCanvasTool,\n balanceCheckTool,\n savingsInfoTool,\n healthCheckTool,\n ratesInfoTool,\n transactionHistoryTool,\n saveDepositTool,\n withdrawTool,\n sendTransferTool,\n borrowTool,\n repayDebtTool,\n claimRewardsTool,\n payApiTool,\n mppServicesTool,\n swapExecuteTool,\n swapQuoteTool,\n voloStakeTool,\n voloUnstakeTool,\n voloStatsTool,\n webSearchTool,\n explainTxTool,\n portfolioAnalysisTool,\n protocolDeepDiveTool,\n tokenPricesTool,\n saveContactTool,\n createPaymentLinkTool,\n listPaymentLinksTool,\n cancelPaymentLinkTool,\n createInvoiceTool,\n cancelInvoiceTool,\n listInvoicesTool,\n spendingAnalyticsTool,\n yieldSummaryTool,\n activitySummaryTool,\n resolveSuinsTool,\n updateTodoTool,\n};\n","/**\n * tool-modifiable-fields.ts — Audric Harness Correctness Spec v1.4 / Item 6\n *\n * Per-tool registry of input fields the host UI may let the user modify\n * before approving a `PendingAction`. The engine consults this registry\n * when emitting a `pending_action` event so the client can render an\n * editable control without hard-coding tool names in the UI layer.\n *\n * The plan reserves modification for amount-bearing write tools where the\n * user might want to lower the amount before confirming (e.g. \"save $50\"\n * → user edits to $30 → engine resumes with the modified input). Tools\n * absent from this registry have no modifiable fields and the UI renders\n * a static \"approve / deny\" pair.\n */\nimport type { PendingActionModifiableField } from '../types.js';\n\n/**\n * Tool name → ordered list of modifiable input fields. Order matters for\n * UI rendering — the first entry typically becomes the prominent control.\n */\nexport const TOOL_MODIFIABLE_FIELDS: Record<string, PendingActionModifiableField[]> = {\n save_deposit: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n withdraw: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n send_transfer: [\n // `amount` first so the UI surfaces it prominently; the recipient\n // address field is also editable in case the user typed the wrong one.\n { name: 'amount', kind: 'amount' },\n { name: 'to', kind: 'address' },\n ],\n swap_execute: [\n { name: 'amount', kind: 'amount' },\n ],\n borrow: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n repay_debt: [\n { name: 'amount', kind: 'amount', asset: 'USDC' },\n ],\n volo_stake: [\n { name: 'amount', kind: 'amount', asset: 'SUI' },\n ],\n volo_unstake: [\n { name: 'amount', kind: 'amount', asset: 'vSUI' },\n ],\n};\n\n/**\n * Returns the modifiable fields for a tool name, or `undefined` if the tool\n * has no modifiable inputs. Used by the engine when emitting `pending_action`.\n */\nexport function getModifiableFields(\n toolName: string,\n): PendingActionModifiableField[] | undefined {\n return TOOL_MODIFIABLE_FIELDS[toolName];\n}\n","export const DEFAULT_SYSTEM_PROMPT = `You are Audric — a financial agent on Sui. Audric is exactly five products: Audric Passport (the trust layer — Google sign-in, non-custodial wallet, tap-to-confirm consent, sponsored gas — wraps every other product), Audric Intelligence (you — the 5-system brain: Agent Harness with 34 tools, Reasoning Engine with 14 guards and 6 skill recipes, Silent Profile, Chain Memory, AdviceLog), Audric Finance (manage money on Sui — 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 — send USDC, receive via payment links / invoices / QR; free, global, instant on Sui), and Audric Store (creator marketplace, ships Phase 5 — say \"coming soon\" if asked). Save, swap, borrow, repay, withdraw, charts → Audric Finance. Send, receive, payment-link, invoice, QR → Audric Pay. Your silent context (profile, memory, chain facts, advice log) shapes your replies but never surfaces as a notification — 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 — this is an internal capability, not a promoted product, so only mention it when the user asks for something that needs it.\n\n## Response rules\n- 1-2 sentences max. No bullet lists unless asked. No preambles.\n- Never say \"Would you like me to...\", \"Sure!\", \"Great question!\", \"Absolutely!\" — just do it or say you can't.\n- Present amounts as $1,234.56 and rates as X.XX% APY.\n- Show top 3 results unless asked for more. Summarize totals in one line.\n\n## Caption rules (after tool calls)\n- **When a canvas was rendered (\\`render_canvas\\` was called, or any tool that auto-renders a card like balance_check / portfolio_analysis / savings_info / health_check / transaction_history): the canvas IS the answer.** Your chat message must NOT restate wallet, savings, debt, holdings, or net-worth numbers — they are already on screen. Add at most ONE sentence of context, advice, or next step (e.g. \"Your USDC is idle — consider depositing for ~4.5% APY\"), or say nothing.\n- **When NO canvas was rendered:** lead with the result and quote the actual numbers from the tool. One sentence.\n- **NEVER describe a position as \"no\", \"none\", \"minimal\", \"zero\", or \"inactive\" if the tool result contains a positive value for that field.** The tool result is the source of truth — never your interior summary. If the canvas shows $100 in savings, you cannot say \"no active savings\" in the caption.\n- **NEVER claim \"no DeFi positions\" when the tool result says the DeFi slice is UNAVAILABLE.** When \\`balance_check\\` displayText contains \"DeFi positions: UNAVAILABLE\" or \"DeFi data source unreachable\", the slice is unknown — say \"DeFi data is currently unavailable\" or omit the mention. Only claim \"no DeFi positions\" when the displayText explicitly omits any DeFi line (i.e. the fetch succeeded with $0 across every covered protocol).\n\n## Execution rule\nOnly offer to execute actions you have tools for. If you retrieved a quote, data, or information but have no tool to act on it, give the user the result and tell them where to execute manually — in one sentence. Never say \"Would you like me to proceed?\" unless you have a tool that can actually proceed.\n\n## Before acting\n- ALWAYS call a read tool first before any write tool — balance_check before save/send/borrow, savings_info before withdraw.\n- Show real numbers from tools — never fabricate rates, amounts, or balances.\n- When user says \"all\" or an imprecise amount, call the read tool first to get the exact number.\n\n## Tool usage\n- Use tools proactively — don't refuse requests you can handle.\n- For real-world questions (weather, search, news, prices), use pay_api. Tell the user the cost first.\n- For NAVI lending APYs, use rates_info; for VOLO liquid staking stats, use volo_stats; for spot token prices, use token_prices.\n- For protocol-level due diligence (TVL, fees, audits, safety) on Sui DeFi protocols, use protocol_deep_dive with the slug.\n- Run multiple read-only tools in parallel when you need several data points.\n- If a tool errors, say what went wrong and what to try instead. One sentence.\n\n## Savings = USDC or USDsui (critical)\n- save_deposit and borrow accept ONLY USDC or USDsui. No other token can be deposited or borrowed.\n- USDC is the canonical default. USDsui is permitted because it has a productive NAVI pool (often a higher APY than USDC). All other holdings (GOLD, SUI, USDT, USDe, ETH, NAVX, WAL) are NOT saveable.\n- When asked \"how much can I save?\":\n - Report saveableUsdc from balance_check (the user's USDC wallet balance — canonical saveable).\n - If the user also holds USDsui in their wallet, report that separately as \"USDsui (saveable): X.XX\". Do NOT roll the two together — the LLM must keep the per-asset distinction so the user can pick.\n- When the user says \"save 10 USDC\" → call save_deposit with asset=\"USDC\". When they say \"save 10 USDsui\" → call with asset=\"USDsui\". Never silently substitute.\n- When the user says \"save 10\" (no asset) → call balance_check first and ask which stable they want, OR pick whichever they hold more of with a one-line explanation.\n- \"Best stable to save right now?\" → call rates_info to compare USDC vs USDsui APY on NAVI; let the user pick.\n- NEVER say a non-saveable token (GOLD, SUI, USDT, etc.) is \"in savings\" or \"earning APY in savings\". Wallet holdings ≠ savings positions, even for stables we don't accept.\n- If user wants to save a non-saveable token, tell them to swap to USDC or USDsui first. Do NOT auto-chain swap + deposit.\n- Repay symmetry: a USDsui debt MUST be repaid with USDsui (and USDC debt with USDC). When calling repay_debt, pass asset=\"USDsui\" if the borrow is USDsui. If the user asks \"repay my debt\" and savings_info shows borrows in BOTH stables, list both and ask which to repay first. If the user holds the wrong stable, tell them to swap manually — do NOT auto-chain swap + repay.\n\n## Multi-step flows\n- \"How much X for Y?\": swap_quote first, then swap_execute if user confirms.\n- \"Swap then save\": swap_execute → balance_check → save_deposit. Confirm each step.\n- \"Buy $X of token\": token_prices → calculate amount → swap_execute.\n- \"Best yield on SUI\": compare rates_info (NAVI lending) + volo_stats (vSUI liquid staking).\n- withdraw supports legacy positions: USDC, USDe, USDsui, SUI. Pass asset param to withdraw a specific token.\n- \"Deposit SUI to earn yield\": volo_stake for SUI liquid staking. save_deposit only accepts USDC or USDsui.\n- \"Is protocol X safe?\" / \"Tell me about NAVI\": protocol_deep_dive with the slug.\n- \"Full account report\" / \"account summary\" / \"give me everything\" / \"complete overview\": triggers the \\`account_report\\` recipe — when the recipe block appears, follow EVERY step including all six tool calls. Each step renders a distinct rich card; skipping a step means a missing card.\n\n## Safety\n- Never encourage risky financial behavior.\n- Warn when health factor < 1.5.\n- All amounts in USDC unless stated otherwise.`;\n","// Claude Sonnet 4 pricing (USD per token)\nconst DEFAULT_INPUT_COST = 3 / 1_000_000; // $3 per 1M input tokens\nconst DEFAULT_OUTPUT_COST = 15 / 1_000_000; // $15 per 1M output tokens\nconst CACHE_WRITE_MULTIPLIER = 1.25; // 1.25x input rate\nconst CACHE_READ_MULTIPLIER = 0.1; // 0.1x input rate\n\nexport interface CostSnapshot {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n estimatedCostUsd: number;\n}\n\nexport interface CostTrackerConfig {\n budgetLimitUsd?: number;\n inputCostPerToken?: number;\n outputCostPerToken?: number;\n}\n\nexport class CostTracker {\n private inputTokens = 0;\n private outputTokens = 0;\n private cacheReadTokens = 0;\n private cacheWriteTokens = 0;\n private readonly budgetLimitUsd: number | null;\n private readonly inputCost: number;\n private readonly outputCost: number;\n\n constructor(config: CostTrackerConfig = {}) {\n this.budgetLimitUsd = config.budgetLimitUsd ?? null;\n this.inputCost = config.inputCostPerToken ?? DEFAULT_INPUT_COST;\n this.outputCost = config.outputCostPerToken ?? DEFAULT_OUTPUT_COST;\n }\n\n track(\n inputTokens: number,\n outputTokens: number,\n cacheReadTokens?: number,\n cacheWriteTokens?: number,\n ): void {\n this.inputTokens += inputTokens;\n this.outputTokens += outputTokens;\n this.cacheReadTokens += cacheReadTokens ?? 0;\n this.cacheWriteTokens += cacheWriteTokens ?? 0;\n }\n\n getSnapshot(): CostSnapshot {\n const totalTokens =\n this.inputTokens + this.outputTokens + this.cacheReadTokens + this.cacheWriteTokens;\n\n const estimatedCostUsd =\n this.inputTokens * this.inputCost +\n this.outputTokens * this.outputCost +\n this.cacheReadTokens * this.inputCost * CACHE_READ_MULTIPLIER +\n this.cacheWriteTokens * this.inputCost * CACHE_WRITE_MULTIPLIER;\n\n return {\n inputTokens: this.inputTokens,\n outputTokens: this.outputTokens,\n cacheReadTokens: this.cacheReadTokens,\n cacheWriteTokens: this.cacheWriteTokens,\n totalTokens,\n estimatedCostUsd,\n };\n }\n\n isOverBudget(): boolean {\n if (this.budgetLimitUsd === null) return false;\n return this.getSnapshot().estimatedCostUsd >= this.budgetLimitUsd;\n }\n\n getRemainingBudgetUsd(): number | null {\n if (this.budgetLimitUsd === null) return null;\n return Math.max(0, this.budgetLimitUsd - this.getSnapshot().estimatedCostUsd);\n }\n\n reset(): void {\n this.inputTokens = 0;\n this.outputTokens = 0;\n this.cacheReadTokens = 0;\n this.cacheWriteTokens = 0;\n }\n}\n","/**\n * Generates user-facing descriptions for `PendingAction`s.\n *\n * Extracted from `engine.ts` in SPEC 7 P2.3 so both the legacy\n * single-write yield path AND the new bundle-composer (`compose-bundle.ts`)\n * can derive per-step descriptions from the same source.\n */\nimport type { Tool } from './types.js';\nimport type { PendingToolCall } from './orchestration.js';\nimport { estimatePayApiCost } from './tools/pay.js';\n\nfunction resolveTokenSymbol(nameOrType: string): string {\n if (!nameOrType.includes('::')) return nameOrType;\n const parts = nameOrType.split('::');\n return parts[parts.length - 1];\n}\n\nexport function describeAction(tool: Tool, call: PendingToolCall): string {\n const input = call.input as Record<string, unknown>;\n switch (tool.name) {\n case 'save_deposit': {\n return `Save ${input.amount} USDC into lending`;\n }\n case 'withdraw': {\n const wAsset = input.asset ?? '';\n return `Withdraw ${input.amount}${wAsset ? ' ' + wAsset : ''} from lending`;\n }\n case 'send_transfer':\n return `Send $${input.amount} to ${input.to}`;\n case 'borrow':\n return `Borrow $${input.amount} against collateral`;\n case 'repay_debt':\n return `Repay $${input.amount} of outstanding debt`;\n case 'claim_rewards':\n return 'Claim all pending protocol rewards';\n case 'pay_api': {\n const url = String(input.url ?? '');\n const cost = estimatePayApiCost(url);\n return `Pay for API call to ${url} (~$${cost})`;\n }\n case 'swap_execute': {\n const from = resolveTokenSymbol(String(input.from ?? '?'));\n const to = resolveTokenSymbol(String(input.to ?? '?'));\n const amt = input.amount ?? '?';\n const slippagePct = ((input.slippage as number) ?? 0.01) * 100;\n return `Swap ${amt} ${from} for ${to} (${slippagePct}% max slippage)`;\n }\n case 'volo_stake':\n return `Stake ${input.amount} SUI for vSUI`;\n case 'volo_unstake':\n return `Unstake ${input.amount === 'all' ? 'all' : input.amount} vSUI`;\n default:\n return `Execute ${tool.name}`;\n }\n}\n","import type { ThinkingConfig, ThinkingEffort } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Per-shape thinking-budget HARD caps (SPEC 8 v0.5.1, P3.2 slice 5)\n//\n// The 4 harness shapes (`lean` / `standard` / `rich` / `max`) correspond\n// 1-to-1 with the 4 ThinkingEffort tiers (`low` / `medium` / `high` /\n// `max`). Each tier carries a hard ceiling on `thinking.budget_tokens`\n// that hosts cannot exceed via direct config — the engine clamps before\n// calling the provider.\n//\n// Why HARD caps:\n// - Cost ceiling enforced even if a host misconfigures `budgetTokens`\n// - LEAN tier (low effort) MUST emit zero thinking blocks per spec — a\n// non-zero budget would produce drift between the spec's promise\n// (\"LEAN turns feel instant\") and reality\n// - Acceptance gates in P3.6 reference these exact caps; codifying them\n// here means the gates and the enforcement share a source of truth\n//\n// The host can pass a SMALLER budget — these are caps, not floors. A host\n// that wants `medium=4_000` keeps that; the engine never raises it.\n// ---------------------------------------------------------------------------\n\nexport const EFFORT_THINKING_BUDGET_CAPS: Record<ThinkingEffort, number | null> = {\n // null = thinking force-disabled (LEAN tier — single-fact reads need\n // zero deliberation; a thinking block here adds ~300ms TTFVP for no\n // benefit — see SPEC 8 § \"Decision 2: LEAN shape: zero thinking blocks\")\n low: null,\n medium: 8_000,\n high: 16_000,\n max: 32_000,\n};\n\n/**\n * Clamp a `ThinkingConfig` to the HARD cap for the given effort tier.\n *\n * - When `effort === 'low'`, returns `{ type: 'disabled' }` regardless of\n * input — LEAN tier is non-negotiable.\n * - When `config.type === 'enabled'` and `config.budgetTokens` exceeds\n * the cap, returns a copy with `budgetTokens` clamped down.\n * - When `config.type === 'adaptive'`, returns it unchanged — adaptive\n * mode is shape-agnostic by design (Anthropic decides per-turn).\n * - When `effort` is undefined, returns `config` unchanged — caller\n * hasn't classified the turn yet (back-compat for hosts that don't\n * route on effort).\n *\n * This function is pure and side-effect-free; safe to call per-turn.\n */\nexport function clampThinkingForEffort(\n config: ThinkingConfig | undefined,\n effort: ThinkingEffort | undefined,\n): ThinkingConfig | undefined {\n if (!config) return config;\n if (effort === undefined) return config;\n const cap = EFFORT_THINKING_BUDGET_CAPS[effort];\n if (cap === null) {\n return { type: 'disabled' };\n }\n if (config.type === 'enabled' && config.budgetTokens > cap) {\n return { ...config, budgetTokens: cap };\n }\n return config;\n}\n","import type { Tool, ToolFlags } from './types.js';\nimport type { PendingToolCall } from './orchestration.js';\n\n// ---------------------------------------------------------------------------\n// Guard types\n// ---------------------------------------------------------------------------\n\nexport type GuardVerdict = 'pass' | 'hint' | 'warn' | 'block';\n\nexport type GuardTier = 'safety' | 'financial' | 'ux';\n\nexport interface GuardResult {\n verdict: GuardVerdict;\n gate: string;\n tier: GuardTier;\n message?: string;\n}\n\nexport interface GuardInjection {\n _gate: string;\n _hint?: string;\n _warning?: string;\n _error?: string;\n}\n\nexport interface GuardCheckResult {\n blocked: boolean;\n blockReason?: string;\n blockGate?: string;\n injections: GuardInjection[];\n events: GuardEvent[];\n}\n\nexport interface GuardEvent {\n timestamp: number;\n toolName: string;\n toolUseId: string;\n gate: string;\n verdict: GuardVerdict;\n tier: GuardTier;\n message?: string;\n}\n\n/**\n * [v1.4 Item 4] Per-guard metric emitted via `EngineConfig.onGuardFired`.\n * Hosts (e.g. audric `TurnMetricsCollector`) accumulate these for the\n * `TurnMetrics.guardsFired` JSON column. Mirrors `GuardEvent` but with\n * a coarser tri-state action (allow/warn/block) so the host doesn't\n * need to know the engine's verdict vocabulary.\n */\nexport interface GuardMetric {\n name: string;\n tier: GuardTier;\n action: 'allow' | 'warn' | 'block';\n injectionAdded: boolean;\n}\n\n/**\n * Engine-internal mapping from `GuardVerdict` to `GuardMetric.action`.\n * `pass` and `hint` collapse to `allow` because hint is non-blocking —\n * the model just sees a soft note.\n */\nexport function guardVerdictToAction(verdict: GuardVerdict): GuardMetric['action'] {\n if (verdict === 'pass' || verdict === 'hint') return 'allow';\n if (verdict === 'warn') return 'warn';\n return 'block';\n}\n\n// ---------------------------------------------------------------------------\n// Guard configuration\n// ---------------------------------------------------------------------------\n\nexport interface GuardConfig {\n balanceValidation?: boolean;\n healthFactor?: { warnBelow: number; blockBelow: number } | false;\n largeTransfer?: { warnAbove: number; strongWarnAbove: number } | false;\n slippage?: boolean;\n staleData?: boolean;\n irreversibility?: boolean;\n artifactPreview?: boolean;\n costWarning?: boolean;\n retryProtection?: boolean;\n inputValidation?: boolean;\n /**\n * Root-cause guard for \"LLM types a recipient address from memory and\n * loses funds to a wrong-but-valid address\". When enabled (default),\n * `send_transfer.to` is rejected unless the address can be sourced\n * from a saved contact, the user's own wallet, or the user's recent\n * messages. Set to `false` only if the host has its own equivalent\n * upstream guard (e.g. an off-process verifier).\n */\n addressSource?: boolean;\n /**\n * Companion to `addressSource`: blocks send_transfer that defaults to\n * USDC when the user's recent messages clearly named a non-USDC token\n * (SUI, USDT, WAL, etc.). Without this, the LLM would call\n * `send_transfer({ amount, to })` for a \"send my SUI\" request and the\n * tool would silently ship USDC. Default on.\n */\n assetIntent?: boolean;\n /**\n * Root-cause fix for \"LLM hallucinates a stale training-data price\n * (e.g. '$3.50/SUI') and shows the user a wildly wrong estimate before\n * the swap card renders\". When enabled (default), `swap_execute` is\n * blocked unless a matching `swap_quote(from, to, amount)` ran in the\n * recent past (60s window, ±1% amount tolerance). The block forces the\n * LLM to fetch a real on-chain quote and cite its actual numbers, not\n * a guess. Set to `false` only if the host has its own pre-execution\n * quote requirement.\n */\n swapPreview?: boolean;\n /**\n * Root-cause fix for \"user asks about a watched address (`0x40cd…`)\n * and the LLM calls `balance_check` / `portfolio_analysis` /\n * `transaction_history` without passing `address`, returning the\n * signed-in user's own data instead\". The default-to-self behavior is\n * correct when no address is mentioned, but silently wrong when the\n * user names a third-party wallet. When enabled (default), the guard\n * inspects recent user messages for full Sui addresses and blocks\n * any read tool that targets the user's own wallet (or omits\n * `address`) when a different address was named. Disable only if the\n * host has its own equivalent address-resolution layer.\n */\n addressScope?: boolean;\n}\n\nexport const DEFAULT_GUARD_CONFIG: GuardConfig = {\n balanceValidation: true,\n healthFactor: { warnBelow: 2.0, blockBelow: 1.5 },\n largeTransfer: { warnAbove: 50, strongWarnAbove: 500 },\n slippage: true,\n staleData: true,\n irreversibility: true,\n artifactPreview: true,\n costWarning: true,\n retryProtection: true,\n inputValidation: true,\n addressSource: true,\n assetIntent: true,\n swapPreview: true,\n addressScope: true,\n};\n\n// ---------------------------------------------------------------------------\n// BalanceTracker — tracks freshness of balance data across the session\n// ---------------------------------------------------------------------------\n\nexport class BalanceTracker {\n private lastBalanceAt = 0;\n private lastWriteAt = 0;\n\n recordRead(): void {\n this.lastBalanceAt = Date.now();\n }\n\n recordWrite(): void {\n this.lastWriteAt = Date.now();\n }\n\n isStale(): boolean {\n return this.lastWriteAt > this.lastBalanceAt;\n }\n\n hasEverRead(): boolean {\n return this.lastBalanceAt > 0;\n }\n}\n\nconst BALANCE_READ_TOOLS = new Set([\n 'balance_check',\n 'savings_info',\n 'health_check',\n]);\n\n// ---------------------------------------------------------------------------\n// RetryTracker — prevents re-execution of paid/non-retryable tool calls\n// ---------------------------------------------------------------------------\n\nexport class RetryTracker {\n private executed = new Map<string, { result: unknown; paidAt: number }>();\n\n private key(toolName: string, input: unknown): string {\n const url = (input as Record<string, unknown>)?.url ?? '';\n return `${toolName}:${url}`;\n }\n\n record(toolName: string, input: unknown, result: unknown): void {\n const r = result as Record<string, unknown>;\n if (r?.paymentConfirmed || r?.doNotRetry) {\n this.executed.set(this.key(toolName, input), { result, paidAt: Date.now() });\n }\n }\n\n isBlocked(toolName: string, input: unknown): { blocked: boolean; previousResult?: unknown } {\n const prev = this.executed.get(this.key(toolName, input));\n if (!prev) return { blocked: false };\n return { blocked: true, previousResult: prev.result };\n }\n}\n\n// ---------------------------------------------------------------------------\n// SwapQuoteTracker — records swap_quote calls so swapPreview can verify a\n// swap_execute was preceded by a real on-chain quote. Without this, the\n// LLM falls back to training-memory prices and gives the user wildly wrong\n// estimates (the \"$3.50/SUI when SUI is $0.95\" class of bugs).\n// ---------------------------------------------------------------------------\n\ninterface RecordedSwapQuote {\n from: string;\n to: string;\n amount: number;\n ts: number;\n}\n\nexport class SwapQuoteTracker {\n /** Quotes recorded in the recent window. Trimmed lazily on every check. */\n private quotes: RecordedSwapQuote[] = [];\n\n /** Match window: 60s is generous enough for slow LLM turns but tight enough\n * to invalidate stale quotes from earlier in the session. */\n private readonly windowMs = 60_000;\n\n /** Amount tolerance: ±1% (covers gas-padding, integer-rounding, and the\n * rare case where the LLM rounds the input differently between quote and\n * execute). Prices barely move in 60s so 1% is forgiving but meaningful. */\n private readonly amountTolerance = 0.01;\n\n /**\n * Normalize a token identifier so symbol vs. coinType vs. case don't\n * cause spurious mismatches. Lowercase + trim is sufficient because the\n * SDK's resolver itself is case-insensitive on symbols.\n */\n private normalize(token: string): string {\n return token.trim().toLowerCase();\n }\n\n record(input: { from: string; to: string; amount: number }): void {\n const now = Date.now();\n this.quotes.push({\n from: this.normalize(input.from),\n to: this.normalize(input.to),\n amount: input.amount,\n ts: now,\n });\n const cutoff = now - this.windowMs;\n this.quotes = this.quotes.filter((q) => q.ts > cutoff);\n }\n\n hasMatchingQuote(input: { from: string; to: string; amount: number }): boolean {\n const cutoff = Date.now() - this.windowMs;\n const fromN = this.normalize(input.from);\n const toN = this.normalize(input.to);\n const target = input.amount;\n return this.quotes.some(\n (q) =>\n q.ts > cutoff &&\n q.from === fromN &&\n q.to === toN &&\n target > 0 &&\n Math.abs(q.amount - target) / target <= this.amountTolerance,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Individual guard implementations\n// Priority order: Safety > Financial > UX\n// ---------------------------------------------------------------------------\n\nfunction guardRetryProtection(\n tool: Tool,\n call: PendingToolCall,\n retryTracker: RetryTracker,\n): GuardResult {\n const check = retryTracker.isBlocked(tool.name, call.input);\n if (check.blocked) {\n return {\n verdict: 'block',\n gate: 'retry_blocked',\n tier: 'safety',\n message: `Blocked: ${tool.name} was already called and payment was confirmed. Do not retry.`,\n };\n }\n return { verdict: 'pass', gate: 'retry_blocked', tier: 'safety' };\n}\n\nfunction guardIrreversibility(\n tool: Tool,\n _call: PendingToolCall,\n conversationText: string,\n): GuardResult {\n if (!tool.flags.irreversible) {\n return { verdict: 'pass', gate: 'irreversibility', tier: 'safety' };\n }\n\n // [security] `confirm.*send` was rewritten to bound the wildcard\n // span (`.{0,200}`) so the regex is linear-time on degenerate inputs\n // like a 100KB string starting with \"confirm\" but never containing\n // \"send\". CodeQL flagged the unbounded `.*` as polynomial-redos.\n const hasPreview = /preview|here.{0,2}s what|confirm.{0,200}send|looks? good/i.test(conversationText);\n if (hasPreview) {\n return { verdict: 'pass', gate: 'irreversibility', tier: 'safety' };\n }\n\n return {\n verdict: 'hint',\n gate: 'irreversibility',\n tier: 'safety',\n message: 'This action is irreversible. Show a preview and ask the user to confirm before proceeding.',\n };\n}\n\nfunction guardBalanceValidation(\n tool: Tool,\n _call: PendingToolCall,\n balanceTracker: BalanceTracker,\n): GuardResult {\n if (!tool.flags.requiresBalance) {\n return { verdict: 'pass', gate: 'balance_required', tier: 'financial' };\n }\n\n if (!balanceTracker.hasEverRead()) {\n return {\n verdict: 'hint',\n gate: 'balance_required',\n tier: 'financial',\n message: 'Balance has not been checked this session. Call balance_check first to verify sufficient funds.',\n };\n }\n\n if (balanceTracker.isStale()) {\n return {\n verdict: 'hint',\n gate: 'balance_required',\n tier: 'financial',\n message: 'Balance data is stale (a write action occurred since last check). Call balance_check first to verify sufficient funds.',\n };\n }\n\n return { verdict: 'pass', gate: 'balance_required', tier: 'financial' };\n}\n\nfunction guardHealthFactor(\n tool: Tool,\n _call: PendingToolCall,\n lastHealthFactor: number | null,\n config: { warnBelow: number; blockBelow: number },\n): GuardResult {\n if (!tool.flags.affectsHealth) {\n return { verdict: 'pass', gate: 'health_factor', tier: 'financial' };\n }\n\n if (lastHealthFactor === null) {\n return {\n verdict: 'hint',\n gate: 'health_factor',\n tier: 'financial',\n message: 'Health factor has not been checked this session. Call health_check before this action.',\n };\n }\n\n if (lastHealthFactor < config.blockBelow) {\n return {\n verdict: 'block',\n gate: 'health_factor',\n tier: 'financial',\n message: `Health factor is ${lastHealthFactor.toFixed(2)} — this action risks liquidation. Refusing.`,\n };\n }\n\n if (lastHealthFactor < config.warnBelow) {\n return {\n verdict: 'warn',\n gate: 'health_factor',\n tier: 'financial',\n message: `Health factor is ${lastHealthFactor.toFixed(2)} — this action may reduce it further.`,\n };\n }\n\n return { verdict: 'pass', gate: 'health_factor', tier: 'financial' };\n}\n\nfunction guardLargeTransfer(\n tool: Tool,\n call: PendingToolCall,\n config: { warnAbove: number; strongWarnAbove: number },\n): GuardResult {\n if (tool.name !== 'send_transfer') {\n return { verdict: 'pass', gate: 'large_transfer', tier: 'financial' };\n }\n\n const input = call.input as Record<string, unknown>;\n const amount = Number(input.amount ?? 0);\n if (!amount || amount <= 0) {\n return { verdict: 'pass', gate: 'large_transfer', tier: 'financial' };\n }\n\n const recipient = String(input.recipient ?? input.to ?? '');\n const shortAddr = recipient.length > 10\n ? `${recipient.slice(0, 6)}...${recipient.slice(-4)}`\n : recipient;\n\n if (amount > config.strongWarnAbove) {\n return {\n verdict: 'warn',\n gate: 'large_transfer',\n tier: 'financial',\n message: `High-value transfer ($${amount}). Double-check the address: ${shortAddr}`,\n };\n }\n\n if (amount > config.warnAbove) {\n return {\n verdict: 'hint',\n gate: 'large_transfer',\n tier: 'financial',\n message: `This is a large transfer ($${amount}). Verify the recipient address.`,\n };\n }\n\n return { verdict: 'pass', gate: 'large_transfer', tier: 'financial' };\n}\n\nfunction guardSlippage(\n tool: Tool,\n _call: PendingToolCall,\n lastAssistantText: string,\n): GuardResult {\n if (tool.name !== 'swap_execute') {\n return { verdict: 'pass', gate: 'slippage_warning', tier: 'financial' };\n }\n\n // [security] Rewritten to non-overlapping form (`\\d[\\d,]{0,30}`\n // followed by an optional `\\.\\d{1,10}`) so the digit/decimal section\n // matches in linear time. Previously `[\\d,]+\\.?\\d*` could ambiguously\n // distribute digits across the two pieces, triggering CodeQL's\n // polynomial-redos rule on a long input like \"1234,1234,...\".\n const hasEstimate = /~?\\$?\\d[\\d,]{0,30}(?:\\.\\d{1,10})?\\s*(SUI|USDC|USDT|WETH)/i.test(lastAssistantText)\n || /approximately|≈|about|expect|receive/i.test(lastAssistantText);\n\n if (hasEstimate) {\n return { verdict: 'pass', gate: 'slippage_warning', tier: 'financial' };\n }\n\n return {\n verdict: 'hint',\n gate: 'slippage_warning',\n tier: 'financial',\n message: 'State the expected output amount to the user before executing the swap.',\n };\n}\n\nfunction guardCostWarning(\n tool: Tool,\n _call: PendingToolCall,\n conversationText: string,\n): GuardResult {\n if (!tool.flags.costAware) {\n return { verdict: 'pass', gate: 'cost_warning', tier: 'ux' };\n }\n\n const hasCostMention = /\\$\\d+\\.?\\d*|cost|fee|charge|price|pay/i.test(conversationText);\n if (hasCostMention) {\n return { verdict: 'pass', gate: 'cost_warning', tier: 'ux' };\n }\n\n return {\n verdict: 'hint',\n gate: 'cost_warning',\n tier: 'ux',\n message: 'This action has a monetary cost. Confirm the user is aware before proceeding.',\n };\n}\n\n// ---------------------------------------------------------------------------\n// guardAddressSource — root-cause fix for the \"LLM mistypes a recipient\n// address from memory and ships funds to a wrong-but-valid address\"\n// failure mode. We trust the user, never the model, with addresses.\n//\n// Accepts the `to` field on `send_transfer` only when it can be sourced\n// from one of three trusted origins:\n// 1. A saved contact's address (case-insensitive, normalized)\n// 2. The user's own wallet (sending to self)\n// 3. Verbatim presence in the user's recent messages\n// (case-insensitive substring match on the raw 0x...64-hex string)\n//\n// Anything else → block with a structured error so the LLM is forced to\n// ask the user to paste the address again rather than re-typing it.\n// ---------------------------------------------------------------------------\n\nconst SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{64}$/;\n\nfunction normalizeAddress(addr: string): string {\n return addr.trim().toLowerCase();\n}\n\n/**\n * [send-safety v2] Bound the failure mode where the LLM was asked to\n * send a non-USDC token (e.g. just-swapped SUI) but called send_transfer\n * with no `asset` field. The tool defaults `asset` to USDC, so the user\n * lost real money: \"Done! Sent your SUI\" while only USDC moved.\n *\n * Heuristic: if any of the supported NON-USDC tokens appears as a word\n * in the user's recent messages AND the call has no `asset` (or asset\n * is USDC while a different token is mentioned), block the call and\n * force the LLM to re-issue with an explicit `asset`.\n *\n * Tokens are matched as standalone words (`\\bSUI\\b`, `\\bWAL\\b`, etc.)\n * to avoid false positives on things like \"USDC\" or addresses that\n * happen to contain the substring \"sui\".\n */\nconst NON_USDC_TOKEN_WORDS: ReadonlyArray<{ symbol: string; pattern: RegExp }> = [\n // Patterns are anchored with \\b on both sides. Case-insensitive.\n { symbol: 'SUI', pattern: /\\bSUI\\b/i },\n { symbol: 'USDT', pattern: /\\bUSDT\\b/i },\n { symbol: 'USDe', pattern: /\\bUSDe\\b/i },\n { symbol: 'USDsui', pattern: /\\bUSDsui\\b/i },\n { symbol: 'WAL', pattern: /\\bWAL\\b/i },\n { symbol: 'ETH', pattern: /\\bETH\\b/i },\n { symbol: 'NAVX', pattern: /\\bNAVX\\b/i },\n { symbol: 'GOLD', pattern: /\\bGOLD\\b/i },\n];\n\nfunction guardAssetIntent(\n tool: Tool,\n call: PendingToolCall,\n userText: string,\n): GuardResult {\n if (tool.name !== 'send_transfer') {\n return { verdict: 'pass', gate: 'asset_intent', tier: 'safety' };\n }\n\n const input = call.input as Record<string, unknown>;\n const assetWasSet = !(input.asset === undefined || input.asset === null || input.asset === '');\n\n // If the LLM made any explicit asset choice, trust it — even if it's\n // USDC. The danger we're guarding against is the *silent default* to\n // USDC when the schema didn't expose `asset` at all (the original\n // failure mode). Once the LLM has explicitly committed to a token,\n // the user can verify and cancel at the permission card.\n if (assetWasSet) {\n return { verdict: 'pass', gate: 'asset_intent', tier: 'safety' };\n }\n\n // Asset was omitted. Block iff the user named a non-USDC token in\n // their recent messages, since the omitted-asset path defaults to\n // USDC and would silently ship the wrong token.\n const mentioned = NON_USDC_TOKEN_WORDS.find((t) => t.pattern.test(userText));\n if (!mentioned) {\n return { verdict: 'pass', gate: 'asset_intent', tier: 'safety' };\n }\n\n return {\n verdict: 'block',\n gate: 'asset_intent',\n tier: 'safety',\n message:\n `Asset mismatch: the user's recent messages mention \"${mentioned.symbol}\" but send_transfer was called without an \\`asset\\` field (defaults to USDC). ` +\n `If the user asked you to send ${mentioned.symbol}, re-issue send_transfer with \\`asset: \"${mentioned.symbol}\"\\`. ` +\n `If the user really meant USDC, set \\`asset: \"USDC\"\\` explicitly to confirm intent. Never default to USDC when the user named a different token.`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// guardSwapPreview — root-cause fix for \"LLM hallucinates a stale price\n// (e.g. '$3.50/SUI' when SUI is $0.95) and shows the user a wildly wrong\n// estimate before the swap card renders\". We require swap_execute to be\n// preceded by a real on-chain swap_quote so the LLM has authoritative\n// numbers (price impact, route, exact output) to cite.\n//\n// Match rule:\n// - Same `from` and `to` token identifiers (case-insensitive).\n// - `amount` within ±1% of the quoted amount.\n// - swap_quote ran within the last 60s (current turn is well within).\n//\n// Anything else → block with a structured error so the LLM is forced to\n// call swap_quote first and re-issue swap_execute with the same params.\n// ---------------------------------------------------------------------------\n\nfunction guardSwapPreview(\n tool: Tool,\n call: PendingToolCall,\n swapQuoteTracker: SwapQuoteTracker,\n): GuardResult {\n if (tool.name !== 'swap_execute') {\n return { verdict: 'pass', gate: 'swap_preview', tier: 'safety' };\n }\n\n const input = call.input as { from?: unknown; to?: unknown; amount?: unknown };\n const from = typeof input.from === 'string' ? input.from : '';\n const to = typeof input.to === 'string' ? input.to : '';\n const amount = Number(input.amount ?? 0);\n\n // If inputs are malformed, let `inputValidation`/`preflight` handle it —\n // this guard is specifically about quote freshness, not input shape.\n if (!from || !to || !(amount > 0)) {\n return { verdict: 'pass', gate: 'swap_preview', tier: 'safety' };\n }\n\n if (swapQuoteTracker.hasMatchingQuote({ from, to, amount })) {\n return { verdict: 'pass', gate: 'swap_preview', tier: 'safety' };\n }\n\n return {\n verdict: 'block',\n gate: 'swap_preview',\n tier: 'safety',\n message:\n `swap_execute requires a recent matching swap_quote so the user sees an accurate preview. ` +\n `Call swap_quote({ from: \"${from}\", to: \"${to}\", amount: ${amount} }) first, then re-issue swap_execute with the same params. ` +\n `swap_quote is read-only and returns the real on-chain output, route, and price impact — never estimate from memory.`,\n };\n}\n\nfunction guardAddressSource(\n tool: Tool,\n call: PendingToolCall,\n userText: string,\n contacts: ReadonlyArray<{ name: string; address: string }>,\n walletAddress: string | undefined,\n): GuardResult {\n if (tool.name !== 'send_transfer') {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n const input = call.input as Record<string, unknown>;\n const rawTo = String(input.to ?? '');\n if (!rawTo) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n // Contact-name passthrough: send_transfer accepts either a 0x address\n // or a contact name. If it's not in 0x...64-hex form, leave it alone —\n // the SDK's contact resolver handles names and will throw if unknown.\n if (!SUI_ADDRESS_REGEX.test(rawTo)) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n const normalizedTo = normalizeAddress(rawTo);\n\n if (walletAddress && normalizeAddress(walletAddress) === normalizedTo) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n for (const c of contacts) {\n if (normalizeAddress(c.address) === normalizedTo) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n }\n\n if (userText.toLowerCase().includes(normalizedTo)) {\n return { verdict: 'pass', gate: 'address_source', tier: 'safety' };\n }\n\n return {\n verdict: 'block',\n gate: 'address_source',\n tier: 'safety',\n message:\n `Safety check failed: the recipient address \"${rawTo}\" was not provided by the user (no saved contact matches, address is not the user's own wallet, and it does not appear verbatim in the user's recent messages). For safety, addresses must be supplied directly by the user — never reconstructed from memory or partial recall. Ask the user to paste the destination address again exactly.`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// guardAddressScope — symmetric companion to `guardAddressSource`, but for\n// READ tools. Bounds the failure mode where the LLM is asked about a\n// third-party wallet (`\"what's the balance of 0x40cd...\"`) and silently\n// drops the address parameter, returning the signed-in user's own data\n// instead. The default-to-self behavior of these tools is correct when\n// no address is mentioned, but wrong when the user named a third party.\n//\n// Read tools whose schema accepts an optional `address` field. Mirrors\n// the SDK's \"default to context.walletAddress\" pattern in `balance.ts`,\n// `portfolio-analysis.ts`, and `history.ts`. Tools not in this set\n// always pass through (they either don't take an address or use a\n// different param name).\n// ---------------------------------------------------------------------------\nconst READ_TOOLS_WITH_ADDRESS_PARAM = new Set([\n 'balance_check',\n 'portfolio_analysis',\n 'transaction_history',\n 'savings_info',\n 'health_check',\n 'spending_analytics',\n 'yield_summary',\n 'activity_summary',\n 'explain_tx',\n]);\n\n// Loose match for Sui addresses inside conversational text. The strict\n// `SUI_ADDRESS_REGEX` is anchored (`^…$`) and matches a single, full\n// 0x...64-hex string only. For substring scanning we accept 60-64 hex\n// characters since some clients normalize away leading zeros.\nconst SUI_ADDRESS_IN_TEXT_REGEX = /0x[a-fA-F0-9]{60,64}/g;\n\nfunction guardAddressScope(\n tool: Tool,\n call: PendingToolCall,\n userText: string,\n walletAddress: string | undefined,\n): GuardResult {\n if (!READ_TOOLS_WITH_ADDRESS_PARAM.has(tool.name)) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n const matches = userText.match(SUI_ADDRESS_IN_TEXT_REGEX);\n if (!matches || matches.length === 0) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n // Filter out references to the user's own wallet — those are not bugs.\n // Dedupe so a user message like \"compare 0xabc to 0xabc\" only carries\n // one address through the rest of the check.\n const ownWallet = walletAddress ? normalizeAddress(walletAddress) : null;\n const thirdPartyAddresses = Array.from(\n new Set(matches.map(normalizeAddress).filter((a) => a !== ownWallet)),\n );\n\n if (thirdPartyAddresses.length === 0) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n const input = call.input as Record<string, unknown>;\n const callAddress =\n typeof input.address === 'string' && input.address.length > 0\n ? normalizeAddress(input.address)\n : null;\n\n // Pass if the call already targets one of the user-mentioned third\n // parties. The LLM might pick any of multiple mentioned addresses on\n // any given turn — that's a UX choice, not a safety issue.\n if (callAddress && thirdPartyAddresses.includes(callAddress)) {\n return { verdict: 'pass', gate: 'address_scope', tier: 'safety' };\n }\n\n // Block: user named at least one third-party address but the call\n // either omitted `address` (defaults to signed-in user) or targeted\n // a different wallet (likely the signed-in user's, also wrong).\n const target = thirdPartyAddresses[0];\n const omittedHint = callAddress\n ? `with address: \"${callAddress}\"`\n : 'without an `address` field (which defaults to the signed-in user)';\n const mentionedHint =\n thirdPartyAddresses.length === 1\n ? `address ${target}`\n : `${thirdPartyAddresses.length} third-party addresses (first: ${target})`;\n return {\n verdict: 'block',\n gate: 'address_scope',\n tier: 'safety',\n message:\n `Address-scope mismatch: the user's recent messages mention ${mentionedHint} but ${tool.name} was called ${omittedHint}. ` +\n `Re-issue ${tool.name} with \\`address: \"${target}\"\\` to inspect the wallet the user actually asked about. ` +\n `Never default to the signed-in user when the user named a different wallet.`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Post-execution guards — run after tool result is available\n// ---------------------------------------------------------------------------\n\nexport function guardArtifactPreview(result: unknown): GuardInjection | null {\n if (!result || typeof result !== 'object') return null;\n const r = result as Record<string, unknown>;\n\n const hasImage =\n (typeof r.url === 'string' && /\\.(png|jpg|jpeg|webp|gif|svg)(\\?|$)/i.test(r.url))\n || (Array.isArray(r.images) && r.images.length > 0)\n || typeof r.image_url === 'string';\n\n const hasPdf = typeof r.url === 'string' && /\\.pdf(\\?|$)/i.test(r.url);\n\n if (hasImage || hasPdf) {\n return {\n _gate: 'artifact_preview',\n _hint: 'Show this to the user before proceeding. Output as ![description](url).',\n };\n }\n\n return null;\n}\n\nexport function guardStaleData(toolFlags: ToolFlags): GuardInjection | null {\n if (!toolFlags.mutating) return null;\n return {\n _gate: 'stale_data',\n _hint: 'A write action just completed. The balance snapshot is outdated. Do NOT calculate new balances from old data — call balance_check for fresh numbers, or use only the data returned by the write tool.',\n };\n}\n\n// ---------------------------------------------------------------------------\n// Guard runner — orchestrates all pre-execution guards\n// ---------------------------------------------------------------------------\n\nexport interface GuardRunnerState {\n balanceTracker: BalanceTracker;\n retryTracker: RetryTracker;\n swapQuoteTracker: SwapQuoteTracker;\n lastHealthFactor: number | null;\n}\n\nexport function createGuardRunnerState(): GuardRunnerState {\n return {\n balanceTracker: new BalanceTracker(),\n retryTracker: new RetryTracker(),\n swapQuoteTracker: new SwapQuoteTracker(),\n lastHealthFactor: null,\n };\n}\n\nexport function runGuards(\n tool: Tool,\n call: PendingToolCall,\n state: GuardRunnerState,\n config: GuardConfig,\n conversationContext: { fullText: string; lastAssistantText: string; recentUserText: string },\n /**\n * [v1.4 Item 4] Optional per-guard observation hook. Fired exactly\n * once per non-`pass` guard verdict (i.e. for every event that ends\n * up in `events`/`injections`/`block`). Errors thrown by the host\n * are caught so a misbehaving collector can't break tool execution.\n */\n onGuardFired?: (guard: GuardMetric) => void,\n /**\n * Identity context for the address-source safety guard. The guard\n * accepts `send_transfer.to` only when sourced from a saved contact,\n * the user's own wallet, or the user's recent messages — preventing\n * the LLM from typing addresses from memory and shipping funds to a\n * wrong-but-syntactically-valid recipient.\n */\n identity?: {\n contacts?: ReadonlyArray<{ name: string; address: string }>;\n walletAddress?: string;\n },\n): GuardCheckResult {\n const results: GuardResult[] = [];\n const now = Date.now();\n const fire = (verdict: GuardVerdict, tier: GuardTier, gate: string, hadInjection: boolean) => {\n if (!onGuardFired) return;\n try {\n onGuardFired({\n name: gate,\n tier,\n action: guardVerdictToAction(verdict),\n injectionAdded: hadInjection,\n });\n } catch (err) {\n console.warn('[guards] onGuardFired threw (ignored):', err);\n }\n };\n\n // Tier 0: Input validation (preflight) — runs first, invalid input = immediate block\n if (config.inputValidation !== false && tool.preflight) {\n const check = tool.preflight(call.input);\n if (!check.valid) {\n const event: GuardEvent = {\n timestamp: now,\n toolName: tool.name,\n toolUseId: call.id,\n gate: 'input_validation',\n verdict: 'block',\n tier: 'safety',\n message: check.error,\n };\n fire('block', 'safety', 'input_validation', false);\n return {\n blocked: true,\n blockReason: check.error,\n blockGate: 'input_validation',\n injections: [],\n events: [event],\n };\n }\n }\n\n // Tier 1: Safety guards\n if (config.retryProtection !== false) {\n results.push(guardRetryProtection(tool, call, state.retryTracker));\n }\n if (config.addressSource !== false) {\n results.push(\n guardAddressSource(\n tool,\n call,\n conversationContext.recentUserText,\n identity?.contacts ?? [],\n identity?.walletAddress,\n ),\n );\n }\n if (config.assetIntent !== false) {\n results.push(guardAssetIntent(tool, call, conversationContext.recentUserText));\n }\n if (config.addressScope !== false) {\n results.push(\n guardAddressScope(\n tool,\n call,\n conversationContext.recentUserText,\n identity?.walletAddress,\n ),\n );\n }\n if (config.swapPreview !== false) {\n results.push(guardSwapPreview(tool, call, state.swapQuoteTracker));\n }\n if (config.irreversibility !== false) {\n results.push(guardIrreversibility(tool, call, conversationContext.fullText));\n }\n\n // Tier 2: Financial guards\n if (config.balanceValidation !== false) {\n results.push(guardBalanceValidation(tool, call, state.balanceTracker));\n }\n if (config.healthFactor) {\n results.push(guardHealthFactor(tool, call, state.lastHealthFactor, config.healthFactor));\n }\n if (config.largeTransfer) {\n results.push(guardLargeTransfer(tool, call, config.largeTransfer));\n }\n if (config.slippage !== false) {\n results.push(guardSlippage(tool, call, conversationContext.lastAssistantText));\n }\n\n // Tier 3: UX guards\n if (config.costWarning !== false) {\n results.push(guardCostWarning(tool, call, conversationContext.fullText));\n }\n\n // Process results — first block wins, collect all hints/warnings\n const events: GuardEvent[] = results\n .filter((r) => r.verdict !== 'pass')\n .map((r) => ({\n timestamp: now,\n toolName: tool.name,\n toolUseId: call.id,\n gate: r.gate,\n verdict: r.verdict,\n tier: r.tier,\n message: r.message,\n }));\n\n const block = results.find((r) => r.verdict === 'block');\n if (block) {\n // Fire once for the block winner; non-blocking warnings/hints from\n // earlier in the chain are surfaced too so the host sees the full\n // picture per turn.\n for (const r of results) {\n if (r.verdict === 'pass') continue;\n fire(r.verdict, r.tier, r.gate, false);\n }\n return {\n blocked: true,\n blockReason: block.message ?? `Blocked by ${block.gate}`,\n blockGate: block.gate,\n injections: [],\n events,\n };\n }\n\n const injections: GuardInjection[] = results\n .filter((r) => r.verdict === 'hint' || r.verdict === 'warn')\n .map((r) => ({\n _gate: r.gate,\n ...(r.verdict === 'hint' ? { _hint: r.message } : { _warning: r.message }),\n }));\n\n for (const r of results) {\n if (r.verdict === 'pass') continue;\n fire(r.verdict, r.tier, r.gate, r.verdict === 'hint' || r.verdict === 'warn');\n }\n\n return { blocked: false, injections, events };\n}\n\n// ---------------------------------------------------------------------------\n// Post-execution hooks — update tracker state after tools run\n// ---------------------------------------------------------------------------\n\nexport function updateGuardStateAfterToolResult(\n toolName: string,\n tool: Tool | undefined,\n input: unknown,\n result: unknown,\n isError: boolean,\n state: GuardRunnerState,\n): void {\n if (isError) return;\n\n if (BALANCE_READ_TOOLS.has(toolName)) {\n state.balanceTracker.recordRead();\n }\n\n if (tool?.flags.mutating) {\n state.balanceTracker.recordWrite();\n }\n\n if (toolName === 'health_check' && result && typeof result === 'object') {\n const r = result as Record<string, unknown>;\n const hf = Number(r.healthFactor ?? r.health_factor ?? r.hf);\n if (!isNaN(hf) && hf > 0) {\n state.lastHealthFactor = hf;\n }\n }\n\n // Record successful swap_quote calls so guardSwapPreview can verify a\n // matching quote ran before swap_execute. We key off the *input* (not\n // the result) so the LLM can use the same params for both calls and\n // the match is unambiguous.\n if (toolName === 'swap_quote' && input && typeof input === 'object') {\n const i = input as { from?: unknown; to?: unknown; amount?: unknown };\n const from = typeof i.from === 'string' ? i.from : '';\n const to = typeof i.to === 'string' ? i.to : '';\n const amount = Number(i.amount ?? 0);\n if (from && to && amount > 0) {\n state.swapQuoteTracker.record({ from, to, amount });\n }\n }\n\n state.retryTracker.record(toolName, input, result);\n}\n\n// ---------------------------------------------------------------------------\n// Conversation text extraction (for guard context)\n// ---------------------------------------------------------------------------\n\nexport function extractConversationText(\n messages: Array<{ role: string; content: unknown }>,\n): { fullText: string; lastAssistantText: string; recentUserText: string } {\n const textParts: string[] = [];\n const userParts: string[] = [];\n let lastAssistantText = '';\n\n for (const msg of messages) {\n if (!Array.isArray(msg.content)) continue;\n for (const block of msg.content as Array<Record<string, unknown>>) {\n if (block.type === 'text' && typeof block.text === 'string') {\n textParts.push(block.text);\n if (msg.role === 'assistant') {\n lastAssistantText = block.text;\n } else if (msg.role === 'user') {\n userParts.push(block.text);\n }\n }\n }\n }\n\n // Only the most recent ~10 user turns are considered an authoritative\n // source for `guardAddressSource`. Older addresses fall out of the\n // window so a user can't accidentally re-use a stale address from\n // 50 messages ago without re-pasting it.\n const RECENT_USER_TURN_WINDOW = 10;\n const recentUserParts = userParts.slice(-RECENT_USER_TURN_WINDOW);\n\n // [security] Cap each returned string at ~16KB before guards run any\n // regex over them. A few of the heuristic regexes downstream (e.g.\n // `/preview|...|confirm.*send|.../`, `/[\\d,]+\\.?\\d*\\s*(SUI|USDC|...)/`)\n // backtrack super-linearly on degenerate inputs — bounding the input\n // here keeps CodeQL's polynomial-regex alert at bay AND removes the\n // theoretical ReDoS surface from a maliciously crafted long message.\n // 16KB is comfortably larger than any realistic conversation slice we\n // need for the heuristic checks (which only look for keywords/numbers).\n const MAX_REGEX_INPUT = 16 * 1024;\n const cap = (s: string): string =>\n s.length <= MAX_REGEX_INPUT ? s : s.slice(-MAX_REGEX_INPUT);\n\n return {\n fullText: cap(textParts.join('\\n')),\n lastAssistantText: cap(lastAssistantText),\n recentUserText: cap(recentUserParts.join('\\n')),\n };\n}\n","import type { Message, ContentBlock, Tool } from '../types.js';\n\n/**\n * [v1.4 Item 4] Side-channel return from `microcompact` so callers can\n * count or surface dedup hits without re-walking the message ledger.\n * Backwards-compatible: `microcompact(messages)` still returns the\n * processed `Message[]` (now enriched), and the dedup set lives on the\n * returned array via a non-enumerable `dedupedToolUseIds` accessor that\n * the engine reads in its agent loop.\n */\nexport interface MicrocompactResult extends Array<Message> {\n /**\n * Tool-use IDs whose prior results were replaced with a compact\n * back-reference during this pass. Empty when nothing matched.\n */\n dedupedToolUseIds: Set<string>;\n}\n\n/**\n * Zero-cost deduplication pass: if the same tool was called with identical\n * inputs earlier in the conversation and the result hasn't changed, replace\n * the full prior result with a compact back-reference. Runs before any\n * LLM-based compaction and costs nothing.\n *\n * [v1.5.1] Tools may opt out of dedupe by setting `cacheable: false` on\n * their `Tool` definition. Non-cacheable tools (e.g. `balance_check`,\n * `savings_info`, `health_check`, `transaction_history`) are excluded\n * from the `seen` map entirely, so neither the current call nor any\n * later call with identical inputs gets replaced — necessary because\n * their results depend on mutable on-chain state that writes invalidate.\n *\n * Returns a new array — does not mutate the input. The returned array\n * carries a `dedupedToolUseIds` property listing every tool-use ID whose\n * tool_result block was replaced with a back-reference this pass.\n *\n * @param messages — conversation ledger to compact.\n * @param tools — optional tool registry consulted to resolve the\n * per-tool `cacheable` flag. Omit to dedupe every\n * tool (legacy behavior — back-compat).\n */\nexport function microcompact(\n messages: readonly Message[],\n tools?: readonly Tool[],\n): MicrocompactResult {\n const seen = new Map<string, { turnIndex: number }>();\n let toolUseIndex = 0;\n\n const toolUseInputs = new Map<string, string>();\n // Map tool name → cacheable flag. Default behavior (no entry, or\n // `cacheable === undefined`) is `true` — back-compat with hosts that\n // don't pass a tools array.\n const cacheableByName = new Map<string, boolean>();\n if (tools) {\n for (const t of tools) {\n cacheableByName.set(t.name, t.cacheable ?? true);\n }\n }\n const dedupedToolUseIds = new Set<string>();\n\n // Resolve tool name from a tool_use_id — cached lookup so each result\n // pass stays linear.\n const toolNameById = new Map<string, string>();\n\n for (const msg of messages) {\n for (const block of msg.content) {\n if (block.type === 'tool_use') {\n toolUseInputs.set(block.id, `${block.name}:${stableStringify(block.input)}`);\n toolNameById.set(block.id, block.name);\n }\n }\n }\n\n const out = messages.map((msg) => {\n if (msg.role !== 'user') return { role: msg.role, content: [...msg.content] };\n\n const hasToolResults = msg.content.some((b) => b.type === 'tool_result');\n if (!hasToolResults) return { role: msg.role, content: [...msg.content] };\n\n const newContent: ContentBlock[] = msg.content.map((block) => {\n if (block.type !== 'tool_result') return block;\n\n const key = toolUseInputs.get(block.toolUseId);\n if (!key) return block;\n\n // [v1.5.1] Skip dedupe entirely for tools whose results depend on\n // mutable state. Don't write to `seen` either — otherwise a later\n // *cacheable* call with the same key would erroneously dedupe\n // against this fresh result.\n const toolName = toolNameById.get(block.toolUseId);\n if (toolName && cacheableByName.get(toolName) === false) {\n toolUseIndex++;\n return block;\n }\n\n toolUseIndex++;\n const prior = seen.get(key);\n\n if (prior && !block.isError) {\n dedupedToolUseIds.add(block.toolUseId);\n return {\n ...block,\n content: `[Same result as call #${prior.turnIndex} — ${key.split(':')[0]} with identical inputs. Result unchanged.]`,\n };\n }\n\n if (!block.isError) {\n seen.set(key, { turnIndex: toolUseIndex });\n }\n return block;\n });\n\n return { role: msg.role, content: newContent };\n });\n\n // Attach the side-channel without breaking `Message[]` consumers — the\n // result is structurally compatible with `Message[]`, the extra property\n // is invisible to anything that only reads array semantics or runs deep\n // equality against a plain `Message[]` (vitest, JSON.stringify, …).\n Object.defineProperty(out, 'dedupedToolUseIds', {\n value: dedupedToolUseIds,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n return out as MicrocompactResult;\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return JSON.stringify(value);\n const sorted = Object.keys(value as Record<string, unknown>).sort();\n const obj: Record<string, unknown> = {};\n for (const k of sorted) obj[k] = (value as Record<string, unknown>)[k];\n return JSON.stringify(obj);\n}\n","import type { Message, ContentBlock } from './types.js';\nimport { microcompact } from './compact/microcompact.js';\n\n// Rough token estimation: ~4 chars per token (conservative for English + JSON)\nconst CHARS_PER_TOKEN = 4;\n\n// Default context window for Sonnet 4.6\nconst DEFAULT_CONTEXT_LIMIT = 200_000;\n\n// ---------------------------------------------------------------------------\n// Token estimation\n// ---------------------------------------------------------------------------\n\n/** Rough token count for a message array. */\nexport function estimateTokens(messages: Message[]): number {\n let chars = 0;\n for (const msg of messages) {\n for (const block of msg.content) {\n chars += blockCharCount(block);\n }\n }\n return Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nfunction blockCharCount(block: ContentBlock): number {\n switch (block.type) {\n case 'text':\n return block.text.length;\n case 'thinking':\n return block.thinking.length;\n case 'redacted_thinking':\n return block.data.length;\n case 'tool_use':\n return block.name.length + JSON.stringify(block.input).length;\n case 'tool_result':\n return block.content.length;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message compaction\n// ---------------------------------------------------------------------------\n\nexport interface CompactOptions {\n /** Max token budget for the conversation. Default 100_000. */\n maxTokens?: number;\n /** Number of recent messages to always keep uncompacted. Default 8. */\n keepRecentCount?: number;\n /** System prompt token estimate (subtracted from budget). Default 500. */\n systemPromptTokens?: number;\n /** LLM-based summarizer for old turns. When provided, replaces old turns with a summary. */\n summarizer?: (messages: Message[]) => Promise<string>;\n}\n\n// ---------------------------------------------------------------------------\n// ContextBudget — tracks cumulative token usage and signals compaction\n// ---------------------------------------------------------------------------\n\nexport interface ContextBudgetConfig {\n /** Total context window size in tokens. Default 200_000 (Sonnet 4.6). */\n contextLimit?: number;\n /** Trigger compaction at this fraction of contextLimit. Default 0.85. */\n compactThreshold?: number;\n /** Emit a warning at this fraction of contextLimit. Default 0.70. */\n warnThreshold?: number;\n}\n\nexport class ContextBudget {\n private estimatedTokens = 0;\n private readonly contextLimit: number;\n private readonly compactThreshold: number;\n private readonly warnThreshold: number;\n\n constructor(config: ContextBudgetConfig = {}) {\n this.contextLimit = config.contextLimit ?? DEFAULT_CONTEXT_LIMIT;\n this.compactThreshold = config.compactThreshold ?? 0.85;\n this.warnThreshold = config.warnThreshold ?? 0.70;\n }\n\n /** Update with actual input_tokens from the API usage event. */\n update(inputTokens: number): void {\n this.estimatedTokens = inputTokens;\n }\n\n /** True when the session should be compacted (at 85% of context limit). */\n shouldCompact(): boolean {\n return this.estimatedTokens >= this.contextLimit * this.compactThreshold;\n }\n\n /** True when nearing the limit (at 70% of context limit). */\n shouldWarn(): boolean {\n return this.estimatedTokens >= this.contextLimit * this.warnThreshold;\n }\n\n /** Current token count. */\n get tokens(): number {\n return this.estimatedTokens;\n }\n\n /** Remaining tokens before compaction triggers. */\n get remaining(): number {\n return Math.max(0, Math.floor(this.contextLimit * this.compactThreshold) - this.estimatedTokens);\n }\n\n /** Usage ratio (0..1). */\n get usage(): number {\n return this.estimatedTokens / this.contextLimit;\n }\n\n reset(): void {\n this.estimatedTokens = 0;\n }\n}\n\n/**\n * Compact a conversation that exceeds the token budget.\n *\n * Strategy:\n * 1. Always preserve the most recent `keepRecentCount` messages (the active context).\n * 2. If an LLM `summarizer` is provided, summarize old turns into a brief recap and\n * replace them with a synthetic summary turn pair.\n * 3. For older messages, summarise tool_result content to a brief one-liner.\n * 4. If still over budget, drop the oldest messages (keeping the first user message\n * for context continuity).\n *\n * Returns a new array — does not mutate the input.\n */\nexport async function compactMessages(\n messages: readonly Message[],\n opts: CompactOptions = {},\n): Promise<Message[]> {\n const maxTokens = opts.maxTokens ?? 100_000;\n const keepRecent = opts.keepRecentCount ?? 8;\n const systemTokens = opts.systemPromptTokens ?? 500;\n const budget = maxTokens - systemTokens;\n\n if (messages.length === 0) return [];\n\n // Phase -1: zero-cost deduplication of identical tool calls\n const deduped = microcompact(messages);\n\n const mutable = deduped.map((m) => ({\n role: m.role,\n content: m.content.map((b) => ({ ...b })),\n })) as Message[];\n\n if (estimateTokens(mutable) <= budget) return mutable;\n\n const splitIdx = Math.max(0, mutable.length - keepRecent);\n const oldMessages = mutable.slice(0, splitIdx);\n const recent = mutable.slice(splitIdx);\n\n // Phase 0: If summarizer is provided, try LLM-based summarization of old turns\n if (opts.summarizer && oldMessages.length > 0) {\n const strippedOld = stripThinkingBlocks(oldMessages);\n try {\n const summary = await opts.summarizer(strippedOld);\n const summaryMessages: Message[] = [\n { role: 'user', content: [{ type: 'text', text: `[Session summary: ${summary}]` }] },\n { role: 'assistant', content: [{ type: 'text', text: 'Understood. I have the context from our earlier conversation.' }] },\n ];\n const withSummary = [...summaryMessages, ...recent];\n if (estimateTokens(withSummary) <= budget) return sanitizeMessages(withSummary);\n } catch {\n // Summarizer failed — fall through to truncation strategy\n }\n }\n\n // Phase 1: summarise tool_result blocks in older messages\n for (let i = 0; i < splitIdx; i++) {\n mutable[i].content = mutable[i].content.map((block) => {\n if (block.type === 'tool_result' && block.content.length > 200) {\n return {\n ...block,\n content: truncateToolResult(block.content),\n };\n }\n return block;\n });\n }\n\n // Strip thinking blocks from old messages (they don't aid context continuity)\n for (let i = 0; i < splitIdx; i++) {\n mutable[i].content = mutable[i].content.filter(\n (b) => b.type !== 'thinking' && b.type !== 'redacted_thinking',\n );\n }\n\n if (estimateTokens(mutable) <= budget) return mutable;\n\n // Phase 2: drop old messages from the middle, keep first + recent\n if (splitIdx <= 1) {\n // All messages are recent (or only the first message is \"old\") — skip middle-drop\n return sanitizeMessages(mutable);\n }\n\n const first = mutable[0];\n const recentFromMutable = mutable.slice(splitIdx);\n const oldSection = mutable.slice(1, splitIdx);\n\n while (oldSection.length > 0 && estimateTokens([first, ...oldSection, ...recentFromMutable]) > budget) {\n oldSection.shift();\n }\n\n const compacted = [first, ...oldSection, ...recentFromMutable];\n\n // Phase 3: if still over budget (very long recent section), truncate tool results in recent\n if (estimateTokens(compacted) > budget) {\n for (const msg of compacted) {\n msg.content = msg.content.map((block) => {\n if (block.type === 'tool_result' && block.content.length > 100) {\n return { ...block, content: truncateToolResult(block.content) };\n }\n return block;\n });\n }\n }\n\n return sanitizeMessages(compacted);\n}\n\n/**\n * Strip thinking and redacted_thinking blocks from messages.\n * Used before summarization — thinking blocks don't help the summarizer.\n */\nfunction stripThinkingBlocks(messages: Message[]): Message[] {\n return messages.map((m) => ({\n ...m,\n content: m.content.filter(\n (b) => b.type !== 'thinking' && b.type !== 'redacted_thinking',\n ),\n })).filter((m) => m.content.length > 0);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Remove orphaned tool_use / tool_result blocks that lost their pair\n * during compaction. Anthropic requires every tool_result to match a\n * preceding tool_use and vice versa.\n */\nfunction sanitizeMessages(messages: Message[]): Message[] {\n const toolUseIds = new Set<string>();\n const toolResultIds = new Set<string>();\n\n for (const msg of messages) {\n for (const block of msg.content) {\n if (block.type === 'tool_use') toolUseIds.add(block.id);\n if (block.type === 'tool_result') toolResultIds.add(block.toolUseId);\n }\n }\n\n return messages\n .map((msg) => {\n const filtered = msg.content.filter((block) => {\n if (block.type === 'tool_result') return toolUseIds.has(block.toolUseId);\n if (block.type === 'tool_use') return toolResultIds.has(block.id);\n return true;\n });\n if (filtered.length === 0) return null;\n return { ...msg, content: filtered };\n })\n .filter((m): m is Message => m !== null);\n}\n\nfunction truncateToolResult(content: string): string {\n try {\n const parsed = JSON.parse(content);\n\n if (parsed.error) {\n return JSON.stringify({ error: parsed.error });\n }\n\n // Keep just the top-level keys with truncated values\n if (typeof parsed === 'object' && parsed !== null) {\n const summary: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n summary[key] = value;\n } else if (typeof value === 'string') {\n summary[key] = value.length > 50 ? value.slice(0, 50) + '…' : value;\n } else if (Array.isArray(value)) {\n summary[key] = `[${value.length} items]`;\n } else {\n summary[key] = '{…}';\n }\n }\n return JSON.stringify(summary);\n }\n\n return content.slice(0, 100);\n } catch {\n return content.slice(0, 100);\n }\n}\n","/**\n * USD-aware permission resolution for write tools.\n *\n * Replaces the binary auto/confirm/explicit system with dollar-threshold\n * tiers that resolve at runtime based on the transaction value and\n * per-user configuration.\n */\n\nexport type PermissionOperation =\n | 'save'\n | 'withdraw'\n | 'send'\n | 'borrow'\n | 'repay'\n | 'swap'\n | 'pay';\n\nexport interface PermissionRule {\n operation: PermissionOperation;\n /** Auto-execute if USD amount is below this threshold. */\n autoBelow: number;\n /** Confirm if between autoBelow and this. Explicit for anything above. */\n confirmBetween: number;\n}\n\nexport interface UserPermissionConfig {\n rules: PermissionRule[];\n /** Fallback auto threshold for operations without a specific rule. */\n globalAutoBelow: number;\n /** Max total USD of autonomous actions per day (safety net). */\n autonomousDailyLimit: number;\n}\n\nexport const DEFAULT_PERMISSION_CONFIG: UserPermissionConfig = {\n globalAutoBelow: 10,\n autonomousDailyLimit: 200,\n rules: [\n { operation: 'save', autoBelow: 50, confirmBetween: 1000 },\n { operation: 'send', autoBelow: 10, confirmBetween: 200 },\n { operation: 'borrow', autoBelow: 0, confirmBetween: 500 },\n { operation: 'withdraw', autoBelow: 25, confirmBetween: 500 },\n { operation: 'swap', autoBelow: 25, confirmBetween: 300 },\n { operation: 'pay', autoBelow: 1, confirmBetween: 50 },\n { operation: 'repay', autoBelow: 50, confirmBetween: 1000 },\n ],\n};\n\nexport const PERMISSION_PRESETS = {\n conservative: {\n globalAutoBelow: 5,\n autonomousDailyLimit: 100,\n rules: [\n { operation: 'save' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'send' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'borrow' as const, autoBelow: 0, confirmBetween: 100 },\n { operation: 'withdraw' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'swap' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'pay' as const, autoBelow: 1, confirmBetween: 25 },\n { operation: 'repay' as const, autoBelow: 5, confirmBetween: 100 },\n ],\n },\n balanced: DEFAULT_PERMISSION_CONFIG,\n aggressive: {\n globalAutoBelow: 25,\n autonomousDailyLimit: 500,\n rules: [\n { operation: 'save' as const, autoBelow: 100, confirmBetween: 2000 },\n { operation: 'send' as const, autoBelow: 25, confirmBetween: 500 },\n { operation: 'borrow' as const, autoBelow: 10, confirmBetween: 1000 },\n { operation: 'withdraw' as const, autoBelow: 50, confirmBetween: 1000 },\n { operation: 'swap' as const, autoBelow: 50, confirmBetween: 500 },\n { operation: 'pay' as const, autoBelow: 5, confirmBetween: 100 },\n { operation: 'repay' as const, autoBelow: 100, confirmBetween: 2000 },\n ],\n },\n} satisfies Record<string, UserPermissionConfig>;\n\n/**\n * True when `to` matches a saved contact's address (case-insensitive,\n * normalized). Used by `resolvePermissionTier` to enforce the\n * \"first-send to a new raw address always confirms\" rule and to keep\n * the engine + client in sync.\n */\nexport function isKnownContactAddress(\n to: string,\n contacts: ReadonlyArray<{ address: string }>,\n): boolean {\n if (!to) return false;\n const normalized = to.trim().toLowerCase();\n return contacts.some((c) => c.address.trim().toLowerCase() === normalized);\n}\n\n/**\n * Resolve the permission tier for a given operation + USD value.\n *\n * [v1.4] When `sessionSpendUsd` is supplied and adding the incoming\n * `amountUsd` would push cumulative session spend over\n * `config.autonomousDailyLimit`, an otherwise-`auto` tier is downgraded to\n * `confirm`. This is the runtime guard for the daily autonomous spend cap.\n * Tiers above `auto` are returned unchanged.\n *\n * Send-safety rule: when `operation === 'send'` and the destination\n * address is a raw `0x...` (i.e. NOT one of the user's saved contacts),\n * an otherwise-`auto` tier is downgraded to `confirm` regardless of\n * amount. This bounds the \"LLM/user typo silently ships funds\" failure\n * mode to a single confirmation per recipient — once saved as a contact,\n * subsequent sends to the same address auto-approve under tier as normal.\n */\nexport function resolvePermissionTier(\n operation: string,\n amountUsd: number,\n config: UserPermissionConfig,\n sessionSpendUsd?: number,\n sendContext?: {\n to?: string;\n contacts?: ReadonlyArray<{ address: string }>;\n },\n): 'auto' | 'confirm' | 'explicit' {\n const rule = config.rules.find((r) => r.operation === operation);\n const autoBelow = rule?.autoBelow ?? config.globalAutoBelow;\n const confirmBetween = rule?.confirmBetween ?? 1000;\n\n let tier: 'auto' | 'confirm' | 'explicit';\n if (amountUsd < autoBelow) tier = 'auto';\n else if (amountUsd < confirmBetween) tier = 'confirm';\n else tier = 'explicit';\n\n if (\n tier === 'auto' &&\n typeof sessionSpendUsd === 'number' &&\n sessionSpendUsd + amountUsd > config.autonomousDailyLimit\n ) {\n tier = 'confirm';\n }\n\n // Send-safety: a *raw* 0x recipient that doesn't match a saved\n // contact forces confirm. Contact names (e.g. `to: \"wallet1\"`) are\n // already trusted — the user explicitly saved that contact — and get\n // resolved to addresses downstream by `effects.resolveContact`. Without\n // the `0x` guard, a contact-name send was incorrectly demoted to\n // confirm because `isKnownContactAddress(\"wallet1\", contacts)` compares\n // the name against contact *addresses* and returns false.\n if (\n tier === 'auto' &&\n operation === 'send' &&\n sendContext?.to &&\n sendContext.to.startsWith('0x') &&\n !isKnownContactAddress(sendContext.to, sendContext.contacts ?? [])\n ) {\n tier = 'confirm';\n }\n\n return tier;\n}\n\nconst TOOL_TO_OPERATION: Record<string, PermissionOperation> = {\n save_deposit: 'save',\n withdraw: 'withdraw',\n send_transfer: 'send',\n borrow: 'borrow',\n repay_debt: 'repay',\n swap_execute: 'swap',\n pay_api: 'pay',\n volo_stake: 'save',\n volo_unstake: 'withdraw',\n};\n\nexport function toolNameToOperation(toolName: string): PermissionOperation | undefined {\n return TOOL_TO_OPERATION[toolName];\n}\n\n/**\n * Resolve the USD value of a tool call from its inputs.\n * USDC-denominated tools return 1:1. Others multiply by the price cache.\n */\nexport function resolveUsdValue(\n toolName: string,\n input: Record<string, unknown>,\n priceCache: Map<string, number>,\n): number {\n switch (toolName) {\n case 'save_deposit':\n case 'withdraw':\n case 'repay_debt':\n case 'borrow':\n return safeNum(input.amount);\n\n case 'send_transfer': {\n const amount = safeNum(input.amount);\n const asset = String(input.asset ?? 'USDC').toUpperCase();\n if (asset === 'USDC' || asset === 'USDT') return amount;\n return amount * (priceCache.get(asset) ?? 0);\n }\n\n case 'swap_execute': {\n const amount = safeNum(input.fromAmount);\n const fromAsset = String(input.fromAsset ?? '').toUpperCase();\n if (fromAsset === 'USDC' || fromAsset === 'USDT') return amount;\n return amount * (priceCache.get(fromAsset) ?? 0);\n }\n\n case 'pay_api':\n return safeNum(input.maxCost ?? input.price);\n\n case 'volo_stake':\n case 'volo_unstake':\n return safeNum(input.amount) * (priceCache.get('SUI') ?? 0);\n\n default:\n return 0;\n }\n}\n\nfunction safeNum(v: unknown): number {\n const n = Number(v);\n return isNaN(n) ? 0 : n;\n}\n","/**\n * [v0.46.8] Intra-turn deduplication of read-only tool calls.\n *\n * # Problem\n * Two independent execution paths can call the same read-only tool within\n * the same user turn:\n * 1. Host pre-dispatch via `engine.invokeReadTool()` (deterministic — runs\n * before the LLM ever sees the message; injects a synthetic\n * `tool_use`+`tool_result` pair into the ledger so the card renders\n * immediately and the LLM has the data).\n * 2. The LLM itself, mid-turn, emitting a `tool_use` block for the same\n * tool (often because the prompt says \"always call balance_check on\n * direct read questions\" and the model doesn't trust the synthetic\n * pair).\n *\n * Both paths emit a `tool_result` SSE event, the host renders BOTH cards,\n * the user sees a duplicate. Coordinating these two paths via prompt rules\n * is probabilistic (\"DO NOT re-call when you see a synthetic pair\") and\n * has empirically shown ~30% miss rate — the LLM still re-calls anyway.\n *\n * # Fix\n * Idempotent intra-turn cache. Within one user turn:\n * - Calling the same read-only tool with the same args twice returns the\n * cached result on the second call.\n * - The second call yields a `tool_result` event with `resultDeduped:true`\n * so hosts can skip rendering a duplicate card while the LLM still gets\n * the data it needs to satisfy its `tool_use` id.\n *\n * # Lifecycle\n * - Cache lives on the `QueryEngine` instance.\n * - Populated by `invokeReadTool` (host pre-dispatch) AND by the agent\n * loop's tool-execution path (LLM-driven calls).\n * - Cleared on `turn_complete` (clean slate for the next user turn).\n * - Cleared whenever a WRITE tool executes successfully (writes mutate\n * on-chain state, so any subsequent read in the same turn must re-fetch\n * for freshness).\n * - Cleared on errors / abort (defensive cleanup).\n *\n * # Why not just extend microcompact?\n * `microcompact` does CROSS-turn dedup, but explicitly excludes\n * `cacheable: false` tools (balance_check, health_check, savings_info,\n * transaction_history) so post-write refreshes always surface fresh data.\n * Within a single turn (pre-write), those same tools are perfectly\n * dedup-able — state can't change. This cache fills that exact gap.\n *\n * # Invariants\n * - Read-only tools only. Write tools never enter the cache.\n * - Errored results are NEVER cached (the next call should retry).\n * - Cache key includes the full input, stably stringified — different\n * filter args (e.g. `transaction_history({minUsd:5})` vs\n * `transaction_history({})`) hit different cache entries.\n */\nexport class TurnReadCache {\n private readonly store = new Map<string, { result: unknown; sourceToolUseId: string }>();\n\n /**\n * Build the cache key for a (toolName, input) pair. Stable across object\n * key ordering so `{a:1,b:2}` and `{b:2,a:1}` map to the same entry.\n */\n static keyFor(toolName: string, input: unknown): string {\n return `${toolName}:${stableStringify(input)}`;\n }\n\n has(key: string): boolean {\n return this.store.has(key);\n }\n\n get(key: string): { result: unknown; sourceToolUseId: string } | undefined {\n return this.store.get(key);\n }\n\n /**\n * Populate the cache. Caller is responsible for ensuring the result was\n * a successful read (no errors). Overwrites any prior entry for the same\n * key — the most recent successful read wins, which is correct under our\n * \"writes invalidate the whole cache\" invariant.\n */\n set(key: string, value: { result: unknown; sourceToolUseId: string }): void {\n this.store.set(key, value);\n }\n\n /**\n * Drop every entry. Called at turn end and after every successful write.\n * Cheap and intentional — the cache is small (a handful of entries per\n * turn at most) and clearing is the correct response to any state mutation.\n */\n clear(): void {\n this.store.clear();\n }\n\n size(): number {\n return this.store.size;\n }\n}\n\n/**\n * Stable JSON.stringify — sorts object keys recursively so semantically\n * equal inputs produce equal cache keys. Mirrors the helper in\n * `compact/microcompact.ts` so dedup keys agree across both layers.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return JSON.stringify(value.map(stableStringifyForObject));\n return stableStringifyForObject(value);\n}\n\nfunction stableStringifyForObject(value: unknown): string {\n if (value === null || value === undefined) return JSON.stringify(value);\n if (typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) {\n return `[${value.map(stableStringifyForObject).join(',')}]`;\n }\n const sorted = Object.keys(value as Record<string, unknown>).sort();\n const parts = sorted.map(\n (k) => `${JSON.stringify(k)}:${stableStringifyForObject((value as Record<string, unknown>)[k])}`,\n );\n return `{${parts.join(',')}}`;\n}\n","/**\n * EarlyToolDispatcher — dispatches read-only tools mid-stream.\n *\n * When the LLM emits `tool_use_done` for a read-only tool, the dispatcher\n * fires it immediately in the background rather than waiting for the full\n * stream to finish. Results are collected in original call order after the\n * stream exits.\n *\n * Write tools are NOT dispatched — they go through the existing permission\n * gate and TxMutex flow.\n */\n\nimport type { EngineEvent, Tool, ToolContext } from './types.js';\nimport { findTool } from './tool.js';\nimport { budgetToolResult, withRetryStats, type PendingToolCall } from './orchestration.js';\nimport { TurnReadCache } from './turn-read-cache.js';\n\ninterface DispatchEntry {\n call: PendingToolCall;\n tool: Tool;\n promise: Promise<{ data: unknown; isError: boolean }>;\n /**\n * [v0.46.8] True when this entry was satisfied from the\n * `TurnReadCache` rather than a fresh tool execution. The\n * `collectResults` stream surfaces these as `resultDeduped: true` so\n * hosts can skip rendering a duplicate card while the LLM still gets\n * the data it needs to answer its `tool_use_id`.\n */\n deduped: boolean;\n /**\n * [SPEC 8 v0.5.1 B3.2] Per-tool HTTP retry counter. Reads back the\n * mutable `retryStats` ref the dispatcher attached to the tool's\n * context — undefined for cached/deduped entries (no fresh execution\n * happened, so no retries to surface).\n */\n readAttemptCount: () => number | undefined;\n}\n\nexport class EarlyToolDispatcher {\n private entries: DispatchEntry[] = [];\n private readonly tools: Tool[];\n private readonly context: ToolContext;\n private readonly turnReadCache: TurnReadCache | undefined;\n private abortController: AbortController;\n\n constructor(tools: Tool[], context: ToolContext, turnReadCache?: TurnReadCache) {\n this.tools = tools;\n this.context = context;\n this.turnReadCache = turnReadCache;\n this.abortController = new AbortController();\n }\n\n /**\n * Attempt to dispatch a tool call. Returns true if the tool was dispatched\n * (read-only + concurrency-safe), false if it should be queued for later.\n *\n * [v0.46.8] Cache-aware: if a `TurnReadCache` was supplied at\n * construction and a prior call this turn already produced a result\n * for the same `(toolName, input)`, the dispatcher returns true (the\n * call IS handled here, not queued for the post-stream loop) but\n * skips the tool execution entirely — `collectResults` will surface\n * the cached value with `resultDeduped: true`. On a cache miss for\n * a successful real execution, the result is written back to the\n * cache so any later call within the same turn dedups too.\n */\n tryDispatch(call: PendingToolCall): boolean {\n const tool = findTool(this.tools, call.name);\n if (!tool || !tool.isReadOnly || !tool.isConcurrencySafe) return false;\n\n if (this.turnReadCache) {\n const cacheKey = TurnReadCache.keyFor(call.name, call.input);\n const cached = this.turnReadCache.get(cacheKey);\n if (cached) {\n this.entries.push({\n call,\n tool,\n promise: Promise.resolve({ data: cached.result, isError: false }),\n deduped: true,\n readAttemptCount: () => undefined,\n });\n return true;\n }\n }\n\n // [SPEC 8 v0.5.1 B3.2] Per-tool retry counter — fresh ref per\n // dispatch so concurrent reads in the early-dispatch batch keep\n // their attempt counts isolated. The signal override on the child\n // context is preserved through the spread.\n const baseChildContext: ToolContext = { ...this.context, signal: this.abortController.signal };\n const { context: childContext, readAttemptCount } = withRetryStats(baseChildContext);\n const promise = executeTool(tool, call, childContext).then((result) => {\n // Populate the cache on a successful, non-cached execution so a\n // later identical call this turn dedups instead of re-running.\n if (!result.isError && this.turnReadCache) {\n const cacheKey = TurnReadCache.keyFor(call.name, call.input);\n this.turnReadCache.set(cacheKey, {\n result: result.data,\n sourceToolUseId: call.id,\n });\n }\n return result;\n });\n\n this.entries.push({ call, tool, promise, deduped: false, readAttemptCount });\n return true;\n }\n\n /** True if any tools have been dispatched. */\n hasPending(): boolean {\n return this.entries.length > 0;\n }\n\n /** List of call IDs that were early-dispatched. */\n dispatchedIds(): Set<string> {\n return new Set(this.entries.map((e) => e.call.id));\n }\n\n /**\n * Look up the original tool input by `tool_use_id`. Used by the engine to\n * feed `updateGuardStateAfterToolResult` (which needs the call input to\n * record swap_quote → swap_execute pairing, etc.) for tools that were\n * dispatched here instead of going through the normal post-stream loop.\n */\n getInputById(toolUseId: string): unknown | undefined {\n return this.entries.find((e) => e.call.id === toolUseId)?.call.input;\n }\n\n /**\n * Collect all results in original dispatch order.\n * Yields `tool_result` events as each promise resolves.\n */\n async *collectResults(): AsyncGenerator<EngineEvent> {\n for (const entry of this.entries) {\n try {\n const result = await entry.promise;\n const budgeted = result.isError\n ? result.data\n : budgetToolResult(result.data, entry.tool);\n\n const attemptCount = entry.readAttemptCount();\n yield {\n type: 'tool_result',\n toolName: entry.call.name,\n toolUseId: entry.call.id,\n result: budgeted,\n isError: result.isError,\n wasEarlyDispatched: true,\n ...(entry.deduped ? { resultDeduped: true } : {}),\n ...(attemptCount !== undefined ? { attemptCount } : {}),\n };\n } catch (err) {\n yield {\n type: 'tool_result',\n toolName: entry.call.name,\n toolUseId: entry.call.id,\n result: { error: err instanceof Error ? err.message : 'Tool execution failed' },\n isError: true,\n wasEarlyDispatched: true,\n };\n }\n }\n }\n\n /** Cancel all in-flight tool calls. */\n abort(): void {\n this.abortController.abort();\n }\n}\n\nasync function executeTool(\n tool: Tool,\n call: PendingToolCall,\n context: ToolContext,\n): Promise<{ data: unknown; isError: boolean }> {\n const parsed = tool.inputSchema.safeParse(call.input);\n if (!parsed.success) {\n return {\n data: { error: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(', ')}` },\n isError: true,\n };\n }\n\n const result = await tool.call(parsed.data, context);\n return { data: result.data, isError: false };\n}\n","/**\n * SPEC 7 v0.3 Quote-Refresh ReviewCard — per-tool result freshness budgets.\n *\n * When a Payment Stream `pending_action` is composed at T=0 from upstream\n * read results, the user may take 30–60s to read + tap APPROVE. By that\n * time some upstream results have drifted (Cetus quotes refresh in\n * ~30s; NAVI APYs change slower). The host renders a \"QUOTE Ns OLD\"\n * badge and pulses the REGENERATE button when `quoteAge >\n * bundleShortestTtl(...)` so the user is nudged toward a fresh\n * composition. The TTL is a UX hint — it does NOT gate correctness.\n * The actual safety net is Sui's on-chain dry-run + `minOut` reverts.\n *\n * **Why per-tool, not per-bundle.** A bundle that depends on `swap_quote`\n * (30s drift) AND `rates_info` (90s drift) inherits the SHORTEST member\n * TTL — that's the freshness ceiling we can promise. Mixing in a\n * stable-floor read like `balance_check` (120s) doesn't loosen the\n * ceiling; the user still cares about the 30s quote going stale.\n *\n * **Where this lives.** Engine emits `quoteAge` + `regenerateInput` on\n * the bundled `pending_action`; the host imports `bundleShortestTtl` to\n * decide when the regenerate button auto-pulses. Adding a new\n * re-runnable read tool: append it to `TOOL_TTL_MS` here AND ensure the\n * bundle composer's contributing-reads detector picks it up.\n */\nexport const TOOL_TTL_MS: Record<string, number> = {\n swap_quote: 30_000,\n rates_info: 90_000,\n balance_check: 120_000,\n portfolio_analysis: 120_000,\n savings_info: 120_000,\n health_check: 90_000,\n};\n\n/** Default TTL for read tools not in `TOOL_TTL_MS` (60s — conservative). */\nexport const DEFAULT_TOOL_TTL_MS = 60_000;\n\n/**\n * Resolve the shortest TTL among a set of tool_use_ids. Hosts call this\n * to decide when the regenerate button should auto-pulse.\n *\n * @param toolUseIds — the set of upstream read `tool_use` ids that fed\n * the bundle composition (what the engine stamps into\n * `PendingAction.regenerateInput.toolUseIds`).\n * @param toolNamesById — `tool_use_id` → `toolName` map, built by the\n * host from the same turn's tool_use blocks.\n * @returns The smallest TTL in milliseconds. Empty input returns\n * `DEFAULT_TOOL_TTL_MS`.\n */\nexport function bundleShortestTtl(\n toolUseIds: string[],\n toolNamesById: Record<string, string>,\n): number {\n if (toolUseIds.length === 0) return DEFAULT_TOOL_TTL_MS;\n let shortest = Number.POSITIVE_INFINITY;\n for (const id of toolUseIds) {\n const name = toolNamesById[id];\n const ttl: number = (name !== undefined ? TOOL_TTL_MS[name] : undefined) ?? DEFAULT_TOOL_TTL_MS;\n if (ttl < shortest) shortest = ttl;\n }\n return Number.isFinite(shortest) ? shortest : DEFAULT_TOOL_TTL_MS;\n}\n\n/** The set of read tools whose results re-fire on REGENERATE. */\nexport const REGENERATABLE_READ_TOOLS: ReadonlySet<string> = new Set([\n 'swap_quote',\n 'rates_info',\n 'balance_check',\n 'portfolio_analysis',\n 'savings_info',\n 'health_check',\n]);\n","/**\n * SPEC 7 v0.4 Layer 2 — bundle composition helper.\n *\n * When the LLM emits ≥2 `tool_use` blocks in a single assistant turn\n * AND every block resolves to a `confirm`-tier write tool with\n * `bundleable: true`, the permission gate collects them all into a\n * `pendingWrites: PendingToolCall[]` array (instead of breaking on the\n * first one). This helper takes that collected array plus the same-turn\n * read tool_use_ids and returns a `PendingAction` with `steps[]`\n * populated.\n *\n * **Single-write fast path.** When `pendingWrites.length === 1`, the\n * caller should NOT call this helper — emit the legacy single-write\n * `pending_action` shape directly. Bundles are N≥2 only; the legacy\n * shape stays unchanged for backward compatibility (SPEC 1 attemptId\n * resume keying continues to work without host migration).\n *\n * **Quote-Refresh fields (SPEC 7 v0.3).** The helper inspects the\n * pending writes' inputs for references to upstream read results\n * (`balance_check`, `swap_quote`, `rates_info`, etc.). When a step\n * input could plausibly have been derived from a read result (e.g. an\n * amount field whose numeric value matches a read result's exposed\n * amount), the helper marks the corresponding read tool_use_id as a\n * regenerate input. Conservative — false positives just enable the\n * REGENERATE button when it could've stayed off; never wrong-direction.\n *\n * **What this helper does NOT do.**\n * - Run guards (caller does that BEFORE calling here).\n * - Apply USD permission resolution (caller does it per-step BEFORE\n * calling here, to decide which writes get bundled).\n * - Compose the on-chain PTB (host does that via `composeTx({ steps })`\n * after the user approves).\n *\n * The helper is pure synchronous transformation: takes typed inputs,\n * returns a typed `PendingAction`.\n */\nimport { randomUUID } from 'node:crypto';\nimport { findTool } from './tool.js';\nimport { describeAction } from './describe-action.js';\nimport { getModifiableFields } from './tools/tool-modifiable-fields.js';\nimport { REGENERATABLE_READ_TOOLS } from './tool-ttls.js';\nimport type {\n ContentBlock,\n PendingAction,\n PendingActionStep,\n Tool,\n} from './types.js';\nimport type { PendingToolCall } from './orchestration.js';\n\nexport interface BundleCompositionInput {\n /** All confirm-tier bundleable writes the LLM emitted in this turn. MUST be ≥2. */\n pendingWrites: PendingToolCall[];\n /** Tools registered with the engine — for description + modifiableFields lookup. */\n tools: Tool[];\n /**\n * Same-turn earlier read tool_use ids + their results, in the order they\n * landed. The helper extracts `regenerateInput.toolUseIds` from this set\n * by intersecting it with the canonical regeneratable-read allow-list\n * (`REGENERATABLE_READ_TOOLS`).\n */\n readResults: Array<{\n toolUseId: string;\n toolName: string;\n timestamp: number;\n }>;\n /** Full assistant message blocks for the deferred turn (engine.ts uses this). */\n assistantContent: ContentBlock[];\n /** Already-resolved tool_result blocks (early-dispatched reads + auto writes). */\n completedResults: Array<{ toolUseId: string; content: string; isError: boolean }>;\n /** Per-write-call optional guard injections (already resolved, not re-run here). */\n guardInjectionsByCallId?: Record<string, Array<{ _gate: string; _hint?: string; _warning?: string }>>;\n /** Monotonic turn index — same value the legacy single-write path stamps. */\n turnIndex: number;\n}\n\n/**\n * Produce a bundled `PendingAction` from collected pending writes.\n * Caller MUST have already verified pendingWrites.length >= 2 and that\n * every entry's tool has `bundleable: true` + `permissionLevel: 'confirm'`.\n *\n * The helper additionally re-checks `bundleable: true` on each tool as a\n * defensive guard against caller bugs (cheap, catches future call sites\n * that misuse the helper).\n */\nexport function composeBundleFromToolResults(input: BundleCompositionInput): PendingAction {\n if (input.pendingWrites.length < 2) {\n throw new Error(\n 'composeBundleFromToolResults requires ≥2 pending writes; ' +\n 'use the legacy single-write path for N=1.',\n );\n }\n\n const steps: PendingActionStep[] = input.pendingWrites.map((call) => {\n const tool = findTool(input.tools, call.name);\n if (!tool) {\n throw new Error(`Unknown tool '${call.name}' in bundle composition`);\n }\n // [SPEC 7 P2.3 audit fix — BUG 13] Defensive check. The engine.ts\n // permission-gate already filters with\n // `every((w) => w.tool.flags?.bundleable === true)` before calling\n // this helper, but a future call site (CLI, server-task) could miss\n // it. Failing fast here catches the bug before producing a malformed\n // bundle that the host's `composeTx({ steps })` would reject downstream.\n if (tool.flags?.bundleable !== true) {\n throw new Error(\n `Tool '${call.name}' is not bundleable. Set ToolFlags.bundleable=true ` +\n 'in tool-flags.ts before including it in a bundle. ' +\n 'See SPEC 7 § \"Layer 2 — Bundleable tools (v1)\".',\n );\n }\n const description = describeAction(tool, call);\n const modifiableFields = getModifiableFields(call.name);\n return {\n toolName: call.name,\n toolUseId: call.id,\n attemptId: randomUUID(),\n input: call.input,\n description,\n ...(modifiableFields?.length ? { modifiableFields } : {}),\n };\n });\n\n // Regenerate-input tracking: any same-turn read tool_use_id that's in\n // the canonical re-runnable allow-list contributes to the bundle's\n // freshness. Conservative — we don't (yet) inspect step inputs to\n // confirm a reference; if a read landed earlier this turn AND it's in\n // REGENERATABLE_READ_TOOLS, we include it. False positives just\n // enable the REGENERATE button; they don't change correctness.\n const regenerateToolUseIds = input.readResults\n .filter((r) => REGENERATABLE_READ_TOOLS.has(r.toolName))\n .map((r) => r.toolUseId);\n\n const canRegenerate = regenerateToolUseIds.length > 0;\n\n // quoteAge = now − stalest contributing read timestamp. Min, not max:\n // we report the freshness of the WORST input (that's what gates UX).\n // [SPEC 7 P2.3 audit fix — BUG 12] Clamp to >= 0 against clock skew.\n // `Date.now()` is monotonic-ish but not guaranteed; if a read was\n // recorded a few ms in the future (NTP correction, VM clock drift),\n // a negative quoteAge would render as \"QUOTE -3s OLD\" in the UI.\n let quoteAge: number | undefined;\n if (regenerateToolUseIds.length > 0) {\n const stalest = Math.min(\n ...input.readResults\n .filter((r) => REGENERATABLE_READ_TOOLS.has(r.toolName))\n .map((r) => r.timestamp),\n );\n quoteAge = Math.max(0, Date.now() - stalest);\n }\n\n // Concatenated guard injections across every step. Hosts that don't\n // iterate `steps` see the union; hosts that do can re-derive per-step\n // by walking each step's toolUseId against this list (rare).\n const allGuardInjections: NonNullable<PendingAction['guardInjections']> = [];\n if (input.guardInjectionsByCallId) {\n for (const call of input.pendingWrites) {\n const injections = input.guardInjectionsByCallId[call.id];\n if (injections?.length) allGuardInjections.push(...injections);\n }\n }\n\n // Mirror the first step's identity into the legacy top-level fields\n // so pre-SPEC-7 hosts that don't iterate `steps` at least see the\n // first step's tool name + input. New hosts iterate `steps`. The\n // `description` mirrors the first step too — multi-step PermissionCard\n // hosts override this in the UI by walking steps[].description.\n //\n // [SPEC 7 P2.3 audit fix — BUG 2] Per spec line 463: \"`steps[0]`\n // mirrors the top-level toolName/toolUseId/input/attemptId for hosts\n // that haven't been updated\". Use steps[0].attemptId as the top-level\n // id (was: a fresh UUID, which broke the mirror invariant). Pre-bundle\n // hosts that key TurnMetrics rows on top-level `attemptId` now collide\n // with the bundle-aware host's step-0 row — both consistent. The\n // bundle has no separate \"bundle-as-a-whole\" attemptId; the resume\n // route's `updateMany({ where: { attemptId } })` keys still work\n // because they extend trivially to the per-step shape (loop\n // `stepResults`, update each row).\n const firstStep = steps[0];\n\n const action: PendingAction = {\n toolName: firstStep.toolName,\n toolUseId: firstStep.toolUseId,\n input: firstStep.input,\n description: firstStep.description,\n assistantContent: input.assistantContent,\n completedResults: input.completedResults,\n ...(allGuardInjections.length ? { guardInjections: allGuardInjections } : {}),\n turnIndex: input.turnIndex,\n attemptId: firstStep.attemptId,\n steps,\n canRegenerate,\n ...(quoteAge !== undefined ? { quoteAge } : {}),\n ...(regenerateToolUseIds.length > 0\n ? { regenerateInput: { toolUseIds: regenerateToolUseIds } }\n : {}),\n };\n\n return action;\n}\n","import type {\n EngineConfig,\n EngineEvent,\n HarnessShape,\n Message,\n ContentBlock,\n PendingAction,\n SystemPrompt,\n Tool,\n ToolContext,\n PermissionResponse,\n ProviderEvent,\n StopReason,\n} from './types.js';\nimport { toolsToDefinitions, findTool } from './tool.js';\nimport { TxMutex, runTools, withRetryStats, type PendingToolCall } from './orchestration.js';\nimport { getDefaultTools } from './tools/index.js';\nimport { getModifiableFields } from './tools/tool-modifiable-fields.js';\nimport { DEFAULT_SYSTEM_PROMPT } from './prompt.js';\nimport { clearPortfolioCacheFor } from './blockvision-prices.js';\nimport { getTelemetrySink } from './telemetry.js';\nimport { randomUUID } from 'node:crypto';\nimport { CostTracker, type CostSnapshot } from './cost.js';\nimport { describeAction } from './describe-action.js';\nimport { clampThinkingForEffort } from './thinking-budget.js';\nimport {\n type GuardConfig,\n type GuardRunnerState,\n type GuardEvent,\n createGuardRunnerState,\n runGuards,\n updateGuardStateAfterToolResult,\n extractConversationText,\n guardArtifactPreview,\n guardStaleData,\n} from './guards.js';\nimport type { RecipeRegistry, Recipe } from './recipes/index.js';\nimport { ContextBudget, compactMessages } from './context.js';\nimport { microcompact } from './compact/microcompact.js';\nimport { resolvePermissionTier, resolveUsdValue, toolNameToOperation } from './permission-rules.js';\nimport { EarlyToolDispatcher } from './early-dispatcher.js';\nimport { TurnReadCache } from './turn-read-cache.js';\nimport { composeBundleFromToolResults } from './compose-bundle.js';\n\nconst DEFAULT_MAX_TURNS = 10;\nconst DEFAULT_MAX_TOKENS = 4096;\n\ninterface TurnAccumulator {\n text: string;\n stopReason: StopReason;\n assistantBlocks: ContentBlock[];\n pendingToolCalls: PendingToolCall[];\n}\n\nexport class QueryEngine {\n private readonly provider: EngineConfig['provider'];\n private readonly tools: Tool[];\n private readonly systemPrompt: SystemPrompt;\n private readonly model: string | undefined;\n private readonly maxTurns: number;\n private readonly maxTokens: number;\n private readonly temperature: number | undefined;\n private readonly toolChoice: EngineConfig['toolChoice'];\n private readonly thinking: EngineConfig['thinking'];\n private readonly outputConfig: EngineConfig['outputConfig'];\n private readonly agent: unknown;\n private readonly mcpManager: unknown;\n private readonly walletAddress: string | undefined;\n private readonly suiRpcUrl: string | undefined;\n private serverPositions: EngineConfig['serverPositions'];\n private readonly positionFetcher: EngineConfig['positionFetcher'];\n private readonly env: Record<string, string> | undefined;\n private readonly txMutex = new TxMutex();\n private readonly costTracker: CostTracker;\n private readonly guardConfig: GuardConfig | undefined;\n private readonly guardState: GuardRunnerState;\n private readonly recipes: RecipeRegistry | undefined;\n private readonly contextBudget: ContextBudget;\n private readonly contextSummarizer: EngineConfig['contextSummarizer'];\n private readonly priceCache: Map<string, number> | undefined;\n private readonly permissionConfig: import('./permission-rules.js').UserPermissionConfig | undefined;\n // Saved contacts — consulted by `guardAddressSource` and the permission\n // tier resolver (sends to non-contact addresses always require confirm).\n private readonly contacts: ReadonlyArray<{ name: string; address: string }>;\n // [v1.4] Session-scoped autonomous spend tracking.\n private readonly sessionSpendUsd: number | undefined;\n private readonly onAutoExecuted: EngineConfig['onAutoExecuted'];\n private readonly onGuardFired: EngineConfig['onGuardFired'];\n // [v1.4 BlockVision] BlockVision Indexer API key + per-request portfolio\n // cache. Forwarded into every `ToolContext` build site so read tools\n // (`balance_check`, `portfolio_analysis`, future `token_prices`) hit the\n // shared host-paid endpoint and dedupe across each other within a turn.\n private readonly blockvisionApiKey: string | undefined;\n private readonly portfolioCache: EngineConfig['portfolioCache'];\n // [v1.5] See `EngineConfig.postWriteRefresh` — drives the post-write\n // synthetic read injection in `resumeWithToolResult`.\n private readonly postWriteRefresh: EngineConfig['postWriteRefresh'];\n private matchedRecipe: Recipe | null = null;\n\n private messages: Message[] = [];\n private abortController: AbortController | null = null;\n private guardEvents: GuardEvent[] = [];\n // [v0.46.8] Intra-turn dedup cache for read-only tool calls. See\n // `turn-read-cache.ts` for the full lifecycle. Key takeaway: the cache\n // lives across the host's pre-dispatch (`invokeReadTool`) and the\n // agent loop's LLM-driven tool execution within ONE user turn, then\n // clears on `turn_complete` or after any successful write.\n private readonly turnReadCache = new TurnReadCache();\n // [v0.46.8] Set to `true` when the agent loop yields `pending_action`\n // and returns (turn is paused awaiting user confirmation). The\n // submitMessage / resumeWithToolResult wrappers consult this flag in\n // their `finally` block so they DON'T clear the cache mid-turn — the\n // pending write may resume, and the cache should survive the pause.\n private turnPaused = false;\n\n constructor(config: EngineConfig) {\n this.provider = config.provider;\n this.agent = config.agent;\n this.mcpManager = config.mcpManager;\n this.walletAddress = config.walletAddress;\n this.suiRpcUrl = config.suiRpcUrl;\n this.serverPositions = config.serverPositions;\n this.positionFetcher = config.positionFetcher;\n this.env = config.env;\n this.model = config.model;\n this.maxTurns = config.maxTurns ?? DEFAULT_MAX_TURNS;\n this.maxTokens = config.maxTokens ?? DEFAULT_MAX_TOKENS;\n this.temperature = config.temperature;\n this.toolChoice = config.toolChoice;\n this.thinking = config.thinking;\n this.outputConfig = config.outputConfig;\n this.systemPrompt = config.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n this.costTracker = new CostTracker(config.costTracker);\n this.guardConfig = config.guards;\n this.guardState = createGuardRunnerState();\n this.recipes = config.recipes;\n this.contextBudget = new ContextBudget(config.contextBudget);\n this.contextSummarizer = config.contextSummarizer;\n this.priceCache = config.priceCache;\n this.permissionConfig = config.permissionConfig;\n this.contacts = config.contacts ?? [];\n this.sessionSpendUsd = config.sessionSpendUsd;\n this.onAutoExecuted = config.onAutoExecuted;\n this.onGuardFired = config.onGuardFired;\n this.postWriteRefresh = config.postWriteRefresh;\n this.blockvisionApiKey = config.blockvisionApiKey;\n this.portfolioCache = config.portfolioCache;\n\n this.tools = config.tools ?? (config.agent ? getDefaultTools() : []);\n }\n\n /**\n * Submit a user message and stream engine events.\n *\n * Read-only tools execute inline. Write tools that need confirmation yield a\n * `pending_action` event and the stream ends — no persistent connection needed.\n * The caller should save messages + pendingAction to the session store, then\n * call `resumeWithToolResult()` after the user approves/denies and executes.\n *\n * [SPEC 8 v0.5.1 B3.2] Optional `options.harnessShape` + `options.harnessRationale`\n * cause a one-shot `harness_shape` event to be yielded BEFORE the agent loop\n * begins. The engine itself doesn't classify — the host calls\n * `classifyEffort()` (host already does this for thinking-budget routing)\n * and maps via `harnessShapeForEffort()` before calling `submitMessage`.\n * Hosts that don't pass `harnessShape` won't see the event (existing\n * pre-SPEC-8 hosts continue to work; their `TurnMetrics.harnessShape`\n * defaults to `'legacy'`).\n */\n async *submitMessage(\n prompt: string,\n options?: {\n harnessShape?: HarnessShape;\n harnessRationale?: string;\n },\n ): AsyncGenerator<EngineEvent> {\n if (this.costTracker.isOverBudget()) {\n yield { type: 'error', error: new Error('Session budget exceeded') };\n return;\n }\n\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n\n // RE-3.1: Match recipe before pushing message\n this.matchedRecipe = this.recipes?.match(prompt) ?? null;\n\n this.messages.push({\n role: 'user',\n content: [{ type: 'text', text: prompt }],\n });\n\n // [SPEC 8 v0.5.1 B3.2] Emit the per-turn harness shape declaration\n // BEFORE agentLoop runs. Single emission per `submitMessage` call;\n // `resumeWithToolResult` does NOT re-emit (resume continues the same\n // turn under the same shape). Empty rationale falls back to the\n // shape name so dashboards always have non-null context.\n if (options?.harnessShape) {\n yield {\n type: 'harness_shape',\n shape: options.harnessShape,\n rationale:\n options.harnessRationale && options.harnessRationale.trim().length > 0\n ? options.harnessRationale\n : `host-classified ${options.harnessShape}`,\n };\n }\n\n // [v0.46.8] Reset the pause flag at turn start. Any cache entries\n // populated by the host's pre-dispatch (`invokeReadTool`) BEFORE\n // this call MUST survive into the agent loop so LLM-driven calls\n // for the same tools dedup. We do NOT clear the cache here.\n this.turnPaused = false;\n try {\n yield* this.agentLoop(prompt, signal);\n } finally {\n // Turn boundary cleanup: drop the cache so the next user turn\n // starts with a clean slate. Skip when the turn was paused via\n // `pending_action` — the cache must survive the pause so the\n // resumed turn (which is the SAME turn) keeps deduping.\n if (!this.turnPaused) {\n this.turnReadCache.clear();\n }\n }\n }\n\n /**\n * Resume the conversation after a pending action is resolved.\n * Called with the user's approval/denial and optional client-side execution result.\n *\n * This is a separate HTTP request — no persistent connection from submitMessage.\n */\n async *resumeWithToolResult(\n action: PendingAction,\n response: PermissionResponse,\n ): AsyncGenerator<EngineEvent> {\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n\n // [SPEC 7 P2.3 Layer 2] Bundle resume vs single-write resume.\n // - Bundle: action.steps is an array of N steps; response.stepResults\n // carries one outcome per step. We push N `tool_result` blocks back\n // into the conversation (one per step's tool_use_id) so the LLM has\n // complete context for the bundle's atomic outcome.\n // - Single-write (legacy): action.steps is undefined; response.executionResult\n // carries the singular outcome. Behavior unchanged from pre-P2.3.\n const isBundle = Array.isArray(action.steps) && action.steps.length > 0;\n\n // Build the write tool_result blocks (N for bundles, 1 for single-write).\n const writeResultBlocks: ContentBlock[] = [];\n if (isBundle) {\n const steps = action.steps!;\n const stepResults = response.stepResults ?? [];\n\n // Build a quick lookup so step ordering doesn't depend on host\n // ordering. Hosts that return stepResults in a different order\n // (or omit one) still produce correct LLM context.\n const resultByToolUseId = new Map(stepResults.map((r) => [r.toolUseId, r]));\n\n for (const step of steps) {\n if (response.approved) {\n const stepResult = resultByToolUseId.get(step.toolUseId);\n if (stepResult) {\n writeResultBlocks.push({\n type: 'tool_result',\n toolUseId: step.toolUseId,\n content: JSON.stringify(stepResult.result),\n isError: stepResult.isError,\n });\n } else {\n // [SPEC 7 P2.3 audit fix — BUG 11] Host approved the bundle\n // but didn't supply this step's result. Fail closed — treat\n // as an error so the LLM narrates \"this step's outcome is\n // unknown\" instead of fake-success. PTB execution is atomic\n // at the Sui layer, so an approved+missing-result is a host\n // bug; surfacing it to the LLM as an error is safer than\n // pretending success and locking the user into a bad state.\n writeResultBlocks.push({\n type: 'tool_result',\n toolUseId: step.toolUseId,\n content: JSON.stringify({\n error:\n 'Host omitted this step\\'s execution result. Treating ' +\n 'as failure — actual on-chain state is unknown. Re-check ' +\n 'wallet via balance_check before re-attempting.',\n _hostBugMissingStepResult: true,\n }),\n isError: true,\n });\n }\n } else {\n writeResultBlocks.push({\n type: 'tool_result',\n toolUseId: step.toolUseId,\n content: JSON.stringify({ error: 'User declined this action' }),\n isError: true,\n });\n }\n }\n } else {\n writeResultBlocks.push(\n response.approved\n ? {\n type: 'tool_result',\n toolUseId: action.toolUseId,\n content: JSON.stringify(response.executionResult ?? { success: true }),\n isError: false,\n }\n : {\n type: 'tool_result',\n toolUseId: action.toolUseId,\n content: JSON.stringify({ error: 'User declined this action' }),\n isError: true,\n },\n );\n }\n\n // Reconstruct the full turn atomically:\n // 1. Push the assistant message that was deferred during pending_action\n // 2. Push ALL tool_results (completed reads + writes) in one user message\n if (action.assistantContent?.length) {\n this.messages.push({ role: 'assistant', content: action.assistantContent });\n }\n\n const allResults: ContentBlock[] = [\n ...(action.completedResults ?? []).map((r) => ({\n type: 'tool_result' as const,\n toolUseId: r.toolUseId,\n content: r.content,\n isError: r.isError,\n })),\n ...writeResultBlocks,\n ];\n\n this.messages.push({ role: 'user', content: allResults });\n\n // Yield a `tool_result` event per write step (or single write for\n // legacy). Hosts use these to render per-step outcome rows in the\n // PermissionCard UI.\n if (isBundle) {\n const steps = action.steps!;\n const stepResults = response.stepResults ?? [];\n const resultByToolUseId = new Map(stepResults.map((r) => [r.toolUseId, r]));\n for (const step of steps) {\n const stepResult = resultByToolUseId.get(step.toolUseId);\n // [SPEC 7 P2.3 audit fix — BUG 11] When approved+missing-result,\n // mirror the writeResultBlocks fail-closed semantics on the event\n // stream: emit an error event so host UI flags the step as failed\n // (not pretend-success).\n let eventResult: unknown;\n let eventIsError: boolean;\n if (!response.approved) {\n eventResult = { error: 'User declined this action' };\n eventIsError = true;\n } else if (stepResult) {\n eventResult = stepResult.result;\n eventIsError = stepResult.isError;\n } else {\n eventResult = {\n error: 'Host omitted this step\\'s execution result.',\n _hostBugMissingStepResult: true,\n };\n eventIsError = true;\n }\n yield {\n type: 'tool_result',\n toolName: step.toolName,\n toolUseId: step.toolUseId,\n result: eventResult,\n isError: eventIsError,\n };\n }\n } else {\n yield {\n type: 'tool_result',\n toolName: action.toolName,\n toolUseId: action.toolUseId,\n result: response.approved\n ? (response.executionResult ?? { success: true })\n : { error: 'User declined this action' },\n isError: !response.approved,\n };\n }\n\n if (!response.approved) {\n yield { type: 'turn_complete', stopReason: 'end_turn' };\n // Turn ended (user declined) — drop the cache.\n this.turnReadCache.clear();\n return;\n }\n\n // [v0.46.8] A successful approved write MUTATES on-chain state, so\n // any read-tool result cached during the pre-pause portion of this\n // turn is now stale. Drop it before the post-write refresh fires —\n // refresh tools will re-execute and re-populate with fresh data.\n this.turnReadCache.clear();\n\n // [v1.5] Post-write refresh — eliminate the \"LLM invents a wallet\n // total in the post-write narration\" hallucination class by\n // physically injecting authoritative ground truth into the\n // conversation BEFORE the LLM gets to narrate. Tools are configured\n // per write via `EngineConfig.postWriteRefresh`. Errors are\n // non-fatal: we still advance to agentLoop so the user gets *some*\n // narration even if RPC blips.\n yield* this.runPostWriteRefresh(action, response, signal);\n\n // [v0.46.8] Reset the pause flag and wrap the resumed agentLoop in\n // try/finally for cache cleanup, mirroring submitMessage. The\n // post-write refresh above re-populated the cache with fresh\n // post-write reads; agentLoop may add more during follow-up tool\n // calls; finally clears it at turn end (skipping when paused).\n this.turnPaused = false;\n try {\n yield* this.agentLoop(null, signal, false);\n } finally {\n if (!this.turnPaused) {\n this.turnReadCache.clear();\n }\n }\n }\n\n /**\n * [v1.5] Auto-run configured read tools after a successful write,\n * push their results into the conversation, and yield `tool_result`\n * events so hosts/UI render them in the timeline. See\n * `EngineConfig.postWriteRefresh`.\n *\n * Pure injection — no LLM call here. The next `agentLoop` turn sees\n * the fresh tool results and narrates from them.\n */\n private async *runPostWriteRefresh(\n action: PendingAction,\n response: PermissionResponse,\n signal: AbortSignal,\n ): AsyncGenerator<EngineEvent> {\n // [SPEC 7 P2.3 Layer 2] Bundle-aware refresh.\n // - Bundle: union of refresh tools across every step's\n // `postWriteRefresh` entry, deduped (Set semantics).\n // - Single-write: per-tool list as before.\n const isBundle = Array.isArray(action.steps) && action.steps.length > 0;\n const refreshSet = new Set<string>();\n if (isBundle) {\n for (const step of action.steps!) {\n const stepRefresh = this.postWriteRefresh?.[step.toolName];\n if (stepRefresh) for (const t of stepRefresh) refreshSet.add(t);\n }\n } else {\n const singleRefresh = this.postWriteRefresh?.[action.toolName];\n if (singleRefresh) for (const t of singleRefresh) refreshSet.add(t);\n }\n if (refreshSet.size === 0) return;\n const refreshList = Array.from(refreshSet);\n\n // Refresh only on confirmed success. For bundles, treat as failed\n // when ANY step's stepResult.isError is true (atomic semantics —\n // PTB execution fails as a whole, so partial success is impossible\n // on-chain; if the host reports any step error we honor it).\n const writeFailed = (() => {\n if (isBundle) {\n const stepResults = response.stepResults ?? [];\n return stepResults.some((r) => r.isError);\n }\n const exec = response.executionResult;\n return (\n exec != null &&\n typeof exec === 'object' &&\n 'success' in exec &&\n (exec as { success?: unknown }).success === false\n );\n })();\n if (writeFailed) return;\n\n // Resolve & filter — silently drop unknown / non-readonly entries\n // so config drift between host & engine never breaks resume.\n const refreshTools = refreshList\n .map((name) => findTool(this.tools, name))\n .filter((t): t is Tool =>\n t !== undefined && t.isReadOnly && t.isConcurrencySafe,\n );\n if (refreshTools.length === 0) return;\n\n const context: ToolContext = {\n agent: this.agent,\n mcpManager: this.mcpManager,\n walletAddress: this.walletAddress,\n suiRpcUrl: this.suiRpcUrl,\n serverPositions: this.serverPositions,\n positionFetcher: this.positionFetcher,\n env: this.env,\n signal,\n priceCache: this.priceCache,\n permissionConfig: this.permissionConfig,\n sessionSpendUsd: this.sessionSpendUsd,\n blockvisionApiKey: this.blockvisionApiKey,\n portfolioCache: this.portfolioCache,\n };\n\n // [v1.4 — Day 2.5] Bust both portfolio caches for this address before\n // the 1.5s Sui-RPC-indexer-lag delay. The v1.4 BlockVision swap\n // introduced two caching layers — `ToolContext.portfolioCache`\n // (per-request Map, no TTL) and the module-level cache in\n // `blockvision-prices.ts` (60s TTL). Without explicit invalidation,\n // `runPostWriteRefresh` re-runs `balance_check`, which calls\n // `fetchAddressPortfolio()`, which returns the *cached pre-write\n // snapshot* — defeating the entire point of post-write refresh and\n // resurrecting the v0.46.16-era class of \"I deposited 20 USDC but\n // the agent says my balance didn't change\" bug. Pre-v1.4 the same\n // path called `fetchWalletCoins` (Sui RPC, no cache) so the 1.5s\n // delay alone was sufficient; post-v1.4 we MUST invalidate or no\n // amount of waiting will help.\n //\n // [PR 1 — v0.55] `clearPortfolioCacheFor` is now async (Upstash-backed\n // when Audric injects the store) — MUST be awaited or the next\n // `balance_check` races the Redis delete and refetches the stale\n // pre-write balance. Pre-PR-1 it was a sync Map.delete and\n // fire-and-forget worked; under Redis the network round-trip is\n // load-bearing.\n if (this.walletAddress) {\n this.portfolioCache?.delete(this.walletAddress);\n await clearPortfolioCacheFor(this.walletAddress);\n }\n\n // [v0.46.16] Sui RPC indexer lag — `executeTransactionBlock` returns\n // as soon as the tx is included in a checkpoint, but the public RPC's\n // owned-coin index trails by ~500-1500ms. Without this delay the\n // injected `balance_check` returns the *pre-write* snapshot and the\n // LLM either trusts it (wrong) or has to reason around it (noisy).\n // 1500ms catches ~99% of cases on Sui mainnet; the refresh is async\n // anyway so this doesn't block the UI's pending_action resolution.\n if (!signal.aborted) {\n await new Promise<void>((resolve) => {\n const t = setTimeout(resolve, 1500);\n signal.addEventListener('abort', () => { clearTimeout(t); resolve(); }, { once: true });\n });\n }\n if (signal.aborted) return;\n\n // Run all refreshes in parallel — they're read-only and target\n // different RPC endpoints (wallet, NAVI positions, health). The\n // common case (1-3 tools) finishes well under 1s.\n const idStem = `pwr_${action.toolUseId.slice(-6)}`;\n const refreshes = await Promise.all(\n refreshTools.map(async (tool, idx) => {\n const id = `${idStem}_${idx}_${tool.name}`;\n try {\n const parsed = tool.inputSchema.safeParse({});\n if (!parsed.success) {\n return {\n tool,\n id,\n isError: true as const,\n data: {\n error: `Post-write refresh: invalid input for ${tool.name}`,\n },\n attemptCount: undefined as number | undefined,\n };\n }\n // [SPEC 8 v0.5.1 B3.2] Per-tool retry counter — each refresh\n // gets its own context override so attemptCount doesn't bleed\n // across the parallel batch.\n const { context: toolCtx, readAttemptCount } = withRetryStats(context);\n const result = await tool.call(parsed.data, toolCtx);\n return {\n tool,\n id,\n isError: false as const,\n data: result.data,\n attemptCount: readAttemptCount(),\n };\n } catch (err) {\n return {\n tool,\n id,\n isError: true as const,\n data: {\n error:\n err instanceof Error\n ? err.message\n : 'Post-write refresh failed',\n },\n attemptCount: undefined as number | undefined,\n };\n }\n }),\n );\n\n // Push synthetic conversation pair so the LLM sees:\n // assistant(refresh tool_uses) → user(refresh tool_results)\n // Anthropic accepts back-to-back assistant/user blocks; this is the\n // same shape `buildSyntheticPrefetch` uses at session start.\n const refreshUses: ContentBlock[] = refreshes.map((r) => ({\n type: 'tool_use',\n id: r.id,\n name: r.tool.name,\n input: {},\n }));\n this.messages.push({ role: 'assistant', content: refreshUses });\n\n const refreshResults: ContentBlock[] = refreshes.map((r) => ({\n type: 'tool_result',\n toolUseId: r.id,\n content: typeof r.data === 'string' ? r.data : JSON.stringify(r.data),\n isError: r.isError,\n }));\n this.messages.push({ role: 'user', content: refreshResults });\n\n // Yield events so hosts log them in `TurnMetrics.toolsCalled[]` and\n // the UI renders the refreshed cards in-line. Also populate the\n // intra-turn cache so any LLM-driven `tool_use` for the same\n // (name, input) during the resumed agent loop dedups instead of\n // double-rendering on top of the refresh card.\n for (const r of refreshes) {\n if (!r.isError) {\n this.turnReadCache.set(\n TurnReadCache.keyFor(r.tool.name, {}),\n { result: r.data, sourceToolUseId: r.id },\n );\n }\n yield {\n type: 'tool_result',\n toolName: r.tool.name,\n toolUseId: r.id,\n result: r.data,\n isError: r.isError,\n wasPostWriteRefresh: true,\n ...(r.attemptCount !== undefined ? { attemptCount: r.attemptCount } : {}),\n };\n }\n }\n\n interrupt(): void {\n this.abortController?.abort();\n }\n\n getMessages(): readonly Message[] {\n return this.messages;\n }\n\n getMatchedRecipe(): Recipe | null {\n return this.matchedRecipe;\n }\n\n getContextBudget(): ContextBudget {\n return this.contextBudget;\n }\n\n reset(): void {\n this.messages = [];\n this.costTracker.reset();\n this.contextBudget.reset();\n this.guardEvents = [];\n this.matchedRecipe = null;\n }\n\n getGuardEvents(): readonly GuardEvent[] {\n return this.guardEvents;\n }\n\n loadMessages(messages: Message[]): void {\n this.messages = [...messages];\n }\n\n /**\n * [v0.46.7] Run a read-only tool out-of-band, using the engine's tool\n * registry and ToolContext. Used by hosts to deterministically pre-dispatch\n * tools based on user-message intent (e.g. always call `balance_check` when\n * the user says \"what's my net worth?\", regardless of whether the LLM would\n * have otherwise re-called it).\n *\n * The host is responsible for:\n * - Streaming the synthetic `tool_start` + `tool_result` events to the UI\n * (so cards render as if the LLM had called the tool).\n * - Appending matching `tool_use` + `tool_result` ContentBlocks to the\n * engine's message history via `loadMessages([...getMessages(), ...synth])`\n * BEFORE calling `submitMessage`, so the LLM sees the fresh data and\n * doesn't re-call.\n *\n * Throws if the tool isn't registered, isn't read-only, or fails input\n * validation. Tool execution errors are returned as `{ data, isError: true }`\n * for the caller to handle (typically: skip the injection so the LLM falls\n * back to its normal flow).\n */\n async invokeReadTool(\n toolName: string,\n input: unknown,\n options: { signal?: AbortSignal } = {},\n ): Promise<{ data: unknown; isError: boolean }> {\n const tool = findTool(this.tools, toolName);\n if (!tool) throw new Error(`invokeReadTool: tool not found: ${toolName}`);\n if (!tool.isReadOnly) {\n throw new Error(`invokeReadTool: tool is not read-only: ${toolName} (write tools must go through the permission gate)`);\n }\n\n const parsed = tool.inputSchema.safeParse(input);\n if (!parsed.success) {\n throw new Error(\n `invokeReadTool: invalid input for ${toolName}: ${parsed.error.issues.map((i) => i.message).join(', ')}`,\n );\n }\n\n // [v0.46.8] Intra-turn cache: if the same tool was already invoked\n // (either via a prior `invokeReadTool` call or by the LLM mid-turn),\n // return the cached result without re-fetching. Makes pre-dispatch\n // idempotent — calling `invokeReadTool('balance_check', {})` twice\n // back-to-back hits RPC once, not twice.\n const cacheKey = TurnReadCache.keyFor(toolName, parsed.data);\n const cached = this.turnReadCache.get(cacheKey);\n if (cached) {\n return { data: cached.result, isError: false };\n }\n\n const signal = options.signal ?? new AbortController().signal;\n const context: ToolContext = {\n agent: this.agent,\n mcpManager: this.mcpManager,\n walletAddress: this.walletAddress,\n suiRpcUrl: this.suiRpcUrl,\n serverPositions: this.serverPositions,\n positionFetcher: this.positionFetcher,\n env: this.env,\n signal,\n priceCache: this.priceCache,\n permissionConfig: this.permissionConfig,\n sessionSpendUsd: this.sessionSpendUsd,\n blockvisionApiKey: this.blockvisionApiKey,\n portfolioCache: this.portfolioCache,\n };\n\n try {\n const result = await tool.call(parsed.data, context);\n // Cache the successful result so a subsequent LLM-driven\n // `tool_use` for the same (name, input) hits the dedup path in\n // the agent loop and the host doesn't render a duplicate card.\n this.turnReadCache.set(cacheKey, {\n result: result.data,\n sourceToolUseId: 'invokeReadTool',\n });\n return { data: result.data, isError: false };\n } catch (err) {\n // Errors are NOT cached — the next call should retry, not see a\n // stale failure.\n return {\n data: { error: err instanceof Error ? err.message : 'Tool execution failed' },\n isError: true,\n };\n }\n }\n\n setServerPositions(data: EngineConfig['serverPositions']): void {\n this.serverPositions = data;\n }\n\n getUsage(): CostSnapshot {\n return this.costTracker.getSnapshot();\n }\n\n // ---------------------------------------------------------------------------\n // Core agent loop — shared by submitMessage and resumeWithToolResult\n // ---------------------------------------------------------------------------\n\n /**\n * Run the LLM → tool → LLM loop. When a write tool needs confirmation,\n * yields `pending_action` and returns immediately (stream ends cleanly).\n *\n * @param freshPrompt - The original user prompt (for corrupt-history retry). Null on resume.\n */\n private async *agentLoop(\n freshPrompt: string | null,\n signal: AbortSignal,\n applyToolChoice = true,\n ): AsyncGenerator<EngineEvent> {\n const context: ToolContext = {\n agent: this.agent,\n mcpManager: this.mcpManager,\n walletAddress: this.walletAddress,\n suiRpcUrl: this.suiRpcUrl,\n serverPositions: this.serverPositions,\n positionFetcher: this.positionFetcher,\n env: this.env,\n signal,\n priceCache: this.priceCache,\n permissionConfig: this.permissionConfig,\n sessionSpendUsd: this.sessionSpendUsd,\n blockvisionApiKey: this.blockvisionApiKey,\n portfolioCache: this.portfolioCache,\n };\n\n let turns = 0;\n let hasRetriedWithCleanHistory = false;\n let turnStartMs = Date.now();\n\n while (turns < this.maxTurns) {\n if (signal.aborted) {\n yield { type: 'error', error: new Error('Aborted') };\n return;\n }\n\n turns++;\n turnStartMs = Date.now();\n const toolDefs = toolsToDefinitions(this.tools);\n\n const acc: TurnAccumulator = {\n text: '',\n stopReason: 'end_turn',\n assistantBlocks: [],\n pendingToolCalls: [],\n };\n\n const dispatcher = new EarlyToolDispatcher(this.tools, context, this.turnReadCache);\n\n // [SPEC 7 P2.3 Layer 2] Track every read tool that lands during this\n // turn so the bundle composer can populate `regenerateInput.toolUseIds`\n // when ≥2 confirm-tier bundleable writes follow. Contributing reads\n // are filtered to the canonical regeneratable set inside the\n // composer; we just collect everything here. Cleared per-turn at\n // the top of the while loop above (declaration is fresh each turn).\n const turnReadToolResults: Array<{\n toolUseId: string;\n toolName: string;\n timestamp: number;\n }> = [];\n\n try {\n // B.3: Zero-cost dedup of identical tool calls every turn.\n // [v1.4 Item 4] Emit a synthetic tool_result event for each\n // deduped prior call so hosts can flip `resultDeduped` on the\n // matching `TurnMetrics.toolsCalled[]` row. Marker shape is\n // explicit so collectors don't double-count emissions.\n // [v1.5.1] Pass the tool registry so microcompact honors per-tool\n // `cacheable` flags. Mutable-state reads (balance_check etc.)\n // never dedupe, so post-write refreshes always surface fresh\n // data instead of a \"[Same result as call #N]\" marker that the\n // LLM previously misread as \"stale snapshot, fall back to math\".\n const microcompacted = microcompact(this.messages, this.tools);\n this.messages = microcompacted;\n for (const dedupedId of microcompacted.dedupedToolUseIds) {\n yield {\n type: 'tool_result',\n toolName: '__deduped__',\n toolUseId: dedupedId,\n result: null,\n isError: false,\n resultDeduped: true,\n };\n }\n\n // RE-3.3: Compact context if budget is exceeded\n if (this.contextBudget.shouldCompact()) {\n this.messages = await compactMessages(this.messages, {\n maxTokens: 100_000,\n keepRecentCount: 8,\n summarizer: this.contextSummarizer,\n });\n // [v1.4 Item 4] Notify hosts that compaction fired this turn.\n // `compactMessages` stays a pure function; the event keeps the\n // signal observable without coupling.\n yield { type: 'compaction' };\n }\n\n this.messages = validateHistory(this.messages);\n\n if (process.env.NODE_ENV !== 'test') {\n const summary = this.messages.map((m, idx) => {\n const blocks = m.content.map((b) => {\n if (b.type === 'text') return `text(${b.text.slice(0, 40)}…)`;\n if (b.type === 'thinking') return `thinking(${b.thinking.length}ch)`;\n if (b.type === 'redacted_thinking') return `redacted_thinking`;\n if (b.type === 'tool_use') return `tool_use:${b.id.slice(-8)}/${b.name}`;\n return `tool_result:${(b as { toolUseId: string }).toolUseId.slice(-8)}`;\n });\n return ` [${idx}] ${m.role}: [${blocks.join(', ')}]`;\n });\n console.log(`[engine] provider.chat turn=${turns} msgs=${this.messages.length}\\n${summary.join('\\n')}`);\n }\n\n const thinkingEnabled = this.thinking && this.thinking.type !== 'disabled';\n // Anthropic requires toolChoice 'auto' (not 'any') when thinking is enabled\n const effectiveToolChoice = thinkingEnabled\n ? ((applyToolChoice && turns === 1) ? 'auto' as const : undefined)\n : ((applyToolChoice && turns === 1) ? this.toolChoice : undefined);\n\n // RE-3.1: Inject matched recipe context into system prompt for this turn\n let effectivePrompt = this.systemPrompt;\n if (this.matchedRecipe && this.recipes) {\n const recipeCtx = this.recipes.toPromptContext(this.matchedRecipe);\n if (typeof effectivePrompt === 'string') {\n effectivePrompt = `${effectivePrompt}\\n\\n${recipeCtx}`;\n } else if (Array.isArray(effectivePrompt)) {\n effectivePrompt = [\n ...effectivePrompt,\n { type: 'text' as const, text: recipeCtx },\n ];\n }\n }\n\n // [SPEC 8 v0.5.1] HARD-cap thinking budget per effort tier.\n // lean=disabled, standard=8k, rich=16k, max=32k. Hosts that pass\n // a smaller budget keep it; the engine only ever clamps DOWN.\n // See thinking-budget.ts for the full rationale.\n const cappedThinking = clampThinkingForEffort(this.thinking, this.outputConfig?.effort);\n\n const stream = this.provider.chat({\n messages: this.messages,\n systemPrompt: effectivePrompt,\n tools: toolDefs,\n model: this.model,\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n toolChoice: effectiveToolChoice,\n thinking: cappedThinking,\n outputConfig: this.outputConfig,\n signal,\n });\n\n for await (const event of stream) {\n yield* this.handleProviderEvent(event, acc, dispatcher);\n }\n } catch (err) {\n if (freshPrompt && !hasRetriedWithCleanHistory && isCorruptHistoryError(err)) {\n hasRetriedWithCleanHistory = true;\n console.warn('[engine] Corrupt session history detected, resetting to fresh conversation');\n this.messages = [\n { role: 'user', content: [{ type: 'text', text: freshPrompt }] },\n ];\n turns--;\n continue;\n }\n throw err;\n }\n\n if (acc.text) {\n acc.assistantBlocks.push({ type: 'text', text: acc.text });\n }\n\n // B.1: Collect results from early-dispatched tools\n const earlyResultBlocks: ContentBlock[] = [];\n if (dispatcher.hasPending()) {\n if (signal.aborted) {\n dispatcher.abort();\n }\n for await (const earlyEvent of dispatcher.collectResults()) {\n if (earlyEvent.type === 'tool_result') {\n if (!earlyEvent.isError) {\n const warning = flagSuspiciousResult(earlyEvent.toolName, earlyEvent.result);\n if (warning) {\n const flagged = {\n ...earlyEvent,\n result: typeof earlyEvent.result === 'object' && earlyEvent.result\n ? { ...earlyEvent.result as Record<string, unknown>, _warning: warning }\n : { data: earlyEvent.result, _warning: warning },\n };\n yield flagged;\n earlyResultBlocks.push({\n type: 'tool_result',\n toolUseId: flagged.toolUseId,\n content: JSON.stringify(flagged.result),\n isError: flagged.isError,\n });\n continue;\n }\n }\n const tool = findTool(this.tools, earlyEvent.toolName);\n // Pull the original input back off the dispatcher so guard state\n // (e.g. SwapQuoteTracker) can key off it. Passing `null` here was\n // a silent regression that made guardSwapPreview block every\n // swap_execute even after a successful early-dispatched\n // swap_quote.\n const earlyInput = dispatcher.getInputById(earlyEvent.toolUseId) ?? null;\n updateGuardStateAfterToolResult(\n earlyEvent.toolName, tool, earlyInput, earlyEvent.result, earlyEvent.isError, this.guardState,\n );\n\n let enrichedResult = earlyEvent.result;\n if (this.guardConfig && !earlyEvent.isError && tool) {\n const artifactInj = this.guardConfig.artifactPreview !== false\n ? guardArtifactPreview(earlyEvent.result)\n : null;\n const staleInj = this.guardConfig.staleData !== false\n ? guardStaleData(tool.flags)\n : null;\n const allInjections = [\n ...(artifactInj ? [artifactInj] : []),\n ...(staleInj ? [staleInj] : []),\n ];\n if (allInjections.length > 0 && typeof enrichedResult === 'object' && enrichedResult) {\n enrichedResult = { ...enrichedResult as Record<string, unknown>, _guards: allInjections };\n }\n }\n\n const finalEvent = enrichedResult !== earlyEvent.result\n ? { ...earlyEvent, result: enrichedResult }\n : earlyEvent;\n\n yield finalEvent;\n\n if (!finalEvent.isError) {\n const r = finalEvent.result as Record<string, unknown> | null;\n if (r && r.__canvas === true) {\n yield {\n type: 'canvas',\n template: String(r.template ?? ''),\n title: String(r.title ?? ''),\n data: r.templateData ?? null,\n toolUseId: finalEvent.toolUseId,\n };\n }\n // [SPEC 8 v0.5.1] Side-channel todo_update event paired to\n // every update_todo tool result. Mirrors the __canvas\n // pattern above; see tools/update-todo.ts for rationale.\n if (r && r.__todoUpdate === true && Array.isArray(r.items)) {\n yield {\n type: 'todo_update',\n items: r.items as { id: string; label: string; status: 'pending' | 'in_progress' | 'completed' }[],\n toolUseId: finalEvent.toolUseId,\n };\n }\n }\n\n // [SPEC 7 P2.3 Layer 2] Track successful reads for bundle\n // composition. The composer filters to the canonical\n // regeneratable set; collecting all reads here is fine.\n if (!finalEvent.isError && tool && tool.isReadOnly) {\n turnReadToolResults.push({\n toolUseId: finalEvent.toolUseId,\n toolName: finalEvent.toolName,\n timestamp: Date.now(),\n });\n }\n\n earlyResultBlocks.push({\n type: 'tool_result',\n toolUseId: finalEvent.toolUseId,\n content: JSON.stringify(finalEvent.result),\n isError: finalEvent.isError,\n });\n }\n }\n }\n\n const hasEarlyResults = earlyResultBlocks.length > 0;\n const hasRemainingCalls = acc.pendingToolCalls.length > 0;\n\n if (!hasEarlyResults && !hasRemainingCalls) {\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n getTelemetrySink().histogram('anthropic.latency_ms', Date.now() - turnStartMs);\n yield { type: 'turn_complete', stopReason: acc.stopReason };\n return;\n }\n\n if (signal.aborted) {\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n if (hasEarlyResults) {\n this.messages.push({ role: 'user', content: earlyResultBlocks });\n }\n this.addErrorResults(acc.pendingToolCalls, 'Aborted');\n yield { type: 'error', error: new Error('Aborted') };\n return;\n }\n\n // --- Permission gate (only for non-early-dispatched calls) ---\n // [SPEC 7 P2.3 Layer 2] Refactored from `pendingWrite` singular →\n // `pendingWrites` array. The pre-P2.3 loop did `pendingWrite = ...;\n // break;` on the first confirm-tier write, silently dropping any\n // siblings (gap G2 in spec v0.3.1). Now we collect ALL confirm\n // writes; bundle composition runs AFTER guards (below) so the\n // bundleable + non-bundleable partition can be made on guard-passed\n // calls only.\n const approved: PendingToolCall[] = [];\n const toolResultBlocks: ContentBlock[] = [...earlyResultBlocks];\n const pendingWrites: Array<{ call: PendingToolCall; tool: Tool }> = [];\n\n for (const call of acc.pendingToolCalls) {\n const tool = findTool(this.tools, call.name);\n\n // [v0.46.8] Intra-turn dedup for read-only tools. If the host\n // pre-dispatched this tool (via `invokeReadTool`) or the LLM\n // already called it earlier in the same turn, skip execution\n // and emit a deduped `tool_result` so the host can suppress\n // a duplicate card render. The LLM still gets a valid\n // `tool_result` block keyed to ITS `tool_use_id`, satisfying\n // the Anthropic protocol requirement that every `tool_use`\n // be answered by a matching `tool_result`.\n if (tool && tool.isReadOnly) {\n const cacheKey = TurnReadCache.keyFor(call.name, call.input);\n const cached = this.turnReadCache.get(cacheKey);\n if (cached) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: cached.result,\n isError: false,\n resultDeduped: true,\n };\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: call.id,\n content: JSON.stringify(cached.result),\n isError: false,\n });\n continue;\n }\n }\n\n const needsConfirmation = (() => {\n if (!tool || tool.isReadOnly) return false;\n if (tool.permissionLevel === 'explicit') return true;\n // [v0.46.15] Honor `permissionLevel: 'auto'` on write tools even\n // when no agent is present. These are custom tools (e.g. audric's\n // server-owned save_contact / savings_goal_*) that persist via\n // their own data layer (Prisma) and never need on-chain signing.\n // They explicitly opted into auto by setting the permission\n // level — gating them on `context.agent` here silently broke\n // every audric Prisma-backed write tool. Tools that DO need\n // an agent must NOT set permissionLevel: 'auto'.\n if (tool.permissionLevel === 'auto' && !toolNameToOperation(call.name)) {\n return false;\n }\n // Without an agent, write tools can't execute server-side —\n // always require confirmation so the client handles execution.\n if (!context.agent && !tool.isReadOnly) return true;\n if (context.permissionConfig && context.priceCache) {\n const operation = toolNameToOperation(call.name);\n if (operation) {\n const usdValue = resolveUsdValue(call.name, call.input as Record<string, unknown>, context.priceCache);\n const callInput = call.input as Record<string, unknown>;\n // [v1.4] sessionSpendUsd enforces daily cap.\n // Send-safety: a raw 0x recipient with no contact match\n // forces `confirm` regardless of amount (see permission-rules).\n const tier = resolvePermissionTier(\n operation,\n usdValue,\n context.permissionConfig,\n context.sessionSpendUsd,\n operation === 'send'\n ? { to: typeof callInput.to === 'string' ? callInput.to : undefined, contacts: this.contacts }\n : undefined,\n );\n return tier !== 'auto';\n }\n }\n return tool.permissionLevel !== 'auto';\n })();\n\n if (!needsConfirmation) {\n approved.push(call);\n yield { type: 'tool_start', toolName: call.name, toolUseId: call.id, input: call.input };\n continue;\n }\n\n // [SPEC 7 P2.3 Layer 2] Collect every confirm-tier write — no break.\n // Bundle vs single-write decision happens after guards (below).\n pendingWrites.push({ call, tool: tool! });\n }\n\n // --- Guard checks (pre-execution) ---\n const guardedApproved: PendingToolCall[] = [];\n\n if (this.guardConfig) {\n const convCtx = extractConversationText(this.messages);\n\n for (const call of approved) {\n const tool = findTool(this.tools, call.name);\n if (!tool) { guardedApproved.push(call); continue; }\n\n const check = runGuards(\n tool,\n call,\n this.guardState,\n this.guardConfig,\n convCtx,\n this.onGuardFired,\n { contacts: this.contacts, walletAddress: this.walletAddress },\n );\n this.guardEvents.push(...check.events);\n\n if (check.blocked) {\n yield {\n type: 'tool_result',\n toolName: call.name,\n toolUseId: call.id,\n result: { error: check.blockReason, _gate: check.blockGate },\n isError: true,\n };\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: call.id,\n content: JSON.stringify({ error: check.blockReason, _gate: check.blockGate }),\n isError: true,\n });\n continue;\n }\n\n if (check.injections.length > 0) {\n (call as PendingToolCall & { _guardInjections?: unknown[] })._guardInjections = check.injections;\n }\n guardedApproved.push(call);\n }\n } else {\n guardedApproved.push(...approved);\n }\n\n // Execute auto-approved tool calls (reads) even if a write is pending\n for await (const toolEvent of runTools(guardedApproved, this.tools, context, this.txMutex)) {\n if (toolEvent.type === 'tool_result' && !toolEvent.isError) {\n const warning = flagSuspiciousResult(toolEvent.toolName, toolEvent.result);\n if (warning) {\n const flagged = {\n ...toolEvent,\n result: typeof toolEvent.result === 'object' && toolEvent.result\n ? { ...toolEvent.result as Record<string, unknown>, _warning: warning }\n : { data: toolEvent.result, _warning: warning },\n };\n yield flagged;\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: flagged.toolUseId,\n content: JSON.stringify(flagged.result),\n isError: flagged.isError,\n });\n continue;\n }\n }\n\n // Post-execution: update guard state & apply injections\n if (toolEvent.type === 'tool_result') {\n const tool = findTool(this.tools, toolEvent.toolName);\n const originalCall = guardedApproved.find((c) => c.id === toolEvent.toolUseId);\n updateGuardStateAfterToolResult(\n toolEvent.toolName, tool, originalCall?.input ?? null, toolEvent.result, toolEvent.isError, this.guardState,\n );\n\n let enrichedResult = toolEvent.result;\n\n if (this.guardConfig && !toolEvent.isError && tool) {\n // Post-execution guards: artifact preview, stale data hint\n const artifactInj = this.guardConfig.artifactPreview !== false\n ? guardArtifactPreview(toolEvent.result)\n : null;\n const staleInj = this.guardConfig.staleData !== false\n ? guardStaleData(tool.flags)\n : null;\n\n // Merge pre-execution injections from guard check\n const preInjections =\n (guardedApproved.find((c) => c.id === toolEvent.toolUseId) as\n PendingToolCall & { _guardInjections?: unknown[] })?._guardInjections ?? [];\n\n const allInjections = [\n ...preInjections,\n ...(artifactInj ? [artifactInj] : []),\n ...(staleInj ? [staleInj] : []),\n ];\n\n if (allInjections.length > 0 && typeof enrichedResult === 'object' && enrichedResult) {\n enrichedResult = { ...enrichedResult as Record<string, unknown>, _guards: allInjections };\n }\n }\n\n const finalEvent = enrichedResult !== toolEvent.result\n ? { ...toolEvent, result: enrichedResult }\n : toolEvent;\n\n // [v0.46.8] Maintain the intra-turn read cache:\n // - Successful read → populate so subsequent identical\n // calls within the same turn dedup.\n // - Successful write → invalidate the entire cache; on-chain\n // state has changed, any prior read snapshot is stale.\n // - Errored result → leave cache untouched; retry should\n // re-execute.\n if (!finalEvent.isError && tool) {\n if (tool.isReadOnly) {\n const inputForKey = originalCall?.input ?? {};\n const cacheKey = TurnReadCache.keyFor(finalEvent.toolName, inputForKey);\n this.turnReadCache.set(cacheKey, {\n result: finalEvent.result,\n sourceToolUseId: finalEvent.toolUseId,\n });\n // [SPEC 7 P2.3 Layer 2] Track late-dispatched reads too —\n // mirrors the early-dispatch path above so the bundle\n // composer sees every contributing read regardless of\n // dispatch timing.\n turnReadToolResults.push({\n toolUseId: finalEvent.toolUseId,\n toolName: finalEvent.toolName,\n timestamp: Date.now(),\n });\n } else {\n this.turnReadCache.clear();\n }\n }\n\n yield finalEvent;\n\n if (finalEvent.type === 'tool_result' && !finalEvent.isError) {\n const r = finalEvent.result as Record<string, unknown> | null;\n if (r && r.__canvas === true) {\n yield {\n type: 'canvas',\n template: String(r.template ?? ''),\n title: String(r.title ?? ''),\n data: r.templateData ?? null,\n toolUseId: finalEvent.toolUseId,\n };\n }\n // [SPEC 8 v0.5.1] Side-channel todo_update event for the\n // late-dispatch path. Mirrors the early-dispatch emission\n // ~250 lines above.\n if (r && r.__todoUpdate === true && Array.isArray(r.items)) {\n yield {\n type: 'todo_update',\n items: r.items as { id: string; label: string; status: 'pending' | 'in_progress' | 'completed' }[],\n toolUseId: finalEvent.toolUseId,\n };\n }\n\n // [v1.4] Fire onAutoExecuted for write tools that auto-executed\n // (non-readonly tools that reach this loop have already passed the\n // auto-tier check). Wrapped in try/catch so any host error never\n // propagates back into the engine — the tool result already shipped.\n if (\n tool && !tool.isReadOnly && this.onAutoExecuted &&\n this.permissionConfig && this.priceCache\n ) {\n const operation = toolNameToOperation(toolEvent.toolName);\n if (operation && originalCall) {\n const usdValue = resolveUsdValue(\n toolEvent.toolName,\n originalCall.input as Record<string, unknown>,\n this.priceCache,\n );\n Promise.resolve()\n .then(() => this.onAutoExecuted!({\n toolName: toolEvent.toolName,\n usdValue,\n walletAddress: this.walletAddress,\n }))\n .catch((err) => {\n console.warn('[engine] onAutoExecuted callback failed:', err);\n });\n }\n }\n }\n\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: finalEvent.toolUseId,\n content: JSON.stringify(finalEvent.result),\n isError: finalEvent.isError,\n });\n continue;\n }\n\n yield toolEvent;\n }\n\n // --- Guard check on every pending write ---\n // [SPEC 7 P2.3 Layer 2] Run guards on each pending write. Blocked\n // writes feed an error tool_result back to the LLM and are dropped\n // from the bundle/single-write yield. Pre-P2.3 the loop only ran\n // guards on the first (singular) pendingWrite; now we run guards\n // on every collected confirm-tier write so a bundleable trio\n // doesn't silently skip guard checks on steps 2 and 3.\n const guardPassedWrites: Array<{ call: PendingToolCall; tool: Tool }> = [];\n const guardInjectionsByCallId: Record<string, Array<{ _gate: string; _hint?: string; _warning?: string }>> = {};\n let anyGuardBlocked = false;\n\n if (this.guardConfig && pendingWrites.length > 0) {\n const convCtx = extractConversationText(this.messages);\n for (const write of pendingWrites) {\n const check = runGuards(\n write.tool,\n write.call,\n this.guardState,\n this.guardConfig,\n convCtx,\n this.onGuardFired,\n { contacts: this.contacts, walletAddress: this.walletAddress },\n );\n this.guardEvents.push(...check.events);\n\n if (check.blocked) {\n anyGuardBlocked = true;\n yield {\n type: 'tool_result',\n toolName: write.call.name,\n toolUseId: write.call.id,\n result: { error: check.blockReason, _gate: check.blockGate },\n isError: true,\n };\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: write.call.id,\n content: JSON.stringify({ error: check.blockReason, _gate: check.blockGate }),\n isError: true,\n });\n continue;\n }\n\n if (check.injections.length > 0) {\n guardInjectionsByCallId[write.call.id] = check.injections;\n (write.call as PendingToolCall & { _guardInjections?: unknown[] })._guardInjections = check.injections;\n }\n guardPassedWrites.push(write);\n }\n\n // If ANY write was blocked, feed errors back to the LLM and\n // re-prompt — don't surface a partial bundle/single-write\n // pending_action with missing pieces. The LLM will narrate the\n // block and either retry with corrected input or refuse cleanly.\n if (anyGuardBlocked) {\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n this.messages.push({ role: 'user', content: toolResultBlocks });\n continue;\n }\n } else {\n // No guard config — all collected writes pass through.\n guardPassedWrites.push(...pendingWrites);\n }\n\n // [SPEC 7 P2.3 Layer 2] Bundle vs single-write decision.\n //\n // After guards, partition guardPassedWrites into bundleable + non-\n // bundleable. Bundling rules:\n // - 0 writes → fall through to \"all auto-approved\" path below.\n // - 1 write (any kind) → emit legacy single-write pending_action.\n // - ≥2 writes, all bundleable → emit bundle with steps[].\n // - ≥2 writes, mixed → emit FIRST as single-write (matches pre-\n // P2.3 break-on-first behavior); the LLM will re-emit the rest\n // in a follow-up turn after this one resolves.\n if (guardPassedWrites.length > 0) {\n const allBundleable =\n guardPassedWrites.length >= 2 &&\n guardPassedWrites.every((w) => w.tool.flags?.bundleable === true);\n\n const turnIndex = this.messages.filter((m) => m.role === 'assistant').length;\n // [v0.46.8] Mark the turn as paused so the submitMessage /\n // resumeWithToolResult `finally` blocks DON'T clear the cache.\n this.turnPaused = true;\n\n if (allBundleable) {\n // Multi-write Payment Stream — compose bundle.\n const completedResults = toolResultBlocks.map((b) => ({\n toolUseId: (b as { toolUseId: string }).toolUseId,\n content: (b as { content: string }).content,\n isError: (b as { isError?: boolean }).isError ?? false,\n }));\n const bundleAction = composeBundleFromToolResults({\n pendingWrites: guardPassedWrites.map((w) => w.call),\n tools: this.tools,\n readResults: turnReadToolResults,\n assistantContent: acc.assistantBlocks,\n completedResults,\n guardInjectionsByCallId,\n turnIndex,\n });\n yield { type: 'pending_action', action: bundleAction };\n return;\n }\n\n // Single-write (legacy shape). Honors backwards compat — pre-P2.3\n // hosts that key off `attemptId` continue to work.\n //\n // [SPEC 7 P2.3 audit fix — BUG 1] When mixed-bundleability forces\n // single-write fallback (≥2 writes guard-passed but not all\n // bundleable), the dropped writes' `tool_use` blocks are still\n // present in `assistantContent`. Without a matching `tool_result`,\n // the next Anthropic call rejects the turn (orphan tool_use).\n // Synthesize error `tool_result` blocks for every dropped write\n // and append to `toolResultBlocks` BEFORE pulling completedResults.\n // The LLM sees \"this write didn't run, ask user again next turn\".\n // Pre-existing bug class (pre-P2.3 had the same `break;` shape) —\n // we fix it here while we have visibility.\n const pendingWrite = guardPassedWrites[0];\n if (guardPassedWrites.length > 1) {\n for (let i = 1; i < guardPassedWrites.length; i++) {\n const dropped = guardPassedWrites[i];\n const errBody = JSON.stringify({\n error:\n 'This write was emitted alongside another write that requires a separate confirmation. ' +\n 'Re-emit it after the first write resolves.',\n _droppedDueToMixedBundleability: true,\n });\n yield {\n type: 'tool_result',\n toolName: dropped.call.name,\n toolUseId: dropped.call.id,\n result: { error: errBody },\n isError: true,\n };\n toolResultBlocks.push({\n type: 'tool_result',\n toolUseId: dropped.call.id,\n content: errBody,\n isError: true,\n });\n }\n }\n const writeGuardInjections = guardInjectionsByCallId[pendingWrite.call.id];\n const modifiableFields = getModifiableFields(pendingWrite.call.name);\n // [v1.4.2 — Day 3] Per-yield UUID. Hosts write this onto the\n // `TurnMetrics` row at chat-time and key the resume route's\n // update on it instead of `(sessionId, turnIndex)`.\n const attemptId = randomUUID();\n\n yield {\n type: 'pending_action',\n action: {\n toolName: pendingWrite.call.name,\n toolUseId: pendingWrite.call.id,\n input: pendingWrite.call.input,\n description: describeAction(pendingWrite.tool, pendingWrite.call),\n assistantContent: acc.assistantBlocks,\n completedResults: toolResultBlocks.map((b) => ({\n toolUseId: (b as { toolUseId: string }).toolUseId,\n content: (b as { content: string }).content,\n isError: (b as { isError?: boolean }).isError ?? false,\n })),\n ...(writeGuardInjections?.length ? { guardInjections: writeGuardInjections } : {}),\n ...(modifiableFields?.length ? { modifiableFields } : {}),\n turnIndex,\n attemptId,\n },\n };\n return;\n }\n\n // All tools auto-approved — push the complete turn (assistant + results)\n this.messages.push({ role: 'assistant', content: acc.assistantBlocks });\n this.messages.push({ role: 'user', content: toolResultBlocks });\n\n // [SPEC 8 v0.5.1] update_todo maxTurns exemption.\n //\n // Calling update_todo documents work; it doesn't advance work. If the\n // LLM fires it 4× during a 5-tool plan, that's 4 of its 10-turn budget\n // gone to narration before any real action. We exempt iterations\n // whose only tool calls were update_todo by decrementing the counter.\n //\n // The check looks at every `tool_use` block in this iteration's\n // `acc.assistantBlocks` (covers both early-dispatched and late-\n // dispatched calls). If every one was `update_todo`, decrement.\n // Mixed iterations (e.g. balance_check + update_todo) DO count —\n // that's a real piece of work the LLM is doing.\n const toolUseBlocks = acc.assistantBlocks.filter((b) => b.type === 'tool_use') as { name: string }[];\n const allUpdateTodo =\n toolUseBlocks.length > 0 && toolUseBlocks.every((b) => b.name === 'update_todo');\n if (allUpdateTodo) {\n turns--;\n }\n\n if (this.costTracker.isOverBudget()) {\n yield { type: 'error', error: new Error('Session budget exceeded') };\n return;\n }\n }\n\n yield { type: 'turn_complete', stopReason: 'max_turns' };\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n private addErrorResults(pendingCalls: PendingToolCall[], reason: string): void {\n const errorBlocks: ContentBlock[] = pendingCalls.map((call) => ({\n type: 'tool_result' as const,\n toolUseId: call.id,\n content: JSON.stringify({ error: reason }),\n isError: true,\n }));\n if (errorBlocks.length > 0) {\n this.messages.push({ role: 'user', content: errorBlocks });\n }\n }\n\n private *handleProviderEvent(\n event: ProviderEvent,\n acc: TurnAccumulator,\n dispatcher?: EarlyToolDispatcher,\n ): Generator<EngineEvent> {\n switch (event.type) {\n case 'thinking_delta': {\n yield { type: 'thinking_delta', text: event.text, blockIndex: event.blockIndex };\n break;\n }\n\n case 'thinking_done': {\n acc.assistantBlocks.push({\n type: 'thinking',\n thinking: event.thinking,\n signature: event.signature,\n });\n yield {\n type: 'thinking_done',\n blockIndex: event.blockIndex,\n signature: event.signature,\n // [SPEC 8 v0.5.1] forward HowIEvaluated structured fields when\n // the provider parsed an <eval_summary> marker.\n ...(event.summaryMode && event.evaluationItems\n ? { summaryMode: true, evaluationItems: event.evaluationItems }\n : {}),\n };\n break;\n }\n\n case 'redacted_thinking': {\n acc.assistantBlocks.push({\n type: 'redacted_thinking',\n data: event.data,\n });\n break;\n }\n\n case 'text_delta': {\n acc.text += event.text;\n yield { type: 'text_delta', text: event.text };\n break;\n }\n\n case 'tool_use_done': {\n if (acc.text) {\n acc.assistantBlocks.push({ type: 'text', text: acc.text });\n acc.text = '';\n }\n acc.assistantBlocks.push({\n type: 'tool_use',\n id: event.id,\n name: event.name,\n input: event.input,\n });\n\n const call: PendingToolCall = { id: event.id, name: event.name, input: event.input };\n\n // B.1: Try early dispatch for read-only tools mid-stream\n if (dispatcher?.tryDispatch(call)) {\n yield { type: 'tool_start', toolName: call.name, toolUseId: call.id, input: call.input };\n } else {\n acc.pendingToolCalls.push(call);\n }\n break;\n }\n\n case 'usage': {\n this.costTracker.track(\n event.inputTokens,\n event.outputTokens,\n event.cacheReadTokens,\n event.cacheWriteTokens,\n );\n this.contextBudget.update(event.inputTokens);\n const sink = getTelemetrySink();\n if (event.inputTokens) sink.counter('anthropic.tokens', { kind: 'input' }, event.inputTokens);\n if (event.outputTokens) sink.counter('anthropic.tokens', { kind: 'output' }, event.outputTokens);\n if (event.cacheReadTokens) sink.counter('anthropic.tokens', { kind: 'cache_read' }, event.cacheReadTokens);\n if (event.cacheWriteTokens) sink.counter('anthropic.tokens', { kind: 'cache_write' }, event.cacheWriteTokens);\n yield {\n type: 'usage',\n inputTokens: event.inputTokens,\n outputTokens: event.outputTokens,\n cacheReadTokens: event.cacheReadTokens,\n cacheWriteTokens: event.cacheWriteTokens,\n };\n break;\n }\n\n case 'stop': {\n acc.stopReason = event.reason;\n break;\n }\n\n default:\n break;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isCorruptHistoryError(err: unknown): boolean {\n const msg = err instanceof Error ? err.message : String(err);\n return (\n (msg.includes('tool_use') && msg.includes('tool_result')) ||\n msg.includes('roles must alternate') ||\n (msg.includes('400') && msg.includes('invalid_request_error'))\n );\n}\n\n/**\n * Pre-flight validation: ensures message history meets Anthropic's requirements\n * right before every API call. Anthropic requires that every tool_use in an\n * assistant message has a matching tool_result in the IMMEDIATELY NEXT user\n * message — not just anywhere in the history. This function strips any\n * tool_use/tool_result blocks that violate this positional constraint and\n * fixes role alternation. Single point of defense — no corrupt messages can\n * reach the API regardless of how they got into the session.\n */\nexport function validateHistory(messages: Message[]): Message[] {\n const result: Message[] = [];\n let i = 0;\n\n while (i < messages.length) {\n const msg = messages[i];\n\n // For assistant messages with tool_use, verify the next message has ALL results\n const toolUseIds = msg.content\n .filter((b): b is { type: 'tool_use'; id: string; name: string; input: unknown } => b.type === 'tool_use')\n .map((b) => b.id);\n\n if (toolUseIds.length > 0 && msg.role === 'assistant') {\n const next = messages[i + 1];\n const nextResultIds = new Set(\n (next?.content ?? [])\n .filter((b): b is { type: 'tool_result'; toolUseId: string; content: string } => b.type === 'tool_result')\n .map((b) => b.toolUseId),\n );\n\n // Strip tool_use blocks that have no result in the next message\n const cleanAssistant = msg.content.filter((b) => {\n if (b.type === 'tool_use') return nextResultIds.has(b.id);\n return true;\n });\n\n // Strip tool_result blocks from next message whose tool_use was removed\n const keptToolUseIds = new Set(\n cleanAssistant\n .filter((b): b is { type: 'tool_use'; id: string; name: string; input: unknown } => b.type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanNext = next?.content.filter((b) => {\n if (b.type === 'tool_result') return keptToolUseIds.has(b.toolUseId);\n return true;\n });\n\n if (cleanAssistant.length > 0) {\n result.push({ role: msg.role, content: cleanAssistant });\n }\n if (cleanNext && cleanNext.length > 0) {\n result.push({ role: next!.role, content: cleanNext });\n }\n i += 2;\n continue;\n }\n\n // For user messages: strip any tool_result blocks that reference a tool_use\n // not present in the immediately preceding assistant message\n if (msg.role === 'user' && msg.content.some((b) => b.type === 'tool_result')) {\n const prevAssistant = result[result.length - 1];\n const prevToolUseIds = new Set(\n (prevAssistant?.role === 'assistant' ? prevAssistant.content : [])\n .filter((b): b is { type: 'tool_use'; id: string; name: string; input: unknown } => b.type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanContent = msg.content.filter((b) => {\n if (b.type === 'tool_result') return prevToolUseIds.has(b.toolUseId);\n return true;\n });\n if (cleanContent.length > 0) {\n result.push({ role: msg.role, content: cleanContent });\n }\n i++;\n continue;\n }\n\n result.push(msg);\n i++;\n }\n\n // Merge consecutive same-role messages (can happen after stripping)\n const merged: Message[] = [];\n for (const msg of result) {\n const last = merged[merged.length - 1];\n if (last && last.role === msg.role) {\n last.content = [...last.content, ...msg.content];\n } else {\n merged.push({ role: msg.role, content: [...msg.content] });\n }\n }\n\n // First message must be user, AND it must not consist solely of\n // orphan `tool_result` blocks whose matching `tool_use` lived in an\n // assistant turn we're about to shift off. Anthropic rejects any\n // user message containing a tool_result that doesn't reference a\n // preceding assistant tool_use.\n //\n // The most common trigger is host code that seeds the conversation\n // with prefetched tool calls (see audric's `buildSyntheticPrefetch`):\n // `[assistant tool_uses, user tool_results, assistant text]`. After\n // shifting off the leading assistant, the user message's tool_results\n // are now orphaned. Strip them; if that empties the user message,\n // shift it off too — the next message may be assistant, in which\n // case we loop again.\n while (merged.length > 0) {\n if (merged[0].role !== 'user') {\n merged.shift();\n continue;\n }\n const cleaned = merged[0].content.filter((b) => b.type !== 'tool_result');\n if (cleaned.length === 0) {\n merged.shift();\n continue;\n }\n if (cleaned.length !== merged[0].content.length) {\n merged[0] = { role: 'user', content: cleaned };\n }\n break;\n }\n\n return merged;\n}\n\n\nfunction flagSuspiciousResult(toolName: string, result: unknown): string | null {\n if (!result || typeof result !== 'object') return null;\n const r = result as Record<string, unknown>;\n if (toolName === 'swap_execute') {\n const outAmt = Number(r.toAmount ?? r.outputAmount ?? 0);\n const inAmt = Number(r.fromAmount ?? r.inputAmount ?? 1);\n if (inAmt > 0 && outAmt / inAmt > 1_000_000) {\n return '[Warning: This quote may contain inaccurate data. Verify on-chain before executing.]';\n }\n }\n const apy = Number(r.apy ?? r.APY ?? NaN);\n if (!isNaN(apy) && apy < 0) {\n return '[Warning: Negative APY detected — data may be stale.]';\n }\n return null;\n}\n","import type { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Messages — provider-agnostic conversation format\n// ---------------------------------------------------------------------------\n\nexport type ContentBlock =\n | { type: 'text'; text: string }\n | { type: 'thinking'; thinking: string; signature: string }\n | { type: 'redacted_thinking'; data: string }\n | { type: 'tool_use'; id: string; name: string; input: unknown }\n | {\n type: 'tool_result';\n toolUseId: string;\n content: string;\n isError?: boolean;\n };\n\nexport interface Message {\n role: 'user' | 'assistant';\n content: ContentBlock[];\n}\n\n// ---------------------------------------------------------------------------\n// Engine events — yielded by QueryEngine.submitMessage()\n// ---------------------------------------------------------------------------\n\nexport type EngineEvent =\n /**\n * [SPEC 8 v0.5.1] `blockIndex` identifies which thinking block this delta\n * belongs to. Anthropic streams multi-block thinking with rising indices\n * across each turn (block 0, 1, 2, ...). Hosts use this to render\n * chronologically interleaved thinking accordions instead of flattening\n * every delta into one string. Backwards-compatible: older hosts that\n * ignore the field still see deltas in emission order.\n */\n | { type: 'thinking_delta'; text: string; blockIndex: number }\n /**\n * [SPEC 8 v0.5.1] When the thinking block contained a parseable\n * `<eval_summary>...</eval_summary>` marker, `summaryMode` flips true\n * and `evaluationItems` carries the structured rows. Hosts render the\n * `HowIEvaluatedBlock` (\"✦ HOW I EVALUATED THIS\") trust card from\n * these fields. Both undefined when the block had no marker (every\n * read-only and most write turns).\n */\n | {\n type: 'thinking_done';\n blockIndex: number;\n signature?: string;\n summaryMode?: boolean;\n evaluationItems?: import('./eval-summary.js').EvaluationItem[];\n }\n | { type: 'text_delta'; text: string }\n | { type: 'tool_start'; toolName: string; toolUseId: string; input: unknown }\n | {\n type: 'tool_result';\n toolName: string;\n toolUseId: string;\n result: unknown;\n isError: boolean;\n /**\n * [v1.4 Item 4] True when the tool was executed by `EarlyToolDispatcher`\n * (read tools dispatched concurrently before the LLM yields). Hosts\n * record this in `TurnMetrics.toolsCalled[].wasEarlyDispatched`.\n */\n wasEarlyDispatched?: boolean;\n /**\n * [v1.4 Item 4] True when this result was synthesized from a previous\n * identical tool call by `microcompact` deduplication, instead of\n * actually re-running the tool.\n */\n resultDeduped?: boolean;\n /**\n * [v1.5] True when this result was produced by the engine's\n * post-write refresh mechanism (see `EngineConfig.postWriteRefresh`).\n * The engine auto-runs configured read tools immediately after a\n * successful write so the LLM narrates from fresh on-chain state\n * instead of inferring from a stale snapshot. Hosts should render\n * these like any other tool result; the flag is for analytics and\n * UI affordances (e.g. a subtle \"auto-refreshed\" badge).\n */\n wasPostWriteRefresh?: boolean;\n /**\n * [SPEC 8 v0.5.1 B3.2] Number of HTTP attempts the tool made before\n * succeeding (or returning the final result). Surfaced when the tool\n * went through one or more retries inside its retry wrapper\n * (`fetchBlockVisionWithRetry` and equivalents). Set ONLY when N > 1\n * — a successful first try leaves the field undefined to avoid\n * header noise in the host's `ToolBlockView`. Hosts render\n * \"TOOL · attempt N · 1.4s\" subtitle when present, hidden otherwise.\n *\n * Plumbing: engine sets a per-tool `retryStats: { attemptCount: 1 }`\n * counter on `ToolContext`; the BlockVision retry wrapper increments\n * it on every retry attempt; the engine reads it back after the tool\n * returns and surfaces here when > 1. Tools that don't use a retry\n * wrapper never emit a value.\n */\n attemptCount?: number;\n }\n | {\n type: 'pending_action';\n action: PendingAction;\n }\n | { type: 'turn_complete'; stopReason: StopReason }\n | {\n type: 'usage';\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n }\n | { type: 'error'; error: Error }\n | {\n /** Emitted when a tool result carries a canvas payload (__canvas: true). */\n type: 'canvas';\n template: string;\n data: unknown;\n title: string;\n toolUseId: string;\n }\n /**\n * [v1.4 Item 4] Emitted exactly once per agent turn when context-window\n * compaction fires. Hosts (e.g. audric `TurnMetricsCollector`) flip a\n * boolean for the `TurnMetrics.compactionTriggered` column. Carries no\n * payload — `compactMessages` stays a pure function.\n */\n | { type: 'compaction' }\n /**\n * [SPEC 8 v0.5.1] Side-channel event paired to every `update_todo` tool\n * call. Hosts render the persistent todo card from this event (NOT from\n * the tool_result — see `tools/update-todo.ts` § \"side-channel\" for\n * rationale). Carries the full items array so the host can\n * unconditionally replace its rendered list (the tool is idempotent —\n * each call replaces the previous state). `toolUseId` lets the host\n * key the render cell to the originating tool call.\n */\n | { type: 'todo_update'; items: TodoItem[]; toolUseId: string }\n /**\n * [SPEC 8 v0.5.1] Mid-execution progress signal from a long-running tool\n * (Cetus swap_execute 2-5s, protocol_deep_dive 3-8s, portfolio_analysis\n * 1-2s). Tools opt in by calling `context.progress?.(msg, pct?)` from\n * inside their `call` implementation. Hosts render the message + bar\n * inside the corresponding tool block's spinner — kills the dead-air\n * static-spinner UX that's the explicit SPEC 8 v0.3 fix target.\n *\n * Engine wiring (queue-and-yield in the dispatcher) lands with the\n * Cetus integration in a follow-on slice. SPEC 8 v0.5.1 reserves the\n * event type now so hosts can pre-wire the renderer.\n *\n * `pct` is 0–100 when the tool can express progress quantitatively,\n * undefined otherwise (free-text status only).\n */\n | { type: 'tool_progress'; toolUseId: string; toolName: string; message: string; pct?: number }\n /**\n * [SPEC 8 v0.5.1, D2] Inline-form structured input event reserved for\n * SPEC 9 v0.1.2 (`pending_input` form primitive). The engine does NOT\n * emit this event under SPEC 8 — the type is reserved so legacy hosts\n * can add a no-op handler now and avoid crashing when SPEC 9 ships\n * `pending_input` emission. See SPEC 8 § \"v0.5 cross-spec coupling\n * fixes\" — gap D2 — for the forward-compat rationale.\n */\n | {\n type: 'pending_input';\n /** Form schema (shape locked in SPEC 9 v0.1.2; engine treats it opaquely). */\n schema: unknown;\n /** Engine round-trip identifier — host posts the answer back keyed on this. */\n inputId: string;\n /** Optional human-readable prompt the LLM wants the host to display above the form. */\n prompt?: string;\n }\n /**\n * [SPEC 8 v0.5.1 B3.2] One-shot per-turn declaration of which adaptive\n * harness shape this turn is running under. Emitted at the start of\n * `submitMessage` BEFORE `agentLoop` begins (not on `resumeWithToolResult`\n * — resume is a continuation of the same turn, not a new shape decision).\n *\n * Derived from `classifyEffort()` on the host side: `low → 'lean'`,\n * `medium → 'standard'`, `high → 'rich'`, `max → 'max'`. Hosts use it\n * to (a) pre-allocate UI affordances (todo surface for `rich+`),\n * (b) stamp `TurnMetrics.harnessShape` for dashboard segmentation,\n * and (c) gate optional features (e.g. forbid `update_todo` rendering\n * on `lean` even if a misbehaving LLM emits one).\n *\n * If absent, hosts MUST default to `'legacy'` for telemetry purposes\n * (existing engines that don't emit this event are pre-SPEC-8). The\n * engine emits it ONLY when the host passes `harnessShape` into\n * `submitMessage` options; hosts that don't classify won't see this\n * event.\n */\n | {\n type: 'harness_shape';\n shape: HarnessShape;\n /**\n * 1-line human-readable explanation of why this shape was picked.\n * Examples: \"matched recipe portfolio_rebalance → max\",\n * \"session has prior writes + 'borrow' keyword → rich\",\n * \"single-fact lookup → lean\". Forwarded into telemetry verbatim.\n */\n rationale: string;\n };\n\n/**\n * [SPEC 8 v0.5.1 B3.2] Adaptive harness shape — driven by `classifyEffort()`,\n * pinned per-turn at turn start. Each shape implies a different\n * `thinking.budget_tokens` cap, soft block limit, and `update_todo`\n * permission. See SPEC 8 § \"Adaptive thresholds: harness shape gate\"\n * for the canonical mapping.\n */\nexport type HarnessShape = 'lean' | 'standard' | 'rich' | 'max';\n\n/**\n * [SPEC 8 v0.5.1 B3.2] Maps the engine's `ThinkingEffort` to the host-facing\n * harness shape. Single source of truth for the `low → lean`, `medium →\n * standard`, `high → rich`, `max → max` mapping. Exported so hosts (and\n * tests) get the mapping for free without re-implementing it.\n */\nexport function harnessShapeForEffort(effort: ThinkingEffort): HarnessShape {\n switch (effort) {\n case 'low':\n return 'lean';\n case 'medium':\n return 'standard';\n case 'high':\n return 'rich';\n case 'max':\n return 'max';\n }\n}\n\n/**\n * [SPEC 8 v0.5.1] One row in an `update_todo` payload. Mirrored from\n * `packages/engine/src/tools/update-todo.ts`. Kept here so hosts that\n * consume `EngineEvent` don't need to depend on the tool module.\n */\nexport interface TodoItem {\n id: string;\n label: string;\n status: 'pending' | 'in_progress' | 'completed';\n}\n\nexport type StopReason = 'end_turn' | 'tool_use' | 'max_tokens' | 'max_turns' | 'error';\n\n/**\n * [v1.4 Item 6] Describes a single input field on a `PendingAction` that\n * the host UI may let the user modify before approving. Carried on the\n * `pending_action` event so clients can render editable controls without\n * hard-coding per-tool field metadata. See\n * `packages/engine/src/tools/tool-modifiable-fields.ts` for the registry.\n */\nexport interface PendingActionModifiableField {\n /** Input key on the `PendingAction.input` object (e.g. \"amount\", \"to\"). */\n name: string;\n /**\n * UI hint for which control to render.\n * - `amount` — numeric input; UI shows a \"~Max\" hint when balance is known.\n * - `address` — Sui address input with paste/scan affordance.\n */\n kind: 'amount' | 'address';\n /** Optional asset symbol (e.g. \"USDC\", \"SUI\", \"vSUI\") for amount fields. */\n asset?: string;\n}\n\n/**\n * [SPEC 7 v0.4 Layer 2] One step inside a multi-write Payment Stream\n * `PendingAction`. Single-write actions never carry `steps[]`; the\n * legacy `toolName`/`toolUseId`/`input`/`attemptId` fields cover them.\n */\nexport interface PendingActionStep {\n toolName: string;\n toolUseId: string;\n /**\n * Per-step UUID v4 stamped at emit time. Hosts write one\n * `TurnMetrics` row per step keyed on this id; the resume route's\n * `updateMany({ where: { attemptId } })` extends trivially to the\n * per-step shape (loop `stepResults`, update each row).\n */\n attemptId: string;\n input: unknown;\n /** Per-step user-facing summary (rendered in the PermissionCard). */\n description: string;\n /** Optional modifiable fields for THIS step (rare in v1; sourced from `tool-modifiable-fields.ts`). */\n modifiableFields?: PendingActionModifiableField[];\n}\n\n/**\n * Serializable description of a write tool that needs user approval.\n * Stored in the session so the client can act on it in a separate request.\n */\nexport interface PendingAction {\n toolName: string;\n toolUseId: string;\n input: unknown;\n description: string;\n /** Full assistant message content from the LLM turn that triggered this action. */\n assistantContent: ContentBlock[];\n /** Results from auto-approved tools in the same LLM turn (e.g. balance_check). */\n completedResults?: Array<{ toolUseId: string; content: string; isError: boolean }>;\n /** Guard injections (hints/warnings) from pre-execution checks. */\n guardInjections?: Array<{ _gate: string; _hint?: string; _warning?: string }>;\n /**\n * [v1.4 Item 6] Fields the host UI may let the user modify before\n * approving. Sourced from `tool-modifiable-fields.ts`. Absent (or\n * empty) means the action is approve-or-deny only.\n */\n modifiableFields?: PendingActionModifiableField[];\n /**\n * [v1.4 Item 6] Monotonic turn index (assistant message count) at the\n * point this pending action was emitted. Hosts use it to update the\n * matching `TurnMetrics` row when the action resolves — see\n * `apps/web/app/api/engine/resume/route.ts` `updateMany` clause.\n */\n turnIndex: number;\n /**\n * [v1.4.2 — Day 3 / Spec Item 3] Per-yield random identifier (UUID v4)\n * stamped at the moment the engine emits this `pending_action`. Hosts\n * persist it on the `TurnMetrics` row at chat-time and key the resume\n * route's `updateMany` on it instead of `(sessionId, turnIndex)` — that\n * pair is ambiguous when the same turn yields a second pending action\n * (e.g. user edits → re-yield) or when a backfill leaves multiple rows\n * matching the pair, which is exactly the false-resolution bug Item 3\n * exists to kill. Also survives session persistence so the resume call\n * can read it back from the rehydrated `PendingAction`.\n *\n * **Bundles:** when `steps !== undefined` (multi-write Payment Stream),\n * the top-level `attemptId` mirrors `steps[0].attemptId` per SPEC 7\n * § Layer 2 line 463 (\"`steps[0]` mirrors the top-level\n * toolName/toolUseId/input/attemptId for hosts that haven't been\n * updated\"). Pre-bundle hosts that key TurnMetrics rows on top-level\n * `attemptId` collide cleanly with the bundle-aware host's step-0 row.\n * Bundle-aware hosts iterate `steps[]` and write N TurnMetrics rows\n * (one per step `attemptId`); the resume route's\n * `updateMany({ where: { attemptId } })` keys still work because the\n * route loops `stepResults` and updates each per-step row.\n */\n attemptId: string;\n /**\n * [SPEC 7 v0.4 Layer 2] When set, this `pending_action` represents a\n * multi-write Payment Stream. Single-step bundles are NOT created — the\n * engine emits the legacy single-write shape when N=1. Hosts that haven't\n * been updated read `toolName`/`toolUseId`/`input` (which mirror\n * `steps[0]`); newer hosts iterate `steps`.\n *\n * Bundleable tools (v1): `save_deposit`, `withdraw`, `borrow`,\n * `repay_debt`, `send_transfer`, `swap_execute`, `claim_rewards`,\n * `volo_stake`, `volo_unstake`. Non-bundleable: `pay_api`\n * (HTTPS coupling), `save_contact` (Postgres only).\n */\n steps?: PendingActionStep[];\n /**\n * [SPEC 7 v0.3 Quote-Refresh] Milliseconds since the upstream read tools\n * that fed this bundle's composition completed. Engine stamps at emit\n * time using `Date.now() - min(tool_result.timestamp)` across the listed\n * `regenerateInput.toolUseIds`. Host renders as a \"QUOTE Ns OLD\" badge in\n * the PermissionCard header. Only set on bundled `pending_action`s.\n */\n quoteAge?: number;\n /**\n * [SPEC 7 v0.3 Quote-Refresh] True when the bundle was composed from\n * re-runnable read tools (`swap_quote`, `rates_info`, `balance_check`,\n * `portfolio_analysis`). False when amounts came from user-provided\n * inputs that don't depend on upstream quotes. Single-write\n * `pending_action`s set this to `false` (regenerate is N≥2 only).\n */\n canRegenerate?: boolean;\n /**\n * [SPEC 7 v0.3 Quote-Refresh] Engine-internal payload listing which\n * upstream read `tool_use` ids to re-fire when the user taps REGENERATE.\n * Host echoes this back via `POST /api/engine/regenerate`; engine re-runs\n * each tool with the same input (no LLM call), rebuilds the bundle, and\n * emits a fresh `pending_action` with new per-step `attemptId`s.\n */\n regenerateInput?: {\n toolUseIds: string[];\n };\n}\n\n/**\n * Response from the client when resolving a pending action.\n * - `approved: false` → tool is declined, LLM is told \"user declined\"\n * - `approved: true` with `executionResult` → engine uses the client-provided result\n * (single-write path)\n * - `approved: true` with `stepResults` → engine pushes one `tool_result`\n * block per step into the conversation (bundle path)\n */\nexport interface PermissionResponse {\n approved: boolean;\n /** Single-write (legacy) execution result. Ignored when `stepResults` is set. */\n executionResult?: unknown;\n /**\n * [SPEC 7 v0.4 Layer 2] Per-step results for a bundle resume. One entry\n * per step in the original `PendingAction.steps`, in the same order.\n * Each carries the step's `toolUseId` + `attemptId` so the host's resume\n * route can update the matching `TurnMetrics` row.\n *\n * **Atomic semantics:** PTB execution is atomic at the Sui layer. If the\n * host detects a bundle-level failure, it should populate every entry\n * with `isError: true` carrying the same error message (so the LLM\n * narrates the failure once, not N times).\n */\n stepResults?: Array<{\n toolUseId: string;\n attemptId: string;\n result: unknown;\n isError: boolean;\n }>;\n}\n\n// ---------------------------------------------------------------------------\n// Tool types\n// ---------------------------------------------------------------------------\n\nexport type PermissionLevel = 'auto' | 'confirm' | 'explicit';\n\nexport interface ToolResult<T = unknown> {\n data: T;\n displayText?: string;\n}\n\nexport interface ToolContext {\n agent?: unknown; // T2000 instance — typed loosely to avoid circular dep at type level\n mcpManager?: unknown; // McpClientManager — typed loosely to avoid circular dep\n walletAddress?: string; // User's Sui wallet address (required for MCP reads)\n suiRpcUrl?: string; // Sui JSON-RPC URL for direct chain queries\n serverPositions?: ServerPositionData; // Pre-fetched positions from the server (avoids stale MCP data)\n /** Fresh on-chain position reader — bypasses MCP caching. If provided, read tools prefer this. */\n positionFetcher?: (address: string) => Promise<ServerPositionData>;\n /** Environment variables passed to tools (e.g. API keys not in process.env) */\n env?: Record<string, string>;\n signal?: AbortSignal;\n /** Token symbol → USD price map for USD-aware permission resolution (B.4). */\n priceCache?: Map<string, number>;\n /** Per-user permission config for USD-threshold write tool gating (B.4). */\n permissionConfig?: import('./permission-rules.js').UserPermissionConfig;\n /**\n * [v1.4] Cumulative USD already auto-executed in the current session.\n * Used by `resolvePermissionTier` to enforce `autonomousDailyLimit` —\n * downgrades `auto` to `confirm` when adding the incoming tool's USD\n * value would exceed the limit. Optional; omitted = unbounded.\n */\n sessionSpendUsd?: number;\n /**\n * [v1.4 BlockVision] Server-only BlockVision Indexer API key. Threaded\n * through from the host (`audric/apps/web` reads\n * `process.env.BLOCKVISION_API_KEY`). Forwarded to\n * `fetchAddressPortfolio` / `fetchTokenPrices` in `blockvision-prices.ts`.\n * When undefined / empty the price feed degrades to Sui RPC + the\n * hardcoded stable allow-list — wallets still render but non-stable\n * USD values are reported as `null`.\n */\n blockvisionApiKey?: string;\n /**\n * [v1.4 BlockVision] Per-request memoization of the BlockVision portfolio\n * response. Keyed by Sui address. Multiple read tools (`balance_check`,\n * `portfolio_analysis`) inside the same chat turn re-hit the same address;\n * sharing this Map across them avoids a second 200–500ms BlockVision RTT.\n * The `blockvision-prices` module also has its own TTL cache, so this is\n * primarily a fast-path optimisation rather than a correctness primitive.\n */\n portfolioCache?: Map<string, import('./blockvision-prices.js').AddressPortfolio>;\n /**\n * [SPEC 8 v0.5.1 B3.2] Per-tool-invocation HTTP attempt counter. The\n * engine's tool dispatcher attaches a fresh `{ attemptCount: 1 }` to\n * the context before calling each tool; retry wrappers\n * (`fetchBlockVisionWithRetry` and equivalents) bump\n * `retryStats.attemptCount` on every retry beyond the first attempt;\n * the dispatcher reads the final value back and surfaces it on the\n * `tool_result` event (only when > 1). Tools that don't use a retry\n * wrapper never observe a non-default value.\n *\n * The mutable-ref shape is deliberate — it lets retry wrappers deep\n * in the call stack record state without changing every caller's\n * return type.\n */\n retryStats?: { attemptCount: number };\n}\n\nexport interface ServerPositionData {\n savings: number;\n borrows: number;\n savingsRate: number;\n healthFactor: number | null;\n maxBorrow: number;\n pendingRewards: number;\n supplies: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n borrows_detail: Array<{ asset: string; amount: number; amountUsd: number; apy: number; protocol: string }>;\n}\n\nexport interface ToolJsonSchema {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n}\n\nexport interface ToolFlags {\n mutating?: boolean;\n requiresBalance?: boolean;\n affectsHealth?: boolean;\n irreversible?: boolean;\n producesArtifact?: boolean;\n costAware?: boolean;\n maxRetries?: number;\n /**\n * [SPEC 7 v0.4 Layer 2] Opt-in: this write tool can participate in a\n * multi-write Payment Stream. When the LLM emits ≥2 `tool_use` blocks\n * in a single assistant turn AND every block resolves to a `confirm`-tier\n * write tool with `bundleable: true`, the engine collapses them into one\n * `pending_action` with `steps[]` instead of yielding N times. Default\n * `false` — silently opt-out. v1 set: `save_deposit`, `withdraw`,\n * `borrow`, `repay_debt`, `send_transfer`, `swap_execute`,\n * `claim_rewards`, `volo_stake`, `volo_unstake`.\n *\n * **Permanently non-bundleable:**\n * - `pay_api` — recipient/amount/currency aren't known at LLM intent\n * time (gateway 402 challenge resolves them at route time, after a\n * network round-trip the engine has no knowledge of). PTB cannot be\n * composed at compose time.\n * - `save_contact` — Postgres-only, no on-chain effect.\n */\n bundleable?: boolean;\n}\n\nexport type PreflightResult =\n | { valid: true }\n | { valid: false; error: string };\n\nexport interface Tool<TInput = unknown, TOutput = unknown> {\n name: string;\n description: string;\n inputSchema: z.ZodType<TInput>;\n jsonSchema: ToolJsonSchema;\n call(input: TInput, context: ToolContext): Promise<ToolResult<TOutput>>;\n isConcurrencySafe: boolean;\n isReadOnly: boolean;\n permissionLevel: PermissionLevel;\n flags: ToolFlags;\n preflight?: (input: unknown) => PreflightResult;\n /** Max chars for the serialized tool result. Truncated with a re-call hint when exceeded. */\n maxResultSizeChars?: number;\n /** Custom truncation strategy. Falls back to generic slice + hint when omitted. */\n summarizeOnTruncate?: (result: string, maxChars: number) => string;\n /**\n * [v1.5.1] Whether `microcompact` may dedupe this tool's results across\n * multiple calls with identical input. Default `true` — most tools are\n * effectively pure within a session (price lookups, protocol info,\n * yield pools). Set to `false` for tools whose result depends on\n * mutable on-chain state and therefore changes after writes\n * (`balance_check`, `savings_info`, `health_check`,\n * `transaction_history`). Non-cacheable tools are excluded from the\n * `seen` map entirely, so neither this call nor any later call with\n * the same input gets replaced with a \"[Same result …]\" back-reference.\n */\n cacheable?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Thinking configuration (Anthropic extended thinking / adaptive)\n// ---------------------------------------------------------------------------\n\nexport type ThinkingEffort = 'low' | 'medium' | 'high' | 'max';\n\nexport type ThinkingConfig =\n | { type: 'disabled' }\n | { type: 'adaptive'; display?: 'summarized' | 'omitted' }\n | { type: 'enabled'; budgetTokens: number; display?: 'summarized' | 'omitted' };\n\nexport interface OutputConfig {\n effort?: ThinkingEffort;\n}\n\nexport interface SystemBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n}\n\nexport type SystemPrompt = string | SystemBlock[];\n\n// ---------------------------------------------------------------------------\n// Engine configuration\n// ---------------------------------------------------------------------------\n\nexport interface EngineConfig {\n provider: LLMProvider;\n agent?: unknown; // T2000 instance\n mcpManager?: unknown; // McpClientManager for MCP-based reads\n walletAddress?: string; // User's Sui wallet address (required for MCP reads)\n suiRpcUrl?: string; // Sui JSON-RPC URL for direct chain queries (wallet coins, etc.)\n serverPositions?: ServerPositionData; // Pre-fetched positions from the host app\n /** Fresh on-chain position reader — called per tool invocation, bypasses MCP caching. */\n positionFetcher?: (address: string) => Promise<ServerPositionData>;\n tools?: Tool[];\n systemPrompt?: SystemPrompt;\n model?: string;\n maxTurns?: number;\n maxTokens?: number;\n temperature?: number;\n /** Force tool usage on the first LLM turn (prevents text-only refusals). */\n toolChoice?: ToolChoice;\n thinking?: ThinkingConfig;\n outputConfig?: OutputConfig;\n /** Environment variables forwarded to tool context (API keys, URLs). */\n env?: Record<string, string>;\n costTracker?: {\n budgetLimitUsd?: number;\n inputCostPerToken?: number;\n outputCostPerToken?: number;\n };\n /** Guard runner configuration (RE-2.2). Omit to disable guards. */\n guards?: import('./guards.js').GuardConfig;\n /** Recipe registry for multi-step workflow guidance (RE-3.1). */\n recipes?: import('./recipes/index.js').RecipeRegistry;\n /** Context budget tracking configuration (RE-3.3). */\n contextBudget?: import('./context.js').ContextBudgetConfig;\n /** LLM-based summarizer for context compaction (RE-3.3). */\n contextSummarizer?: (messages: import('./types.js').Message[]) => Promise<string>;\n /** Token symbol → USD price map for USD-aware permission resolution (B.4). */\n priceCache?: Map<string, number>;\n /** Per-user permission config for USD-threshold write tool gating (B.4). */\n permissionConfig?: import('./permission-rules.js').UserPermissionConfig;\n /**\n * Saved contacts for the current user. Used by `guardAddressSource`\n * (a saved contact's address is considered a trusted source for\n * `send_transfer.to`) and by `permission-rules.resolvePermissionTier`\n * (sends to non-contact addresses always require confirmation,\n * regardless of amount). Hosts SHOULD also surface these in the\n * dynamic system prompt block so the LLM can resolve \"send to <name>\".\n */\n contacts?: ReadonlyArray<{ name: string; address: string }>;\n /**\n * [v1.4] Cumulative USD already auto-executed in the current session.\n * Forwarded to `ToolContext` and consulted by `resolvePermissionTier` to\n * enforce `autonomousDailyLimit`.\n */\n sessionSpendUsd?: number;\n /**\n * [v1.4 BlockVision] Server-only BlockVision Indexer API key. Forwarded\n * verbatim into `ToolContext.blockvisionApiKey` for read tools that hit\n * `api.blockvision.org` (`balance_check`, `portfolio_analysis`,\n * `token_prices`). When omitted, those tools degrade gracefully to a\n * Sui-RPC + hardcoded-stable fallback — see `blockvision-prices.ts`.\n */\n blockvisionApiKey?: string;\n /**\n * [v1.4 BlockVision] Per-request portfolio cache shared across read\n * tools in the same chat turn. Forwarded into `ToolContext.portfolioCache`.\n */\n portfolioCache?: Map<string, import('./blockvision-prices.js').AddressPortfolio>;\n /**\n * [v1.4] Fired after a write tool successfully auto-executes (no\n * confirmation required). Hosts use this to persist cumulative spend in\n * Redis and (post-v1.4 BlockVision swap) invalidate cross-session caches\n * keyed by the user's wallet address. Errors are caught — the tool\n * result is never blocked by a failure here.\n *\n * The `walletAddress` field is populated from the engine's\n * `config.walletAddress`; it's absent only on unauthenticated engines\n * (which never auto-execute a real write).\n */\n onAutoExecuted?: (info: {\n toolName: string;\n usdValue: number;\n walletAddress?: string;\n }) => void | Promise<void>;\n /**\n * [v1.4 Item 4] Per-guard observation hook. Forwarded to `runGuards`\n * and fired once per non-`pass` verdict so hosts can record guard\n * behaviour in `TurnMetrics.guardsFired` without re-implementing the\n * verdict→action mapping. Errors thrown by the host are caught.\n */\n onGuardFired?: (guard: import('./guards.js').GuardMetric) => void;\n /**\n * [v1.5] Map of write tool name → list of read tool names whose state\n * the write invalidates. After a successful write resumes via\n * `resumeWithToolResult`, the engine auto-runs each configured read\n * tool with empty input, pushes synthetic `tool_use` + `tool_result`\n * messages into the conversation, and yields `tool_result` events\n * with `wasPostWriteRefresh: true` BEFORE handing control back to the\n * LLM for narration.\n *\n * Why: writes change on-chain state. Without a fresh read, the LLM\n * narrates from the pre-write snapshot and frequently invents balance\n * totals. Auto-injecting fresh reads makes the hallucination class\n * physically impossible — the model has authoritative ground truth in\n * its context before generating the post-write sentence.\n *\n * Constraints:\n * - Refresh tools MUST be `isReadOnly` and `isConcurrencySafe`.\n * - Refresh runs only when the write succeeded (executionResult is\n * not `{ success: false }`); failed writes leave state unchanged\n * and refreshing would be misleading.\n * - Tools are invoked with empty input; refresh tools should accept\n * an empty object schema (e.g. `balance_check`, `savings_info`).\n * - Errors during refresh are non-fatal — a tool_result with\n * `isError: true` is still pushed so the LLM knows refresh failed.\n *\n * Example:\n * ```\n * {\n * save_deposit: ['balance_check', 'savings_info'],\n * send_transfer: ['balance_check'],\n * borrow: ['balance_check', 'savings_info', 'health_check'],\n * }\n * ```\n *\n * Omit (undefined / empty map) to disable post-write refresh entirely.\n */\n postWriteRefresh?: Record<string, string[]>;\n}\n\n// ---------------------------------------------------------------------------\n// LLM Provider interface (re-exported from providers/types for convenience)\n// ---------------------------------------------------------------------------\n\nexport interface LLMProvider {\n chat(params: ChatParams): AsyncGenerator<ProviderEvent>;\n}\n\nexport type ToolChoice = 'auto' | 'any' | { type: 'tool'; name: string };\n\nexport interface ChatParams {\n messages: Message[];\n systemPrompt: SystemPrompt;\n tools: ToolDefinition[];\n model?: string;\n maxTokens?: number;\n temperature?: number;\n toolChoice?: ToolChoice;\n thinking?: ThinkingConfig;\n outputConfig?: OutputConfig;\n signal?: AbortSignal;\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n input_schema: ToolJsonSchema;\n}\n\nexport type ProviderEvent =\n | { type: 'thinking_delta'; text: string; blockIndex: number }\n | {\n type: 'thinking_done';\n blockIndex: number;\n thinking: string;\n signature: string;\n // [SPEC 8 v0.5.1] populated by the provider when a parseable\n // <eval_summary> marker was found in the thinking text.\n summaryMode?: boolean;\n evaluationItems?: import('./eval-summary.js').EvaluationItem[];\n }\n | { type: 'redacted_thinking'; data: string }\n | { type: 'text_delta'; text: string }\n | { type: 'tool_use_start'; id: string; name: string }\n | { type: 'tool_use_delta'; id: string; partialJson: string }\n | { type: 'tool_use_done'; id: string; name: string; input: unknown }\n | {\n type: 'message_start';\n messageId: string;\n model: string;\n }\n | {\n type: 'usage';\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n }\n | { type: 'stop'; reason: StopReason };\n","import type { EngineEvent, HarnessShape, PendingAction, StopReason, TodoItem } from './types.js';\nimport type { EvaluationItem } from './eval-summary.js';\n\n// ---------------------------------------------------------------------------\n// SSE event format — serialisable subset of EngineEvent\n// ---------------------------------------------------------------------------\n\nexport type SSEEvent =\n // [SPEC 8 v0.5.1] blockIndex identifies the thinking block this delta belongs to.\n | { type: 'thinking_delta'; text: string; blockIndex: number }\n | {\n type: 'thinking_done';\n blockIndex: number;\n signature?: string;\n // [SPEC 8 v0.5.1] HowIEvaluated block fields — populated when the\n // thinking text contained a parseable <eval_summary> marker.\n summaryMode?: boolean;\n evaluationItems?: EvaluationItem[];\n }\n | { type: 'text_delta'; text: string }\n | { type: 'tool_start'; toolName: string; toolUseId: string; input: unknown }\n | {\n type: 'tool_result';\n toolName: string;\n toolUseId: string;\n result: unknown;\n isError: boolean;\n // [v1.4] flags carried through unchanged from EngineEvent.tool_result\n wasEarlyDispatched?: boolean;\n resultDeduped?: boolean;\n // [v1.5] true when injected by the engine's post-write refresh\n // (see EngineConfig.postWriteRefresh)\n wasPostWriteRefresh?: boolean;\n // [SPEC 8 v0.5.1 B3.2] HTTP attempt count — set only when > 1 so\n // hosts can render \"TOOL · attempt N · 1.4s\" without header noise\n // on the common single-attempt path.\n attemptCount?: number;\n }\n | { type: 'pending_action'; action: PendingAction }\n | { type: 'turn_complete'; stopReason: StopReason }\n | { type: 'usage'; inputTokens: number; outputTokens: number; cacheReadTokens?: number; cacheWriteTokens?: number }\n | { type: 'error'; message: string }\n | { type: 'canvas'; template: string; data: unknown; title: string; toolUseId: string }\n // [SPEC 8 v0.5.1] todo_update side-channel event paired to every\n // update_todo tool call. Mirrors EngineEvent.todo_update.\n | { type: 'todo_update'; items: TodoItem[]; toolUseId: string }\n // [SPEC 8 v0.5.1] tool_progress mid-execution signal from long-running\n // tools (Cetus swap_execute, protocol_deep_dive, portfolio_analysis).\n // Engine wiring lands with the Cetus integration in a follow-on slice.\n | { type: 'tool_progress'; toolUseId: string; toolName: string; message: string; pct?: number }\n // [SPEC 8 v0.5.1, D2] pending_input reserved for SPEC 9 v0.1.2 inline\n // forms. Engine doesn't emit under SPEC 8; reservation is forward-compat.\n | { type: 'pending_input'; schema: unknown; inputId: string; prompt?: string }\n // [SPEC 8 v0.5.1 B3.2] One-shot per-turn harness shape declaration.\n // Mirrors EngineEvent.harness_shape — see types.ts for full contract.\n | { type: 'harness_shape'; shape: HarnessShape; rationale: string };\n\n// ---------------------------------------------------------------------------\n// Serialise: SSEEvent → SSE text\n// ---------------------------------------------------------------------------\n\nexport function serializeSSE(event: SSEEvent): string {\n const data = JSON.stringify(event);\n return `event: ${event.type}\\ndata: ${data}\\n\\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Deserialise: SSE text → SSEEvent\n// ---------------------------------------------------------------------------\n\nexport function parseSSE(raw: string): SSEEvent | null {\n const dataLine = raw.split('\\n').find((l) => l.startsWith('data: '));\n if (!dataLine) return null;\n try {\n return JSON.parse(dataLine.slice(6)) as SSEEvent;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stream adapter: engine async generator → SSE text stream\n// ---------------------------------------------------------------------------\n\nexport async function* engineToSSE(\n events: AsyncGenerator<EngineEvent>,\n): AsyncGenerator<string> {\n for await (const event of events) {\n if (event.type === 'error') {\n yield serializeSSE({ type: 'error', message: event.error.message });\n } else {\n yield serializeSSE(event as SSEEvent);\n }\n }\n}\n","import type { Message, PendingAction } from './types.js';\nimport type { CostSnapshot } from './cost.js';\n\n// ---------------------------------------------------------------------------\n// Session data\n// ---------------------------------------------------------------------------\n\nexport interface SessionData {\n id: string;\n messages: Message[];\n usage: CostSnapshot;\n createdAt: number;\n updatedAt: number;\n /** Set when the engine is paused waiting for user approval of a write action. */\n pendingAction?: PendingAction | null;\n metadata?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Session store interface — implement for different backends\n// ---------------------------------------------------------------------------\n\nexport interface SessionStore {\n /** Load a session by ID. Returns null if not found or expired. */\n get(sessionId: string): Promise<SessionData | null>;\n\n /** Save or update a session. */\n set(session: SessionData): Promise<void>;\n\n /** Delete a session. */\n delete(sessionId: string): Promise<void>;\n\n /** Check if a session exists. */\n exists(sessionId: string): Promise<boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// MemorySessionStore — for development and testing\n// ---------------------------------------------------------------------------\n\nexport class MemorySessionStore implements SessionStore {\n private store = new Map<string, { data: SessionData; expiresAt: number }>();\n private readonly ttlMs: number;\n\n constructor(opts?: { ttlMs?: number }) {\n this.ttlMs = opts?.ttlMs ?? 24 * 60 * 60 * 1000; // 24h default\n }\n\n async get(sessionId: string): Promise<SessionData | null> {\n const entry = this.store.get(sessionId);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return null;\n }\n return structuredClone(entry.data);\n }\n\n async set(session: SessionData): Promise<void> {\n this.store.set(session.id, {\n data: structuredClone(session),\n expiresAt: Date.now() + this.ttlMs,\n });\n }\n\n async delete(sessionId: string): Promise<void> {\n this.store.delete(sessionId);\n }\n\n async exists(sessionId: string): Promise<boolean> {\n const entry = this.store.get(sessionId);\n if (!entry) return false;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(sessionId);\n return false;\n }\n return true;\n }\n\n /** For testing: number of active (non-expired) sessions. */\n get size(): number {\n this.evictExpired();\n return this.store.size;\n }\n\n private evictExpired(): void {\n const now = Date.now();\n for (const [id, entry] of this.store) {\n if (now > entry.expiresAt) this.store.delete(id);\n }\n }\n}\n","import { readFileSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport yaml from 'js-yaml';\nimport { z } from 'zod';\nimport type { Recipe, RecipeStep } from './types.js';\nimport { isBundleableTool } from '../tool-flags.js';\n\nconst StepRequirementSchema = z.object({\n step: z.string().optional(),\n field: z.string().optional(),\n confirmation: z.boolean().optional(),\n});\n\nconst OnErrorSchema = z.object({\n action: z.enum(['abort', 'refuse', 'report', 'retry']),\n message: z.string(),\n suggest: z.string().optional(),\n});\n\nconst StepSchema: z.ZodType<RecipeStep> = z.object({\n name: z.string().min(1),\n tool: z.string().optional(),\n service: z.string().optional(),\n purpose: z.string().min(1),\n cost: z.string().optional(),\n output: z.object({ type: z.string(), key: z.string() }).optional(),\n gate: z.enum(['none', 'preview', 'review', 'estimate']).optional(),\n gate_prompt: z.string().optional(),\n requires: z.array(StepRequirementSchema).optional(),\n rules: z.array(z.string()).optional(),\n condition: z.string().optional(),\n notes: z.string().optional(),\n flags: z.record(z.unknown()).optional() as z.ZodType<RecipeStep['flags']>,\n on_error: OnErrorSchema.optional(),\n input_template: z.record(z.string()).optional(),\n cost_per_unit: z.string().optional(),\n bundle: z.boolean().optional(),\n});\n\nconst RecipeSchema = z.object({\n name: z.string().min(1),\n description: z.string().min(1),\n triggers: z.array(z.string().min(1)).min(1),\n services: z.array(z.string()).optional(),\n prerequisites: z.array(z.object({ field: z.string(), prompt: z.string() })).optional(),\n steps: z.array(StepSchema).min(1),\n}).refine(\n (r) => {\n const names = r.steps.map((s) => s.name);\n return new Set(names).size === names.length;\n },\n { message: 'Step names must be unique within a recipe' },\n).refine(\n (r) => {\n // [SPEC 7 P2.5 Layer 4] `bundle: true` steps MUST reference a\n // bundleable confirm-tier write tool. See `isBundleableTool` in\n // `tool-flags.ts` for the v1 set. Catches: read tools in a bundle,\n // auto-tier writes, `pay_api` / `save_contact` (non-bundleable\n // confirm), unknown tool names, missing `tool:` field.\n for (const step of r.steps) {\n if (step.bundle === true) {\n if (!step.tool) return false;\n if (!isBundleableTool(step.tool)) return false;\n }\n }\n return true;\n },\n {\n message:\n 'Steps with bundle: true must reference a bundleable confirm-tier write tool. ' +\n 'Allowed: save_deposit, withdraw, borrow, repay_debt, send_transfer, ' +\n 'swap_execute, claim_rewards, volo_stake, volo_unstake. ' +\n 'Forbidden: pay_api, save_contact, any read tool, any auto-tier write.',\n },\n);\n\n/**\n * Load all recipe YAML files from a directory.\n * Throws on validation errors — recipes should fail at load time, not runtime.\n */\nexport function loadRecipes(yamlDir: string): Recipe[] {\n const files = readdirSync(yamlDir).filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'));\n const recipes: Recipe[] = [];\n\n for (const file of files) {\n const content = readFileSync(join(yamlDir, file), 'utf-8');\n const raw = yaml.load(content);\n const parsed = RecipeSchema.parse(raw);\n recipes.push(parsed as Recipe);\n }\n\n return recipes;\n}\n\n/**\n * Parse a single recipe from a YAML string (useful for embedded/bundled recipes).\n */\nexport function parseRecipe(yamlContent: string): Recipe {\n const raw = yaml.load(yamlContent);\n return RecipeSchema.parse(raw) as Recipe;\n}\n","import type { Recipe } from './types.js';\nimport { loadRecipes, parseRecipe } from './loader.js';\n\n/**\n * Stores loaded recipes and matches user messages to the most specific recipe\n * using longest-trigger-match-wins.\n */\nexport class RecipeRegistry {\n private recipes: Recipe[] = [];\n\n /** Load all recipes from a directory of YAML files. */\n loadDir(yamlDir: string): void {\n this.recipes.push(...loadRecipes(yamlDir));\n }\n\n /** Register a single recipe from a YAML string. */\n loadYaml(yamlContent: string): void {\n this.recipes.push(parseRecipe(yamlContent));\n }\n\n /** Register a pre-parsed Recipe object. */\n register(recipe: Recipe): void {\n this.recipes.push(recipe);\n }\n\n /** All loaded recipes. */\n all(): readonly Recipe[] {\n return this.recipes;\n }\n\n /**\n * Match a user message to the most specific recipe.\n * Longest trigger phrase match wins. Returns null if no match.\n */\n match(userMessage: string): Recipe | null {\n const normalized = userMessage.toLowerCase().trim();\n let best: Recipe | null = null;\n let bestLength = 0;\n\n for (const recipe of this.recipes) {\n for (const trigger of recipe.triggers) {\n const triggerLower = trigger.toLowerCase();\n if (normalized.includes(triggerLower) && triggerLower.length > bestLength) {\n best = recipe;\n bestLength = triggerLower.length;\n }\n }\n }\n\n return best;\n }\n\n /**\n * Format a matched recipe as a compact context block for the system prompt.\n * Injected dynamically — only when the recipe matches.\n */\n toPromptContext(recipe: Recipe): string {\n const lines: string[] = [\n `## Active Recipe: ${recipe.name}`,\n recipe.description,\n 'Follow these steps:',\n ];\n\n for (let i = 0; i < recipe.steps.length; i++) {\n const step = recipe.steps[i];\n const num = i + 1;\n const toolNote = step.tool ? ` → ${step.tool}` : '';\n const serviceNote = step.service ? ` (${step.service})` : '';\n const costNote = step.cost ? ` — ${step.cost}` : '';\n const gateNote = step.gate && step.gate !== 'none'\n ? ` [GATE: ${step.gate}]`\n : '';\n\n let line = `${num}. ${step.name}${toolNote}${serviceNote}${costNote}${gateNote}`;\n\n if (step.gate_prompt) {\n line += ` — \"${step.gate_prompt}\"`;\n }\n\n lines.push(line);\n\n if (step.rules?.length) {\n for (const rule of step.rules) {\n lines.push(` - ${rule}`);\n }\n }\n\n if (step.notes) {\n lines.push(` Note: ${step.notes}`);\n }\n\n if (step.on_error) {\n lines.push(` On error: ${step.on_error.action} — ${step.on_error.message}`);\n }\n\n if (step.condition) {\n lines.push(` Condition: ${step.condition}`);\n }\n }\n\n if (recipe.prerequisites?.length) {\n lines.push('Prerequisites (ask before starting):');\n for (const pre of recipe.prerequisites) {\n lines.push(`- ${pre.field}: \"${pre.prompt}\"`);\n }\n }\n\n return lines.join('\\n');\n }\n}\n","import type { ThinkingEffort } from './types.js';\nimport type { Recipe } from './recipes/index.js';\n\n/**\n * Routes each turn to the appropriate thinking effort level based on\n * message content, matched recipe, and session write history.\n *\n * Heuristics only — no LLM call. Cost per session becomes proportional\n * to actual query complexity rather than a fixed budget.\n */\nexport function classifyEffort(\n model: string,\n userMessage: string,\n matchedRecipe: Recipe | null,\n sessionWriteCount: number,\n): ThinkingEffort {\n const supportsMax = model.includes('opus-4-6');\n const msg = userMessage.toLowerCase();\n\n if (supportsMax) {\n if (matchedRecipe?.name === 'portfolio_rebalance') return 'max';\n if (matchedRecipe?.name === 'emergency_withdraw') return 'max';\n if (/rebalance|reallocate|dca setup|close.*position/i.test(msg)) return 'max';\n }\n\n if (matchedRecipe && matchedRecipe.steps.length >= 3) return 'high';\n if (matchedRecipe?.name === 'safe_borrow' || matchedRecipe?.name === 'bulk_mail') return 'high';\n if (sessionWriteCount > 0 && /borrow|withdraw|send|swap/i.test(msg)) return 'high';\n\n // Any matched recipe means multi-step tool work — never route to Haiku\n // regardless of message wording. Haiku struggles with the synthesis these\n // recipes require and ends up looping through more tool rounds than Sonnet,\n // costing more in practice. (Confirmed by 0.46.x TurnMetrics baseline:\n // low-effort Haiku turns averaged $0.040 vs $0.017 for medium-effort Sonnet.)\n if (matchedRecipe) return 'medium';\n\n // Pure simple lookups — single-fact questions Haiku handles well.\n // Explicitly excludes `show|history|all|list|everything` which imply\n // multi-record synthesis (the original regex sent these to Haiku and\n // they bottomed out the cost/latency curves).\n if (/\\b(balance|rate|how much|what is|check|price|apy|hf)\\b/i.test(msg)) return 'low';\n if (!/\\b(deposit|send|swap|borrow|withdraw|save|pay|transfer|show|history|all|list|everything|report|summary|breakdown)\\b/i.test(msg)) return 'low';\n\n return 'medium';\n}\n","// ---------------------------------------------------------------------------\n// <eval_summary> marker parser (SPEC 8 v0.5.1, P3.2 slice 7)\n//\n// The system prompt teaches the LLM to emit a single `<eval_summary>...\n// </eval_summary>` block inside its final thinking burst on\n// write-recommendation turns. The block carries structured rows the host\n// renders as the \"✦ HOW I EVALUATED THIS\" trust card (the highest-impact\n// UX in `audric/audric_demos_v2/demos/01-save-50.html`).\n//\n// Format taught to the LLM:\n//\n// <eval_summary>\n// {\n// \"items\": [\n// { \"label\": \"Health Factor\", \"status\": \"good\", \"note\": \"1.85 → 1.62, above 1.20 threshold\" },\n// { \"label\": \"Slippage cap\", \"status\": \"good\", \"note\": \"0.5% on 100 USDC → max $0.50 loss\" },\n// { \"label\": \"Daily spend\", \"status\": \"warning\", \"note\": \"$8 of $50 daily cap used\" }\n// ]\n// }\n// </eval_summary>\n//\n// Parser behavior:\n// - Returns null when no marker is present (no extra cost on every turn).\n// - Extracts the FIRST marker only — multiple in one block is a violation\n// logged at the engine telemetry level via `evalSummaryViolationsCount`.\n// - Returns null when the inner JSON is malformed — the LLM saw a render\n// mistake; the host falls back to standard ThinkingBlock rendering.\n// - Tolerates whitespace and newlines around the JSON payload.\n//\n// The engine wires this in `providers/anthropic.ts` at the\n// `content_block_stop` handler for thinking blocks, populating the new\n// `summaryMode` + `evaluationItems` fields on `thinking_done` events.\n// ---------------------------------------------------------------------------\n\nexport type EvaluationStatus = 'good' | 'warning' | 'critical' | 'info';\n\nexport interface EvaluationItem {\n label: string;\n status: EvaluationStatus;\n note?: string;\n}\n\nexport interface EvalSummaryParseResult {\n /** Always true when this object is returned (vs null when absent). */\n summaryMode: true;\n /** The structured rows the host renders inside the trust card. */\n evaluationItems: EvaluationItem[];\n /** Count of markers detected — >1 indicates an LLM compliance violation. */\n markerCount: number;\n}\n\nconst MARKER_REGEX = /<eval_summary>([\\s\\S]*?)<\\/eval_summary>/g;\nconst VALID_STATUSES: ReadonlySet<EvaluationStatus> = new Set([\n 'good',\n 'warning',\n 'critical',\n 'info',\n]);\n\n/**\n * Scan a thinking-block text for one or more `<eval_summary>` markers.\n *\n * - Returns null when no marker is present, or when the first marker's\n * JSON is malformed (host falls back to standard rendering).\n * - Returns a parsed result when at least one marker contains valid JSON.\n * `markerCount` reflects the total number of markers seen so the\n * engine can emit a `evalSummaryViolationsCount` telemetry counter\n * when N > 1 (LLM is supposed to emit at most one per turn).\n *\n * The function is pure — safe to call per-thinking-block.\n */\nexport function parseEvalSummary(thinkingText: string): EvalSummaryParseResult | null {\n if (!thinkingText.includes('<eval_summary>')) return null;\n\n const matches: string[] = [];\n for (const match of thinkingText.matchAll(MARKER_REGEX)) {\n matches.push(match[1] ?? '');\n }\n\n if (matches.length === 0) return null;\n\n const firstPayload = matches[0].trim();\n let parsed: unknown;\n try {\n parsed = JSON.parse(firstPayload);\n } catch {\n return null;\n }\n\n if (!parsed || typeof parsed !== 'object') return null;\n const items = (parsed as { items?: unknown }).items;\n if (!Array.isArray(items)) return null;\n\n const evaluationItems: EvaluationItem[] = [];\n for (const item of items) {\n if (!item || typeof item !== 'object') continue;\n const i = item as Record<string, unknown>;\n if (typeof i.label !== 'string' || i.label.trim().length === 0) continue;\n if (typeof i.status !== 'string' || !VALID_STATUSES.has(i.status as EvaluationStatus)) continue;\n const out: EvaluationItem = {\n label: i.label,\n status: i.status as EvaluationStatus,\n };\n if (typeof i.note === 'string' && i.note.length > 0) {\n out.note = i.note;\n }\n evaluationItems.push(out);\n }\n\n if (evaluationItems.length === 0) return null;\n\n return {\n summaryMode: true,\n evaluationItems,\n markerCount: matches.length,\n };\n}\n","import type { SystemBlock } from './types.js';\n\n/**\n * Build a cacheable system prompt array from static and dynamic parts.\n *\n * Anthropic caches system prompt blocks marked with `cache_control: { type: 'ephemeral' }`.\n * Static blocks (identity, tool descriptions) are cached across turns. Dynamic blocks\n * (user profile, positions, state) change per-turn and are NOT cached.\n *\n * Cache breakpoints are placed at the end of each static block — Anthropic caches\n * from the start of the prompt up to the last cache_control marker.\n */\nexport function buildCachedSystemPrompt(\n staticParts: string[],\n dynamicPart?: string,\n): SystemBlock[] {\n const blocks: SystemBlock[] = staticParts.map((text, i) => ({\n type: 'text' as const,\n text,\n ...(i === staticParts.length - 1 && { cache_control: { type: 'ephemeral' as const } }),\n }));\n\n if (dynamicPart) {\n blocks.push({ type: 'text', text: dynamicPart });\n }\n\n return blocks;\n}\n","/**\n * Intelligence Layer prompt builders (F1, F2, F5).\n * Pure functions — no DB or Redis dependencies.\n * Consumed by the host app's dynamic context assembly.\n */\n\n// ---------------------------------------------------------------------------\n// F1: User Financial Profile types + context builder\n// ---------------------------------------------------------------------------\n\nexport interface UserFinancialProfile {\n userId: string;\n riskAppetite: 'conservative' | 'moderate' | 'aggressive';\n financialLiteracy: 'novice' | 'intermediate' | 'advanced';\n prefersBriefResponses: boolean;\n prefersExplainers: boolean;\n currencyFraming: 'usdc' | 'fiat';\n primaryGoals: string[];\n knownPatterns: string[];\n riskConfidence: number;\n literacyConfidence: number;\n lastInferredAt: Date | null;\n}\n\n/**\n * Build system prompt context from a user's financial profile.\n * Returns empty string if profile is absent or confidence is too low.\n * Takes the profile object directly — no DB query.\n */\nexport function buildProfileContext(profile: UserFinancialProfile | null): string {\n if (!profile || profile.riskConfidence < 0.3) return '';\n\n const lines: string[] = ['User financial profile (inferred from conversation history):'];\n\n if (profile.riskConfidence >= 0.5) {\n lines.push(`- Risk appetite: ${profile.riskAppetite}`);\n }\n if (profile.literacyConfidence >= 0.5) {\n lines.push(`- Financial literacy: ${profile.financialLiteracy}`);\n if (profile.financialLiteracy === 'advanced') {\n lines.push(' → Skip basic DeFi explanations (health factor, APY, etc). User knows these.');\n }\n if (profile.financialLiteracy === 'novice') {\n lines.push(' → Always explain DeFi concepts in plain language.');\n }\n }\n if (profile.currencyFraming === 'fiat') {\n lines.push('- Frame amounts as dollars (e.g. \"$50\" not \"50 USDC\")');\n }\n if (profile.prefersBriefResponses) {\n lines.push('- Prefers brief responses — be concise');\n }\n if (profile.primaryGoals.length > 0) {\n lines.push(`- Stated goals: ${profile.primaryGoals.join(', ')}`);\n }\n if (profile.knownPatterns.length > 0) {\n lines.push(`- Behavioural patterns: ${profile.knownPatterns.join(', ')}`);\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// F2: In-Session Proactive Awareness\n// ---------------------------------------------------------------------------\n\nexport function buildProactivenessInstructions(profile: UserFinancialProfile | null): string {\n const brevityGuidance = profile?.prefersBriefResponses\n ? 'This user prefers brevity — only surface context if urgent or directly actionable.'\n : 'Surface relevant context when criteria are met.';\n\n const styleGuidance = profile?.financialLiteracy === 'novice'\n ? 'Frame observations in plain English, no DeFi jargon.'\n : 'Technical framing is fine.';\n\n return `Proactive awareness:\nAfter completing the user's request, consider whether ONE additional piece of financial\ncontext is worth mentioning. ${brevityGuidance}\n\n✓ Mention if:\n- Their savings goal is materially off-track (>20% behind pace)\n- Yield rate changed significantly since last session (>0.5%)\n- They have idle USDC >$50 sitting for >48h\n- An action they just took interacts with an active goal or debt position\n- A pattern would materially benefit from their attention\n\n✗ Do NOT mention if:\n- Tangentially related but not actionable\n- Already surfaced this session\n- Requires more explanation than the original answer\n- Would seem pushy or sales-y\n\n${styleGuidance}\nFormat: One sentence maximum, after main response, separated by a line break.\nFrame as observation, not advice: \"Your Tokyo goal is $80 behind pace.\" — not \"You should deposit more.\"`;\n}\n\n// ---------------------------------------------------------------------------\n// F5: Post-Action Self-Evaluation\n// ---------------------------------------------------------------------------\n\nexport function buildSelfEvaluationInstruction(): string {\n return `Self-evaluation (apply silently before composing your response):\n\n1. ACCURACY — Quote exact values from tool results, not estimates or rounded figures.\n Never combine post-action tool results with pre-action snapshot numbers.\n If the tool returned an error, label it as an error — do not paraphrase it as success.\n\n2. STATE CONSISTENCY — Describe the actual outcome of all steps.\n Partial success (swap ok, deposit failed): describe both clearly.\n Never describe a failed action as if it succeeded.\n\n3. COMPLETENESS — If the user asked multiple things, answer all of them.\n If you couldn't complete something, explain why and what the current state is.\n\n4. TONE — Match tone to outcome.\n Success: confirming and forward-looking.\n Failure: clear about what failed, unchanged, and what to do next.\n Warning: specific risk, not generic caution.\n\nIf any check fails, rewrite before outputting.`;\n}\n","/**\n * Conversation State Machine — F4 of the Intelligence Layer.\n *\n * Types, pure context builder, and a generic state manager interface.\n * The Redis implementation lives in the host app (audric) since it depends on @upstash/redis.\n */\n\n// ---------------------------------------------------------------------------\n// State definitions\n// ---------------------------------------------------------------------------\n\nexport type ConversationState =\n | { type: 'idle' }\n\n | {\n type: 'mid_recipe';\n recipeName: string;\n currentStep: number;\n totalSteps: number;\n completedStepOutputs: Record<string, Record<string, string | number>>;\n startedAt: number;\n }\n\n | {\n type: 'awaiting_confirmation';\n action: string;\n amount?: number;\n recipient?: string;\n proposedAt: number;\n expiresAt: number;\n }\n\n | {\n type: 'post_error';\n failedAction: string;\n errorMessage: string;\n occurredAt: number;\n partialState?: string;\n }\n\n | {\n type: 'post_liquidation_warning';\n healthFactor: number;\n warnedAt: number;\n }\n\n | {\n type: 'onboarding';\n sessionNumber: number;\n hasBalance: boolean;\n hasSavedBefore: boolean;\n };\n\nexport type StateType = ConversationState['type'];\n\n// ---------------------------------------------------------------------------\n// State manager interface (host app provides the implementation)\n// ---------------------------------------------------------------------------\n\nexport interface ConversationStateStore {\n get(): Promise<ConversationState>;\n set(state: ConversationState): Promise<void>;\n transition(to: ConversationState): Promise<void>;\n reset(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Context builder — pure function, no I/O\n// ---------------------------------------------------------------------------\n\nexport function buildStateContext(state: ConversationState): string {\n switch (state.type) {\n case 'idle':\n return '';\n\n case 'mid_recipe': {\n const elapsed = Math.round((Date.now() - state.startedAt) / 60_000);\n const outputs = JSON.stringify(state.completedStepOutputs);\n return [\n `Conversation state: MID-RECIPE`,\n `Active recipe: ${state.recipeName} (step ${state.currentStep + 1} of ${state.totalSteps})`,\n `Started: ${elapsed} minutes ago`,\n `Completed step key outputs: ${outputs}`,\n `If the user asks an unrelated question: answer briefly, then offer to continue the ${state.recipeName} flow.`,\n `If the user says \"cancel\" or \"stop\": confirm you have abandoned the recipe and return to idle.`,\n ].join('\\n');\n }\n\n case 'awaiting_confirmation': {\n const expiryMins = Math.max(0, Math.round((state.expiresAt - Date.now()) / 60_000));\n const expired = state.expiresAt < Date.now();\n return [\n `Conversation state: AWAITING CONFIRMATION`,\n `Proposed action: ${state.action}${state.amount ? ` for $${state.amount}` : ''}${state.recipient ? ` to ${state.recipient}` : ''}`,\n expired\n ? `Status: EXPIRED — ask if user still wants to proceed`\n : `Expires in: ${expiryMins} minutes`,\n `\"yes/confirm/do it\" → execute. \"no/cancel/wait\" → abort, reset to idle.`,\n ].join('\\n');\n }\n\n case 'post_error':\n return [\n `Conversation state: POST-ERROR`,\n `Failed action: ${state.failedAction}`,\n `Error: ${state.errorMessage}`,\n state.partialState ? `Partial state: ${state.partialState}` : '',\n `Acknowledge failure clearly. Offer a specific recovery path if one exists.`,\n `This state clears automatically on the next successful action.`,\n ].filter(Boolean).join('\\n');\n\n case 'post_liquidation_warning':\n return [\n `Conversation state: LIQUIDATION WARNING ACTIVE`,\n `Health factor: ${state.healthFactor.toFixed(2)} — below safe threshold`,\n `Prioritise debt repayment or collateral deposit.`,\n `Do not proceed with any action that would further reduce health factor.`,\n ].join('\\n');\n\n case 'onboarding':\n return [\n `Conversation state: ONBOARDING (session ${state.sessionNumber})`,\n state.sessionNumber === 1\n ? 'First session — introduce capabilities through context, not a feature list.'\n : `Returning user — ${state.hasSavedBefore ? 'has saved before' : 'has not saved yet'}.`,\n ].join('\\n');\n\n default:\n return '';\n }\n}\n","import type { Tool, ToolContext } from './types.js';\nimport { getDefaultTools } from './tools/index.js';\n\n// ---------------------------------------------------------------------------\n// MCP tool descriptor — the shape MCP servers need to register tools\n// ---------------------------------------------------------------------------\n\nexport interface McpToolDescriptor {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n handler: (args: Record<string, unknown>) => Promise<{\n content: Array<{ type: 'text'; text: string }>;\n isError?: boolean;\n }>;\n}\n\n// ---------------------------------------------------------------------------\n// Convert engine tools → MCP tool descriptors\n// ---------------------------------------------------------------------------\n\n/**\n * Builds MCP-compatible tool descriptors from engine tools.\n * Each tool's `call()` is wrapped to return the MCP response format.\n *\n * Usage with @modelcontextprotocol/sdk:\n * ```\n * const descriptors = buildMcpTools(context);\n * for (const desc of descriptors) {\n * server.tool(desc.name, desc.description, desc.inputSchema, desc.handler);\n * }\n * ```\n */\nexport function buildMcpTools(\n context: ToolContext,\n tools?: Tool[],\n): McpToolDescriptor[] {\n const engineTools = tools ?? getDefaultTools();\n\n return engineTools.map((tool) => ({\n name: `audric_${tool.name}`,\n description: tool.description,\n inputSchema: tool.jsonSchema as unknown as Record<string, unknown>,\n\n async handler(args: Record<string, unknown>) {\n try {\n const parsed = tool.inputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n error: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(', ')}`,\n }),\n }],\n isError: true,\n };\n }\n\n const result = await tool.call(parsed.data, context);\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(result.data),\n }],\n };\n } catch (err) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n error: err instanceof Error ? err.message : 'Tool execution failed',\n }),\n }],\n isError: true,\n };\n }\n },\n }));\n}\n\n/**\n * Register all engine tools with an MCP server instance.\n * Convenience wrapper for the common pattern.\n */\nexport function registerEngineTools(\n server: { tool: (name: string, description: string, schema: Record<string, unknown>, handler: (args: Record<string, unknown>) => Promise<unknown>) => void },\n context: ToolContext,\n tools?: Tool[],\n): void {\n const descriptors = buildMcpTools(context, tools);\n for (const desc of descriptors) {\n server.tool(desc.name, desc.description, desc.inputSchema, desc.handler);\n }\n}\n","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type { Tool as McpToolDef } from '@modelcontextprotocol/sdk/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface McpServerConfig {\n /** Human-readable server name, used as tool namespace prefix. */\n name: string;\n /** MCP server URL (Streamable HTTP or SSE endpoint). */\n url: string;\n /** Transport type. Defaults to 'streamable-http'. */\n transport?: 'streamable-http' | 'sse';\n /** Response cache TTL in ms. Default 30_000 (30s). */\n cacheTtlMs?: number;\n /** Whether all tools from this server are read-only. Default true. */\n readOnly?: boolean;\n}\n\nexport interface McpServerConnection {\n config: McpServerConfig;\n client: Client;\n transport: Transport;\n tools: McpToolDef[];\n status: 'connected' | 'disconnected' | 'error';\n lastError?: string;\n}\n\nexport interface McpCallResult {\n content: Array<{ type: string; text?: string; [key: string]: unknown }>;\n isError?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Response cache\n// ---------------------------------------------------------------------------\n\ninterface CacheEntry {\n result: McpCallResult;\n expiresAt: number;\n}\n\nexport class McpResponseCache {\n private cache = new Map<string, CacheEntry>();\n private readonly defaultTtlMs: number;\n\n constructor(defaultTtlMs = 30_000) {\n this.defaultTtlMs = defaultTtlMs;\n }\n\n private key(serverName: string, toolName: string, args: unknown): string {\n return `${serverName}::${toolName}::${JSON.stringify(args)}`;\n }\n\n get(serverName: string, toolName: string, args: unknown): McpCallResult | null {\n const k = this.key(serverName, toolName, args);\n const entry = this.cache.get(k);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(k);\n return null;\n }\n return entry.result;\n }\n\n set(serverName: string, toolName: string, args: unknown, result: McpCallResult, ttlMs?: number): void {\n const k = this.key(serverName, toolName, args);\n this.cache.set(k, {\n result,\n expiresAt: Date.now() + (ttlMs ?? this.defaultTtlMs),\n });\n }\n\n invalidate(serverName?: string): void {\n if (!serverName) {\n this.cache.clear();\n return;\n }\n for (const key of this.cache.keys()) {\n if (key.startsWith(`${serverName}::`)) {\n this.cache.delete(key);\n }\n }\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n\n// ---------------------------------------------------------------------------\n// McpClientManager — multi-server connection registry\n// ---------------------------------------------------------------------------\n\nexport class McpClientManager {\n private connections = new Map<string, McpServerConnection>();\n private readonly responseCache: McpResponseCache;\n\n constructor(opts?: { cacheTtlMs?: number }) {\n this.responseCache = new McpResponseCache(opts?.cacheTtlMs ?? 30_000);\n }\n\n /**\n * Connect to an MCP server and discover its tools.\n * If already connected to a server with this name, disconnects first.\n */\n async connect(config: McpServerConfig): Promise<McpServerConnection> {\n if (this.connections.has(config.name)) {\n await this.disconnect(config.name);\n }\n\n const client = new Client(\n { name: 'audric-engine', version: '0.1.0' },\n { capabilities: {} },\n );\n\n const transportType = config.transport ?? 'streamable-http';\n const url = new URL(config.url);\n\n const transport = transportType === 'sse'\n ? new SSEClientTransport(url)\n : new StreamableHTTPClientTransport(url, {\n reconnectionOptions: {\n maxReconnectionDelay: 30_000,\n initialReconnectionDelay: 1_000,\n reconnectionDelayGrowFactor: 1.5,\n maxRetries: 3,\n },\n });\n\n const conn: McpServerConnection = {\n config,\n client,\n transport,\n tools: [],\n status: 'disconnected',\n };\n\n try {\n await client.connect(transport);\n conn.status = 'connected';\n\n const { tools } = await client.listTools();\n conn.tools = tools;\n } catch (err) {\n try { await client.close(); } catch { /* best-effort */ }\n throw err;\n }\n\n this.connections.set(config.name, conn);\n return conn;\n }\n\n /** Disconnect from a server by name. */\n async disconnect(name: string): Promise<void> {\n const conn = this.connections.get(name);\n if (!conn) return;\n try {\n await conn.client.close();\n } catch { /* best-effort */ }\n conn.status = 'disconnected';\n conn.tools = [];\n this.connections.delete(name);\n this.responseCache.invalidate(name);\n }\n\n /** Disconnect from all servers. */\n async disconnectAll(): Promise<void> {\n const names = [...this.connections.keys()];\n await Promise.allSettled(names.map((n) => this.disconnect(n)));\n }\n\n /** Get a connection by server name. */\n getConnection(name: string): McpServerConnection | undefined {\n return this.connections.get(name);\n }\n\n /** Check if a server is connected. */\n isConnected(name: string): boolean {\n return this.connections.get(name)?.status === 'connected';\n }\n\n /** List all tool definitions across all connected servers. */\n listAllTools(): Array<{ serverName: string; tool: McpToolDef }> {\n const result: Array<{ serverName: string; tool: McpToolDef }> = [];\n for (const [name, conn] of this.connections) {\n if (conn.status !== 'connected') continue;\n for (const tool of conn.tools) {\n result.push({ serverName: name, tool });\n }\n }\n return result;\n }\n\n /**\n * Call a tool on a specific server.\n * Uses response cache for read-only servers.\n */\n async callTool(\n serverName: string,\n toolName: string,\n args: Record<string, unknown> = {},\n ): Promise<McpCallResult> {\n const conn = this.connections.get(serverName);\n if (!conn) throw new Error(`MCP server \"${serverName}\" not connected`);\n if (conn.status !== 'connected') throw new Error(`MCP server \"${serverName}\" is ${conn.status}`);\n\n const cacheTtl = conn.config.cacheTtlMs ?? 30_000;\n if (conn.config.readOnly !== false && cacheTtl > 0) {\n const cached = this.responseCache.get(serverName, toolName, args);\n if (cached) return cached;\n }\n\n const result = await conn.client.callTool({ name: toolName, arguments: args });\n\n const callResult: McpCallResult = {\n content: (result.content ?? []) as McpCallResult['content'],\n isError: result.isError as boolean | undefined,\n };\n\n if (conn.config.readOnly !== false && cacheTtl > 0) {\n this.responseCache.set(serverName, toolName, args, callResult, cacheTtl);\n }\n\n return callResult;\n }\n\n /** Get the response cache (for testing / manual invalidation). */\n get cache(): McpResponseCache {\n return this.responseCache;\n }\n\n /** Number of connected servers. */\n get serverCount(): number {\n let count = 0;\n for (const conn of this.connections.values()) {\n if (conn.status === 'connected') count++;\n }\n return count;\n }\n\n /** All server names. */\n get serverNames(): string[] {\n return [...this.connections.keys()];\n }\n}\n","import { z } from 'zod';\nimport type { Tool as McpToolDef } from '@modelcontextprotocol/sdk/types.js';\nimport type { Tool, ToolJsonSchema, PermissionLevel } from './types.js';\nimport type { McpClientManager } from './mcp-client.js';\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\nexport interface McpToolAdapterConfig {\n /** The McpClientManager to route calls through. */\n manager: McpClientManager;\n /** Server name this tool belongs to. */\n serverName: string;\n /** Override permission level for all tools from this server. */\n permissionLevel?: PermissionLevel;\n /** Override isReadOnly for all tools from this server. */\n isReadOnly?: boolean;\n /** Per-tool overrides keyed by MCP tool name. */\n toolOverrides?: Record<string, {\n permissionLevel?: PermissionLevel;\n isReadOnly?: boolean;\n description?: string;\n }>;\n}\n\n// ---------------------------------------------------------------------------\n// Adapter: single MCP tool → engine Tool\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a single MCP tool definition into an engine Tool.\n * The tool name is namespaced as `{serverName}_{mcpToolName}`.\n */\nexport function adaptMcpTool(\n mcpTool: McpToolDef,\n config: McpToolAdapterConfig,\n): Tool {\n const overrides = config.toolOverrides?.[mcpTool.name];\n const isReadOnly = overrides?.isReadOnly ?? config.isReadOnly ?? true;\n const permissionLevel = overrides?.permissionLevel ?? config.permissionLevel ?? 'auto';\n const namespacedName = `${config.serverName}_${mcpTool.name}`;\n\n const jsonSchema: ToolJsonSchema = (mcpTool.inputSchema ?? {\n type: 'object',\n properties: {},\n }) as ToolJsonSchema;\n\n return {\n name: namespacedName,\n description: overrides?.description ?? mcpTool.description ?? `MCP tool: ${mcpTool.name}`,\n inputSchema: z.record(z.unknown()),\n jsonSchema,\n isReadOnly,\n isConcurrencySafe: isReadOnly,\n permissionLevel,\n flags: {},\n\n async call(input, _context) {\n const result = await config.manager.callTool(\n config.serverName,\n mcpTool.name,\n input as Record<string, unknown>,\n );\n\n const textContent = result.content\n .filter((c) => c.type === 'text' && c.text)\n .map((c) => c.text!)\n .join('\\n');\n\n let data: unknown;\n try {\n data = JSON.parse(textContent);\n } catch {\n data = textContent || result.content;\n }\n\n if (result.isError) {\n return { data: { error: data } };\n }\n\n return { data };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Batch adapter: all tools from a server → engine Tools\n// ---------------------------------------------------------------------------\n\n/**\n * Convert all discovered tools from an MCP server into engine Tools.\n * Call this after `manager.connect(config)` completes successfully.\n */\nexport function adaptAllMcpTools(config: McpToolAdapterConfig): Tool[] {\n const conn = config.manager.getConnection(config.serverName);\n if (!conn || conn.status !== 'connected') {\n return [];\n }\n return conn.tools.map((t) => adaptMcpTool(t, config));\n}\n\n/**\n * Convenience: adapt tools from all connected servers.\n * Returns a flat array of engine Tools, namespaced by server name.\n */\nexport function adaptAllServerTools(\n manager: McpClientManager,\n serverConfigs?: Record<string, Omit<McpToolAdapterConfig, 'manager' | 'serverName'>>,\n): Tool[] {\n const allTools: Tool[] = [];\n\n for (const { serverName, tool } of manager.listAllTools()) {\n const serverOpts = serverConfigs?.[serverName] ?? {};\n allTools.push(adaptMcpTool(tool, {\n manager,\n serverName,\n ...serverOpts,\n }));\n }\n\n return allTools;\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport type {\n ChatParams,\n LLMProvider,\n Message,\n ProviderEvent,\n StopReason,\n SystemPrompt,\n ThinkingConfig,\n ToolDefinition,\n} from '../types.js';\nimport { parseEvalSummary } from '../eval-summary.js';\n\nconst DEFAULT_MODEL = 'claude-sonnet-4-20250514';\nconst DEFAULT_MAX_TOKENS = 4096;\n\n// Anthropic occasionally returns 529 overloaded_error or 429 rate_limit_error\n// when their infrastructure is over capacity. The SDK does NOT auto-retry\n// streaming requests once the connection opens, so we wrap the stream call\n// ourselves: if the stream errors before yielding any events, we retry with\n// exponential backoff. Once tokens have started flowing we propagate, because\n// retrying mid-stream would corrupt engine state (double-counted tokens, etc.).\nconst DEFAULT_MAX_RETRIES = 3;\nconst RETRY_BASE_DELAY_MS = 1000;\nconst RETRY_MAX_DELAY_MS = 8000;\n\nexport interface AnthropicProviderConfig {\n apiKey: string;\n defaultModel?: string;\n defaultMaxTokens?: number;\n /** Max retry attempts for retriable errors (overloaded, rate-limited, network). Default 3. */\n maxRetries?: number;\n}\n\nexport class AnthropicProvider implements LLMProvider {\n private client: Anthropic;\n private defaultModel: string;\n private defaultMaxTokens: number;\n private maxRetries: number;\n\n constructor(config: AnthropicProviderConfig) {\n this.client = new Anthropic({ apiKey: config.apiKey });\n this.defaultModel = config.defaultModel ?? DEFAULT_MODEL;\n this.defaultMaxTokens = config.defaultMaxTokens ?? DEFAULT_MAX_TOKENS;\n this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n }\n\n async *chat(params: ChatParams): AsyncGenerator<ProviderEvent> {\n let attempt = 0;\n while (true) {\n let yieldedAnything = false;\n const inner = this.streamOnce(params);\n try {\n for (;;) {\n const next = await inner.next();\n if (next.done) return;\n yieldedAnything = true;\n yield next.value;\n }\n } catch (err) {\n // Best-effort: tell the inner generator to release the underlying stream.\n try { await inner.return?.(undefined); } catch { /* noop */ }\n\n if (!yieldedAnything && isRetriableError(err) && attempt < this.maxRetries) {\n attempt++;\n const delayMs = computeBackoffMs(attempt);\n console.warn(\n `[anthropic] retriable error (attempt ${attempt}/${this.maxRetries}, retrying in ${delayMs}ms): ${rawErrorMessage(err)}`,\n );\n await sleep(delayMs);\n continue;\n }\n throw new Error(friendlyErrorMessage(err));\n }\n }\n }\n\n private async *streamOnce(params: ChatParams): AsyncGenerator<ProviderEvent> {\n const messages = sanitizeAnthropicMessages(\n params.messages.map(toAnthropicMessage),\n );\n const tools = params.tools.map(toAnthropicTool);\n\n let toolChoice: Anthropic.Messages.MessageCreateParams['tool_choice'] | undefined;\n if (params.toolChoice && tools.length > 0) {\n if (params.toolChoice === 'any') {\n toolChoice = { type: 'any' };\n } else if (params.toolChoice === 'auto') {\n toolChoice = { type: 'auto' };\n } else if (typeof params.toolChoice === 'object') {\n toolChoice = { type: 'tool', name: params.toolChoice.name };\n }\n }\n\n const thinkingParam = toAnthropicThinking(params.thinking);\n\n const systemParam = toAnthropicSystem(params.systemPrompt);\n\n const baseParams: Anthropic.Messages.MessageCreateParamsStreaming = {\n model: params.model ?? this.defaultModel,\n max_tokens: params.maxTokens ?? this.defaultMaxTokens,\n system: systemParam,\n messages,\n stream: true as const,\n tools: tools.length > 0 ? tools : undefined,\n ...(!thinkingParam && params.temperature !== undefined && { temperature: params.temperature }),\n ...(toolChoice && { tool_choice: toolChoice }),\n };\n\n const streamParams = {\n ...baseParams,\n ...(thinkingParam && { thinking: thinkingParam }),\n ...(params.outputConfig?.effort && { output_config: { effort: params.outputConfig.effort } }),\n };\n\n // Cast to satisfy SDK types — thinking/output_config may not be in the type defs yet\n const stream = params.signal\n ? this.client.messages.stream(streamParams as Anthropic.Messages.MessageCreateParamsStreaming, { signal: params.signal })\n : this.client.messages.stream(streamParams as Anthropic.Messages.MessageCreateParamsStreaming);\n\n const toolInputBuffers = new Map<number, { id: string; name: string; json: string }>();\n const thinkingBuffers = new Map<number, { type: 'thinking'; text: string; signature: string } | { type: 'redacted_thinking'; data: string }>();\n let outputTokensFromStart = 0;\n\n try {\n for await (const event of stream) {\n switch (event.type) {\n case 'message_start': {\n const msg = event.message;\n yield {\n type: 'message_start',\n messageId: msg.id,\n model: msg.model,\n };\n if (msg.usage) {\n const u = msg.usage as unknown as Record<string, number>;\n outputTokensFromStart = msg.usage.output_tokens;\n yield {\n type: 'usage',\n inputTokens: msg.usage.input_tokens,\n outputTokens: msg.usage.output_tokens,\n cacheReadTokens: u.cache_read_input_tokens,\n cacheWriteTokens: u.cache_creation_input_tokens,\n };\n }\n break;\n }\n\n case 'content_block_start': {\n const block = event.content_block as { type: string; id?: string; name?: string; data?: string };\n if (block.type === 'tool_use') {\n toolInputBuffers.set(event.index, {\n id: block.id!,\n name: block.name!,\n json: '',\n });\n yield {\n type: 'tool_use_start',\n id: block.id!,\n name: block.name!,\n };\n } else if (block.type === 'thinking') {\n thinkingBuffers.set(event.index, { type: 'thinking', text: '', signature: '' });\n } else if (block.type === 'redacted_thinking') {\n thinkingBuffers.set(event.index, { type: 'redacted_thinking', data: block.data ?? '' });\n }\n break;\n }\n\n case 'content_block_delta': {\n const delta = event.delta as { type: string; text?: string; partial_json?: string; thinking?: string; signature?: string };\n if (delta.type === 'text_delta') {\n yield { type: 'text_delta', text: delta.text! };\n } else if (delta.type === 'input_json_delta') {\n const buf = toolInputBuffers.get(event.index);\n if (buf) {\n buf.json += delta.partial_json!;\n yield {\n type: 'tool_use_delta',\n id: buf.id,\n partialJson: delta.partial_json!,\n };\n }\n } else if (delta.type === 'thinking_delta') {\n const buf = thinkingBuffers.get(event.index);\n if (buf?.type === 'thinking') buf.text += delta.thinking ?? '';\n yield { type: 'thinking_delta', text: delta.thinking ?? '', blockIndex: event.index };\n } else if (delta.type === 'signature_delta') {\n const buf = thinkingBuffers.get(event.index);\n if (buf?.type === 'thinking') buf.signature = delta.signature ?? '';\n }\n break;\n }\n\n case 'content_block_stop': {\n const toolBuf = toolInputBuffers.get(event.index);\n if (toolBuf) {\n let input: unknown = {};\n try {\n input = JSON.parse(toolBuf.json || '{}');\n } catch {\n input = {};\n }\n yield {\n type: 'tool_use_done',\n id: toolBuf.id,\n name: toolBuf.name,\n input,\n };\n toolInputBuffers.delete(event.index);\n }\n const thinkBuf = thinkingBuffers.get(event.index);\n if (thinkBuf?.type === 'thinking') {\n // [SPEC 8 v0.5.1] Detect <eval_summary> marker in the\n // thinking buffer. When present + parseable, populate the\n // structured fields the host renders as HowIEvaluatedBlock.\n const summary = parseEvalSummary(thinkBuf.text);\n yield {\n type: 'thinking_done',\n blockIndex: event.index,\n thinking: thinkBuf.text,\n signature: thinkBuf.signature,\n ...(summary\n ? { summaryMode: true, evaluationItems: summary.evaluationItems }\n : {}),\n };\n thinkingBuffers.delete(event.index);\n } else if (thinkBuf?.type === 'redacted_thinking') {\n yield { type: 'redacted_thinking', data: thinkBuf.data };\n thinkingBuffers.delete(event.index);\n }\n break;\n }\n\n case 'message_delta': {\n const delta = event.delta as { stop_reason?: string };\n const usage = event.usage as { output_tokens?: number } | undefined;\n // message_delta.usage.output_tokens is cumulative — emit only the delta\n if (usage?.output_tokens && usage.output_tokens > outputTokensFromStart) {\n const increment = usage.output_tokens - outputTokensFromStart;\n outputTokensFromStart = usage.output_tokens;\n yield {\n type: 'usage',\n inputTokens: 0,\n outputTokens: increment,\n };\n }\n if (delta.stop_reason) {\n yield {\n type: 'stop',\n reason: mapStopReason(delta.stop_reason),\n };\n }\n break;\n }\n }\n }\n } finally {\n stream.abort();\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error classification + retry helpers\n// ---------------------------------------------------------------------------\n\n// Exported for testing. Not part of the public provider API.\nexport const _internal = {\n isRetriableError: (err: unknown) => isRetriableError(err),\n friendlyErrorMessage: (err: unknown) => friendlyErrorMessage(err),\n computeBackoffMs: (attempt: number) => computeBackoffMs(attempt),\n};\n\nfunction isRetriableError(err: unknown): boolean {\n if (!err) return false;\n\n // Anthropic SDK error classes (status-based)\n if (err instanceof Anthropic.APIError) {\n // 529 overloaded, 408 timeout, 502/503/504 transient\n if (err.status === 529 || err.status === 408) return true;\n if (err.status === 502 || err.status === 503 || err.status === 504) return true;\n // 429 rate-limited — retry but the user may need to slow down regardless\n if (err.status === 429) return true;\n return false;\n }\n\n // Sometimes streaming errors arrive as plain Error with the JSON message\n // baked into err.message (e.g. {\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",...}})\n const msg = rawErrorMessage(err).toLowerCase();\n if (\n msg.includes('overloaded_error') ||\n msg.includes('\"overloaded\"') ||\n msg.includes('rate_limit_error') ||\n msg.includes('econnreset') ||\n msg.includes('etimedout') ||\n msg.includes('socket hang up') ||\n msg.includes('fetch failed') ||\n msg.includes('network error')\n ) {\n return true;\n }\n\n return false;\n}\n\nfunction rawErrorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n if (typeof err === 'string') return err;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n}\n\n/**\n * Map a raw provider error to a clean, user-facing message.\n *\n * Most users see this as the chat error bubble — never leak raw JSON or\n * stack traces. Any string returned here is safe to render verbatim in UI.\n */\nfunction friendlyErrorMessage(err: unknown): string {\n const msg = rawErrorMessage(err).toLowerCase();\n\n if (\n msg.includes('overloaded_error') ||\n msg.includes('\"overloaded\"') ||\n (err instanceof Anthropic.APIError && err.status === 529)\n ) {\n return \"Anthropic's servers are over capacity right now. Please try again in 30 seconds.\";\n }\n if (\n msg.includes('rate_limit_error') ||\n (err instanceof Anthropic.APIError && err.status === 429)\n ) {\n return 'Too many requests in a short window. Please wait a moment and try again.';\n }\n if (\n msg.includes('econnreset') ||\n msg.includes('etimedout') ||\n msg.includes('socket hang up') ||\n msg.includes('fetch failed') ||\n msg.includes('network error')\n ) {\n return \"Couldn't reach Anthropic. Check your connection and try again.\";\n }\n if (err instanceof Anthropic.APIError && err.status === 401) {\n return 'Authentication failed. Please check the Anthropic API key configuration.';\n }\n if (err instanceof Anthropic.APIError && err.status === 400) {\n return 'The request was rejected by Anthropic. This is likely a bug — please retry, and if it persists, contact support.';\n }\n if (err instanceof Anthropic.APIError && err.status >= 500) {\n return 'Anthropic returned a server error. Please try again in a moment.';\n }\n\n return 'Something went wrong. Please try again.';\n}\n\nfunction computeBackoffMs(attempt: number): number {\n const base = Math.min(RETRY_BASE_DELAY_MS * 2 ** (attempt - 1), RETRY_MAX_DELAY_MS);\n const jitter = Math.floor(Math.random() * 250);\n return base + jitter;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ---------------------------------------------------------------------------\n// Conversion helpers\n// ---------------------------------------------------------------------------\n\nfunction toAnthropicSystem(prompt: SystemPrompt): string | Anthropic.Messages.TextBlockParam[] {\n if (typeof prompt === 'string') return prompt;\n return prompt.map((block) => ({\n type: 'text' as const,\n text: block.text,\n ...(block.cache_control && { cache_control: block.cache_control }),\n }));\n}\n\nfunction toAnthropicThinking(config?: ThinkingConfig): Record<string, unknown> | undefined {\n if (!config || config.type === 'disabled') return undefined;\n if (config.type === 'adaptive') return { type: 'adaptive' };\n return { type: 'enabled', budget_tokens: config.budgetTokens };\n}\n\nfunction toAnthropicMessage(msg: Message): Anthropic.MessageParam {\n const content: Anthropic.ContentBlockParam[] = msg.content\n .map((block): Anthropic.ContentBlockParam | null => {\n switch (block.type) {\n case 'text':\n return { type: 'text' as const, text: block.text };\n case 'thinking':\n return { type: 'thinking' as const, thinking: block.thinking, signature: block.signature } as unknown as Anthropic.ContentBlockParam;\n case 'redacted_thinking':\n return { type: 'redacted_thinking' as const, data: block.data } as unknown as Anthropic.ContentBlockParam;\n case 'tool_use':\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input as Record<string, unknown>,\n };\n case 'tool_result':\n return {\n type: 'tool_result' as const,\n tool_use_id: block.toolUseId,\n content: block.content,\n is_error: block.isError,\n };\n }\n })\n .filter((b): b is Anthropic.ContentBlockParam => b !== null);\n\n return { role: msg.role, content };\n}\n\nfunction toAnthropicTool(\n def: ToolDefinition,\n): Anthropic.Messages.Tool {\n return {\n name: def.name,\n description: def.description,\n input_schema: def.input_schema as Anthropic.Messages.Tool.InputSchema,\n };\n}\n\nfunction mapStopReason(reason: string): StopReason {\n switch (reason) {\n case 'end_turn':\n return 'end_turn';\n case 'tool_use':\n return 'tool_use';\n case 'max_tokens':\n return 'max_tokens';\n default:\n return 'end_turn';\n }\n}\n\n/**\n * Last-line-of-defense sanitization operating directly on Anthropic-format messages.\n * Enforces the positional constraint: every tool_use in an assistant message must have\n * a matching tool_result (by tool_use_id) in the immediately next user message.\n * Strips orphans in both directions and fixes role alternation.\n */\nfunction sanitizeAnthropicMessages(\n messages: Anthropic.MessageParam[],\n): Anthropic.MessageParam[] {\n const result: Anthropic.MessageParam[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n const content = Array.isArray(msg.content) ? msg.content : [{ type: 'text' as const, text: msg.content }];\n\n // Collect tool_use ids in this assistant message\n const toolUseIds = content\n .filter((b): b is Anthropic.ToolUseBlockParam => (b as { type: string }).type === 'tool_use')\n .map((b) => b.id);\n\n if (msg.role === 'assistant' && toolUseIds.length > 0) {\n const next = messages[i + 1];\n const nextContent = next ? (Array.isArray(next.content) ? next.content : []) : [];\n const nextResultIds = new Set(\n nextContent\n .filter((b): b is Anthropic.ToolResultBlockParam => (b as { type: string }).type === 'tool_result')\n .map((b) => b.tool_use_id),\n );\n\n // Keep only tool_use blocks that have a result in the next message\n const cleanContent = content.filter((b) => {\n if ((b as { type: string }).type === 'tool_use') return nextResultIds.has((b as Anthropic.ToolUseBlockParam).id);\n return true;\n });\n\n // Keep only tool_result blocks in next whose tool_use survived\n const keptIds = new Set(\n cleanContent\n .filter((b): b is Anthropic.ToolUseBlockParam => (b as { type: string }).type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanNext = nextContent.filter((b) => {\n if ((b as { type: string }).type === 'tool_result')\n return keptIds.has((b as Anthropic.ToolResultBlockParam).tool_use_id);\n return true;\n });\n\n if (cleanContent.length > 0) result.push({ role: 'assistant', content: cleanContent });\n if (cleanNext.length > 0 && next) result.push({ role: next.role, content: cleanNext });\n i++; // skip the next message (already processed)\n\n if (cleanContent.length < content.length || cleanNext.length < nextContent.length) {\n console.warn(\n `[anthropic] sanitized orphans: stripped ${content.length - cleanContent.length} tool_use, ${nextContent.length - cleanNext.length} tool_result`,\n );\n }\n continue;\n }\n\n // For user messages: strip tool_result referencing non-existent tool_use in prev assistant\n if (msg.role === 'user' && content.some((b) => (b as { type: string }).type === 'tool_result')) {\n const prev = result[result.length - 1];\n const prevContent = prev?.role === 'assistant' && Array.isArray(prev.content) ? prev.content : [];\n const prevToolUseIds = new Set(\n prevContent\n .filter((b): b is Anthropic.ToolUseBlockParam => (b as { type: string }).type === 'tool_use')\n .map((b) => b.id),\n );\n const cleanContent = content.filter((b) => {\n if ((b as { type: string }).type === 'tool_result')\n return prevToolUseIds.has((b as Anthropic.ToolResultBlockParam).tool_use_id);\n return true;\n });\n if (cleanContent.length > 0) result.push({ role: msg.role, content: cleanContent });\n continue;\n }\n\n result.push(msg);\n }\n\n // Merge consecutive same-role messages\n const merged: Anthropic.MessageParam[] = [];\n for (const msg of result) {\n const last = merged[merged.length - 1];\n if (last && last.role === msg.role) {\n const lastContent = Array.isArray(last.content) ? last.content : [{ type: 'text' as const, text: last.content }];\n const msgContent = Array.isArray(msg.content) ? msg.content : [{ type: 'text' as const, text: msg.content }];\n last.content = [...lastContent, ...msgContent];\n } else {\n merged.push({ ...msg });\n }\n }\n\n // First message must be user\n while (merged.length > 0 && merged[0].role !== 'user') {\n merged.shift();\n }\n\n return merged;\n}\n"]}