@t2000/engine 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +40 -48
- package/dist/index.js +125 -156
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -38,12 +38,8 @@ type EngineEvent = {
|
|
|
38
38
|
result: unknown;
|
|
39
39
|
isError: boolean;
|
|
40
40
|
} | {
|
|
41
|
-
type: '
|
|
42
|
-
|
|
43
|
-
toolUseId: string;
|
|
44
|
-
input: unknown;
|
|
45
|
-
description: string;
|
|
46
|
-
resolve: (response: PermissionResponse) => void;
|
|
41
|
+
type: 'pending_action';
|
|
42
|
+
action: PendingAction;
|
|
47
43
|
} | {
|
|
48
44
|
type: 'turn_complete';
|
|
49
45
|
stopReason: StopReason;
|
|
@@ -59,11 +55,19 @@ type EngineEvent = {
|
|
|
59
55
|
};
|
|
60
56
|
type StopReason = 'end_turn' | 'tool_use' | 'max_tokens' | 'max_turns' | 'error';
|
|
61
57
|
/**
|
|
62
|
-
*
|
|
58
|
+
* Serializable description of a write tool that needs user approval.
|
|
59
|
+
* Stored in the session so the client can act on it in a separate request.
|
|
60
|
+
*/
|
|
61
|
+
interface PendingAction {
|
|
62
|
+
toolName: string;
|
|
63
|
+
toolUseId: string;
|
|
64
|
+
input: unknown;
|
|
65
|
+
description: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Response from the client when resolving a pending action.
|
|
63
69
|
* - `approved: false` → tool is declined, LLM is told "user declined"
|
|
64
|
-
* - `approved: true`
|
|
65
|
-
* - `approved: true` with `executionResult` → engine skips server-side execution
|
|
66
|
-
* and uses the client-provided result (for client-side tx signing flows)
|
|
70
|
+
* - `approved: true` with `executionResult` → engine uses the client-provided result
|
|
67
71
|
*/
|
|
68
72
|
interface PermissionResponse {
|
|
69
73
|
approved: boolean;
|
|
@@ -231,16 +235,34 @@ declare class QueryEngine {
|
|
|
231
235
|
private abortController;
|
|
232
236
|
constructor(config: EngineConfig);
|
|
233
237
|
/**
|
|
234
|
-
* Submit a user message and
|
|
235
|
-
*
|
|
238
|
+
* Submit a user message and stream engine events.
|
|
239
|
+
*
|
|
240
|
+
* Read-only tools execute inline. Write tools that need confirmation yield a
|
|
241
|
+
* `pending_action` event and the stream ends — no persistent connection needed.
|
|
242
|
+
* The caller should save messages + pendingAction to the session store, then
|
|
243
|
+
* call `resumeWithToolResult()` after the user approves/denies and executes.
|
|
236
244
|
*/
|
|
237
245
|
submitMessage(prompt: string): AsyncGenerator<EngineEvent>;
|
|
246
|
+
/**
|
|
247
|
+
* Resume the conversation after a pending action is resolved.
|
|
248
|
+
* Called with the user's approval/denial and optional client-side execution result.
|
|
249
|
+
*
|
|
250
|
+
* This is a separate HTTP request — no persistent connection from submitMessage.
|
|
251
|
+
*/
|
|
252
|
+
resumeWithToolResult(action: PendingAction, response: PermissionResponse): AsyncGenerator<EngineEvent>;
|
|
238
253
|
interrupt(): void;
|
|
239
254
|
getMessages(): readonly Message[];
|
|
240
255
|
reset(): void;
|
|
241
256
|
loadMessages(messages: Message[]): void;
|
|
242
257
|
setServerPositions(data: EngineConfig['serverPositions']): void;
|
|
243
258
|
getUsage(): CostSnapshot;
|
|
259
|
+
/**
|
|
260
|
+
* Run the LLM → tool → LLM loop. When a write tool needs confirmation,
|
|
261
|
+
* yields `pending_action` and returns immediately (stream ends cleanly).
|
|
262
|
+
*
|
|
263
|
+
* @param freshPrompt - The original user prompt (for corrupt-history retry). Null on resume.
|
|
264
|
+
*/
|
|
265
|
+
private agentLoop;
|
|
244
266
|
private addErrorResults;
|
|
245
267
|
private handleProviderEvent;
|
|
246
268
|
}
|
|
@@ -275,11 +297,6 @@ declare class TxMutex {
|
|
|
275
297
|
}
|
|
276
298
|
declare function runTools(pending: PendingToolCall[], tools: Tool[], context: ToolContext, txMutex: TxMutex): AsyncGenerator<EngineEvent>;
|
|
277
299
|
|
|
278
|
-
/**
|
|
279
|
-
* Wire-safe representation of EngineEvent for SSE transport.
|
|
280
|
-
* `permission_request` replaces the `resolve` callback with a `permissionId`
|
|
281
|
-
* that the client sends back via a separate HTTP endpoint.
|
|
282
|
-
*/
|
|
283
300
|
type SSEEvent = {
|
|
284
301
|
type: 'text_delta';
|
|
285
302
|
text: string;
|
|
@@ -295,12 +312,8 @@ type SSEEvent = {
|
|
|
295
312
|
result: unknown;
|
|
296
313
|
isError: boolean;
|
|
297
314
|
} | {
|
|
298
|
-
type: '
|
|
299
|
-
|
|
300
|
-
toolName: string;
|
|
301
|
-
toolUseId: string;
|
|
302
|
-
input: unknown;
|
|
303
|
-
description: string;
|
|
315
|
+
type: 'pending_action';
|
|
316
|
+
action: PendingAction;
|
|
304
317
|
} | {
|
|
305
318
|
type: 'turn_complete';
|
|
306
319
|
stopReason: StopReason;
|
|
@@ -316,30 +329,7 @@ type SSEEvent = {
|
|
|
316
329
|
};
|
|
317
330
|
declare function serializeSSE(event: SSEEvent): string;
|
|
318
331
|
declare function parseSSE(raw: string): SSEEvent | null;
|
|
319
|
-
declare
|
|
320
|
-
private pending;
|
|
321
|
-
private counter;
|
|
322
|
-
/**
|
|
323
|
-
* Register a permission_request resolve callback.
|
|
324
|
-
* Returns the permissionId to send to the client.
|
|
325
|
-
*/
|
|
326
|
-
register(resolve: (response: PermissionResponse) => void): string;
|
|
327
|
-
/**
|
|
328
|
-
* Resolve a pending permission request from the client.
|
|
329
|
-
* Pass `executionResult` when the client executed the action itself
|
|
330
|
-
* (e.g., signed a transaction) so the engine can skip server-side execution.
|
|
331
|
-
*/
|
|
332
|
-
resolve(permissionId: string, approved: boolean, executionResult?: unknown): boolean;
|
|
333
|
-
/** Number of pending (unresolved) permission requests. */
|
|
334
|
-
get size(): number;
|
|
335
|
-
/** Reject all pending permissions (e.g., on disconnect). */
|
|
336
|
-
rejectAll(): void;
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Wraps a QueryEngine.submitMessage() generator, converting EngineEvents
|
|
340
|
-
* to SSE text. Permission requests are routed through the bridge.
|
|
341
|
-
*/
|
|
342
|
-
declare function engineToSSE(events: AsyncGenerator<EngineEvent>, bridge: PermissionBridge): AsyncGenerator<string>;
|
|
332
|
+
declare function engineToSSE(events: AsyncGenerator<EngineEvent>): AsyncGenerator<string>;
|
|
343
333
|
|
|
344
334
|
interface SessionData {
|
|
345
335
|
id: string;
|
|
@@ -347,6 +337,8 @@ interface SessionData {
|
|
|
347
337
|
usage: CostSnapshot;
|
|
348
338
|
createdAt: number;
|
|
349
339
|
updatedAt: number;
|
|
340
|
+
/** Set when the engine is paused waiting for user approval of a write action. */
|
|
341
|
+
pendingAction?: PendingAction | null;
|
|
350
342
|
metadata?: Record<string, unknown>;
|
|
351
343
|
}
|
|
352
344
|
interface SessionStore {
|
|
@@ -903,4 +895,4 @@ declare function fetchWalletCoins(address: string, rpcUrl?: string): Promise<Wal
|
|
|
903
895
|
|
|
904
896
|
declare const DEFAULT_SYSTEM_PROMPT = "You are Audric, an AI assistant built on the Sui blockchain. You help users manage finances AND access 40+ paid API services via MPP (Machine Payment Protocol) micropayments.\n\n## Core Capabilities\n- Check balances, savings positions, health factors, and interest rates\n- Execute deposits, withdrawals, transfers, borrows, and repayments\n- Track transaction history and earnings\n- Look up swap quotes, bridge options, and token information via NAVI\n- **Access any MPP service** \u2014 weather, web search, news, crypto prices, stock quotes, translations, image generation, maps, flights, and more via the pay_api tool\n- Answer general knowledge questions conversationally\n\n## MPP Services (via pay_api tool)\nWhen users ask for real-world data (weather, search, prices, news, etc.), use the pay_api tool. Each call costs a few cents in USDC, paid automatically on-chain. Common services:\n- **Weather/forecast**: OpenWeather \u2014 current conditions, 5-day forecast\n- **Web search**: Brave Search, Serper (Google), Perplexity (AI-powered)\n- **News**: NewsAPI headlines and search\n- **Crypto**: CoinGecko prices, markets, trending\n- **Stocks**: Alpha Vantage quotes, daily data\n- **Maps**: Google Maps geocode, places, directions\n- **Translation**: DeepL, Google Translate\n- **FX rates**: Exchange rate conversion\n- **Scraping**: Firecrawl, Jina Reader\n- **Flights**: SerpAPI Google Flights\n- **Image gen**: Flux, Stable Diffusion, DALL-E\n- **Email**: Resend\n\nAlways tell users the cost before calling a paid service. If they agree, use pay_api.\n\n## Guidelines\n\n### Before Acting\n- Always check the user's balance before suggesting financial actions\n- Show real numbers from tool results \u2014 never fabricate rates, amounts, or balances\n- For transactions that move funds, explain what will happen and confirm intent\n\n### Tool Usage\n- Use any available tools to help the user \u2014 don't refuse requests you can handle\n- For real-world questions (weather, search, news, prices), use pay_api with the appropriate MPP endpoint\n- Use multiple read-only tools in parallel when you need several data points\n- Present amounts as currency ($1,234.56) and rates as percentages (4.86% APY)\n- If a tool errors, explain the issue clearly and suggest alternatives\n\n### Communication Style\n- Be concise and direct \u2014 lead with results, follow with context\n- Use short sentences. Avoid hedging language.\n- When presenting positions or balances, use a structured format\n- For non-financial questions, answer naturally and helpfully\n\n### Safety\n- Never encourage risky financial behavior\n- Warn when health factor drops below 1.5\n- Remind users of gas costs for on-chain transactions\n- All amounts are in USDC unless explicitly stated otherwise";
|
|
905
897
|
|
|
906
|
-
export { AnthropicProvider, type AnthropicProviderConfig, type BalancePrices, type BalanceResult, type BuildToolOptions, type ChatParams, type CompactOptions, type ContentBlock, type CostSnapshot, CostTracker, type CostTrackerConfig, DEFAULT_SYSTEM_PROMPT, type EngineConfig, type EngineEvent, type HealthFactorResult, type LLMProvider, type McpCallResult, McpClientManager, McpResponseCache, type McpServerConfig, type McpServerConnection, type McpToolAdapterConfig, type McpToolDescriptor, MemorySessionStore, type Message, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_SERVER_NAME, type NaviRawCoin, type NaviRawHealthFactor, type NaviRawPool, type NaviRawPosition, type NaviRawPositionsResponse, type NaviRawProtocolStats, type NaviRawRewardsResponse, type NaviReadOptions, NaviTools, type PendingReward, type PendingToolCall,
|
|
898
|
+
export { AnthropicProvider, type AnthropicProviderConfig, type BalancePrices, type BalanceResult, type BuildToolOptions, type ChatParams, type CompactOptions, type ContentBlock, type CostSnapshot, CostTracker, type CostTrackerConfig, DEFAULT_SYSTEM_PROMPT, type EngineConfig, type EngineEvent, type HealthFactorResult, type LLMProvider, type McpCallResult, McpClientManager, McpResponseCache, type McpServerConfig, type McpServerConnection, type McpToolAdapterConfig, type McpToolDescriptor, MemorySessionStore, type Message, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_SERVER_NAME, type NaviRawCoin, type NaviRawHealthFactor, type NaviRawPool, type NaviRawPosition, type NaviRawPositionsResponse, type NaviRawProtocolStats, type NaviRawRewardsResponse, type NaviReadOptions, NaviTools, type PendingAction, type PendingReward, type PendingToolCall, type PermissionLevel, type PermissionResponse, type PositionEntry, type ProtocolStats, type ProviderEvent, QueryEngine, READ_TOOLS, type RatesResult, type SSEEvent, type SavingsResult, type ServerPositionData, type SessionData, type SessionStore, type StopReason, type SuiCoinBalance, type Tool, type ToolContext, type ToolDefinition, type ToolJsonSchema, type ToolResult, TxMutex, WRITE_TOOLS, type WalletCoin, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, balanceCheckTool, borrowTool, buildMcpTools, buildTool, claimRewardsTool, compactMessages, engineToSSE, estimateTokens, extractMcpText, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchWalletCoins, findTool, getDefaultTools, getMcpManager, getWalletAddress, hasNaviMcp, healthCheckTool, parseMcpJson, parseSSE, payApiTool, ratesInfoTool, registerEngineTools, repayDebtTool, requireAgent, runTools, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, withdrawTool };
|
package/dist/index.js
CHANGED
|
@@ -1259,8 +1259,12 @@ var QueryEngine = class {
|
|
|
1259
1259
|
this.tools = config.tools ?? (config.agent ? getDefaultTools() : []);
|
|
1260
1260
|
}
|
|
1261
1261
|
/**
|
|
1262
|
-
* Submit a user message and
|
|
1263
|
-
*
|
|
1262
|
+
* Submit a user message and stream engine events.
|
|
1263
|
+
*
|
|
1264
|
+
* Read-only tools execute inline. Write tools that need confirmation yield a
|
|
1265
|
+
* `pending_action` event and the stream ends — no persistent connection needed.
|
|
1266
|
+
* The caller should save messages + pendingAction to the session store, then
|
|
1267
|
+
* call `resumeWithToolResult()` after the user approves/denies and executes.
|
|
1264
1268
|
*/
|
|
1265
1269
|
async *submitMessage(prompt) {
|
|
1266
1270
|
if (this.costTracker.isOverBudget()) {
|
|
@@ -1273,6 +1277,71 @@ var QueryEngine = class {
|
|
|
1273
1277
|
role: "user",
|
|
1274
1278
|
content: [{ type: "text", text: prompt }]
|
|
1275
1279
|
});
|
|
1280
|
+
yield* this.agentLoop(prompt, signal);
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Resume the conversation after a pending action is resolved.
|
|
1284
|
+
* Called with the user's approval/denial and optional client-side execution result.
|
|
1285
|
+
*
|
|
1286
|
+
* This is a separate HTTP request — no persistent connection from submitMessage.
|
|
1287
|
+
*/
|
|
1288
|
+
async *resumeWithToolResult(action, response) {
|
|
1289
|
+
this.abortController = new AbortController();
|
|
1290
|
+
const signal = this.abortController.signal;
|
|
1291
|
+
const toolResultBlock = response.approved ? {
|
|
1292
|
+
type: "tool_result",
|
|
1293
|
+
toolUseId: action.toolUseId,
|
|
1294
|
+
content: JSON.stringify(response.executionResult ?? { success: true }),
|
|
1295
|
+
isError: false
|
|
1296
|
+
} : {
|
|
1297
|
+
type: "tool_result",
|
|
1298
|
+
toolUseId: action.toolUseId,
|
|
1299
|
+
content: JSON.stringify({ error: "User declined this action" }),
|
|
1300
|
+
isError: true
|
|
1301
|
+
};
|
|
1302
|
+
this.messages.push({ role: "user", content: [toolResultBlock] });
|
|
1303
|
+
yield {
|
|
1304
|
+
type: "tool_result",
|
|
1305
|
+
toolName: action.toolName,
|
|
1306
|
+
toolUseId: action.toolUseId,
|
|
1307
|
+
result: response.approved ? response.executionResult ?? { success: true } : { error: "User declined this action" },
|
|
1308
|
+
isError: !response.approved
|
|
1309
|
+
};
|
|
1310
|
+
if (!response.approved) {
|
|
1311
|
+
yield { type: "turn_complete", stopReason: "end_turn" };
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
yield* this.agentLoop(null, signal);
|
|
1315
|
+
}
|
|
1316
|
+
interrupt() {
|
|
1317
|
+
this.abortController?.abort();
|
|
1318
|
+
}
|
|
1319
|
+
getMessages() {
|
|
1320
|
+
return this.messages;
|
|
1321
|
+
}
|
|
1322
|
+
reset() {
|
|
1323
|
+
this.messages = [];
|
|
1324
|
+
this.costTracker.reset();
|
|
1325
|
+
}
|
|
1326
|
+
loadMessages(messages) {
|
|
1327
|
+
this.messages = sanitizeMessages(messages);
|
|
1328
|
+
}
|
|
1329
|
+
setServerPositions(data) {
|
|
1330
|
+
this.serverPositions = data;
|
|
1331
|
+
}
|
|
1332
|
+
getUsage() {
|
|
1333
|
+
return this.costTracker.getSnapshot();
|
|
1334
|
+
}
|
|
1335
|
+
// ---------------------------------------------------------------------------
|
|
1336
|
+
// Core agent loop — shared by submitMessage and resumeWithToolResult
|
|
1337
|
+
// ---------------------------------------------------------------------------
|
|
1338
|
+
/**
|
|
1339
|
+
* Run the LLM → tool → LLM loop. When a write tool needs confirmation,
|
|
1340
|
+
* yields `pending_action` and returns immediately (stream ends cleanly).
|
|
1341
|
+
*
|
|
1342
|
+
* @param freshPrompt - The original user prompt (for corrupt-history retry). Null on resume.
|
|
1343
|
+
*/
|
|
1344
|
+
async *agentLoop(freshPrompt, signal) {
|
|
1276
1345
|
const context = {
|
|
1277
1346
|
agent: this.agent,
|
|
1278
1347
|
mcpManager: this.mcpManager,
|
|
@@ -1282,6 +1351,7 @@ var QueryEngine = class {
|
|
|
1282
1351
|
signal
|
|
1283
1352
|
};
|
|
1284
1353
|
let turns = 0;
|
|
1354
|
+
let hasRetriedWithCleanHistory = false;
|
|
1285
1355
|
while (turns < this.maxTurns) {
|
|
1286
1356
|
if (signal.aborted) {
|
|
1287
1357
|
yield { type: "error", error: new Error("Aborted") };
|
|
@@ -1295,16 +1365,29 @@ var QueryEngine = class {
|
|
|
1295
1365
|
assistantBlocks: [],
|
|
1296
1366
|
pendingToolCalls: []
|
|
1297
1367
|
};
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1368
|
+
try {
|
|
1369
|
+
const stream = this.provider.chat({
|
|
1370
|
+
messages: this.messages,
|
|
1371
|
+
systemPrompt: this.systemPrompt,
|
|
1372
|
+
tools: toolDefs,
|
|
1373
|
+
model: this.model,
|
|
1374
|
+
maxTokens: this.maxTokens,
|
|
1375
|
+
signal
|
|
1376
|
+
});
|
|
1377
|
+
for await (const event of stream) {
|
|
1378
|
+
yield* this.handleProviderEvent(event, acc);
|
|
1379
|
+
}
|
|
1380
|
+
} catch (err) {
|
|
1381
|
+
if (freshPrompt && !hasRetriedWithCleanHistory && isCorruptHistoryError(err)) {
|
|
1382
|
+
hasRetriedWithCleanHistory = true;
|
|
1383
|
+
console.warn("[engine] Corrupt session history detected, resetting to fresh conversation");
|
|
1384
|
+
this.messages = [
|
|
1385
|
+
{ role: "user", content: [{ type: "text", text: freshPrompt }] }
|
|
1386
|
+
];
|
|
1387
|
+
turns--;
|
|
1388
|
+
continue;
|
|
1389
|
+
}
|
|
1390
|
+
throw err;
|
|
1308
1391
|
}
|
|
1309
1392
|
if (acc.text) {
|
|
1310
1393
|
acc.assistantBlocks.push({ type: "text", text: acc.text });
|
|
@@ -1329,71 +1412,16 @@ var QueryEngine = class {
|
|
|
1329
1412
|
yield { type: "tool_start", toolName: call.name, toolUseId: call.id, input: call.input };
|
|
1330
1413
|
continue;
|
|
1331
1414
|
}
|
|
1332
|
-
let resolvePermission;
|
|
1333
|
-
const permissionPromise = new Promise((r) => {
|
|
1334
|
-
resolvePermission = r;
|
|
1335
|
-
});
|
|
1336
1415
|
yield {
|
|
1337
|
-
type: "
|
|
1338
|
-
|
|
1339
|
-
toolUseId: call.id,
|
|
1340
|
-
input: call.input,
|
|
1341
|
-
description: describeAction(tool, call),
|
|
1342
|
-
resolve: resolvePermission
|
|
1343
|
-
};
|
|
1344
|
-
let response;
|
|
1345
|
-
try {
|
|
1346
|
-
response = await Promise.race([
|
|
1347
|
-
permissionPromise,
|
|
1348
|
-
new Promise((_, reject) => {
|
|
1349
|
-
if (signal.aborted) reject(new Error("Aborted"));
|
|
1350
|
-
signal.addEventListener("abort", () => reject(new Error("Aborted")), { once: true });
|
|
1351
|
-
})
|
|
1352
|
-
]);
|
|
1353
|
-
} catch {
|
|
1354
|
-
this.addErrorResults(acc.pendingToolCalls, "Aborted");
|
|
1355
|
-
yield { type: "error", error: new Error("Aborted") };
|
|
1356
|
-
return;
|
|
1357
|
-
}
|
|
1358
|
-
if (!response.approved) {
|
|
1359
|
-
toolResultBlocks.push({
|
|
1360
|
-
type: "tool_result",
|
|
1361
|
-
toolUseId: call.id,
|
|
1362
|
-
content: JSON.stringify({ error: "User declined this action" }),
|
|
1363
|
-
isError: true
|
|
1364
|
-
});
|
|
1365
|
-
yield {
|
|
1366
|
-
type: "tool_result",
|
|
1367
|
-
toolName: call.name,
|
|
1368
|
-
toolUseId: call.id,
|
|
1369
|
-
result: { error: "User declined this action" },
|
|
1370
|
-
isError: true
|
|
1371
|
-
};
|
|
1372
|
-
} else if (response.executionResult !== void 0) {
|
|
1373
|
-
const clientResult = response.executionResult;
|
|
1374
|
-
toolResultBlocks.push({
|
|
1375
|
-
type: "tool_result",
|
|
1376
|
-
toolUseId: call.id,
|
|
1377
|
-
content: JSON.stringify(clientResult),
|
|
1378
|
-
isError: false
|
|
1379
|
-
});
|
|
1380
|
-
yield {
|
|
1381
|
-
type: "tool_start",
|
|
1382
|
-
toolName: call.name,
|
|
1383
|
-
toolUseId: call.id,
|
|
1384
|
-
input: call.input
|
|
1385
|
-
};
|
|
1386
|
-
yield {
|
|
1387
|
-
type: "tool_result",
|
|
1416
|
+
type: "pending_action",
|
|
1417
|
+
action: {
|
|
1388
1418
|
toolName: call.name,
|
|
1389
1419
|
toolUseId: call.id,
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
yield { type: "tool_start", toolName: call.name, toolUseId: call.id, input: call.input };
|
|
1396
|
-
}
|
|
1420
|
+
input: call.input,
|
|
1421
|
+
description: describeAction(tool, call)
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
return;
|
|
1397
1425
|
}
|
|
1398
1426
|
for await (const toolEvent of runTools(approved, this.tools, context, this.txMutex)) {
|
|
1399
1427
|
yield toolEvent;
|
|
@@ -1414,25 +1442,6 @@ var QueryEngine = class {
|
|
|
1414
1442
|
}
|
|
1415
1443
|
yield { type: "turn_complete", stopReason: "max_turns" };
|
|
1416
1444
|
}
|
|
1417
|
-
interrupt() {
|
|
1418
|
-
this.abortController?.abort();
|
|
1419
|
-
}
|
|
1420
|
-
getMessages() {
|
|
1421
|
-
return this.messages;
|
|
1422
|
-
}
|
|
1423
|
-
reset() {
|
|
1424
|
-
this.messages = [];
|
|
1425
|
-
this.costTracker.reset();
|
|
1426
|
-
}
|
|
1427
|
-
loadMessages(messages) {
|
|
1428
|
-
this.messages = sanitizeMessages(messages);
|
|
1429
|
-
}
|
|
1430
|
-
setServerPositions(data) {
|
|
1431
|
-
this.serverPositions = data;
|
|
1432
|
-
}
|
|
1433
|
-
getUsage() {
|
|
1434
|
-
return this.costTracker.getSnapshot();
|
|
1435
|
-
}
|
|
1436
1445
|
// ---------------------------------------------------------------------------
|
|
1437
1446
|
// Internal
|
|
1438
1447
|
// ---------------------------------------------------------------------------
|
|
@@ -1491,8 +1500,12 @@ var QueryEngine = class {
|
|
|
1491
1500
|
}
|
|
1492
1501
|
}
|
|
1493
1502
|
};
|
|
1503
|
+
function isCorruptHistoryError(err) {
|
|
1504
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1505
|
+
return msg.includes("tool_use") && msg.includes("tool_result") || msg.includes("roles must alternate") || msg.includes("400") && msg.includes("invalid_request_error");
|
|
1506
|
+
}
|
|
1494
1507
|
function sanitizeMessages(messages) {
|
|
1495
|
-
const
|
|
1508
|
+
const trimmed = [];
|
|
1496
1509
|
for (let i = 0; i < messages.length; i++) {
|
|
1497
1510
|
const msg = messages[i];
|
|
1498
1511
|
const toolUseIds = msg.content.filter((b) => b.type === "tool_use").map((b) => b.id);
|
|
@@ -1506,7 +1519,19 @@ function sanitizeMessages(messages) {
|
|
|
1506
1519
|
break;
|
|
1507
1520
|
}
|
|
1508
1521
|
}
|
|
1522
|
+
trimmed.push(msg);
|
|
1523
|
+
}
|
|
1524
|
+
const result = [];
|
|
1525
|
+
let lastRole = null;
|
|
1526
|
+
for (const msg of trimmed) {
|
|
1527
|
+
if (msg.role === lastRole) {
|
|
1528
|
+
result.pop();
|
|
1529
|
+
}
|
|
1509
1530
|
result.push(msg);
|
|
1531
|
+
lastRole = msg.role;
|
|
1532
|
+
}
|
|
1533
|
+
while (result.length > 0 && result[result.length - 1].role === "user") {
|
|
1534
|
+
result.pop();
|
|
1510
1535
|
}
|
|
1511
1536
|
return result;
|
|
1512
1537
|
}
|
|
@@ -1549,68 +1574,12 @@ function parseSSE(raw) {
|
|
|
1549
1574
|
return null;
|
|
1550
1575
|
}
|
|
1551
1576
|
}
|
|
1552
|
-
|
|
1553
|
-
pending = /* @__PURE__ */ new Map();
|
|
1554
|
-
counter = 0;
|
|
1555
|
-
/**
|
|
1556
|
-
* Register a permission_request resolve callback.
|
|
1557
|
-
* Returns the permissionId to send to the client.
|
|
1558
|
-
*/
|
|
1559
|
-
register(resolve) {
|
|
1560
|
-
const id = `perm_${++this.counter}_${Date.now()}`;
|
|
1561
|
-
this.pending.set(id, resolve);
|
|
1562
|
-
return id;
|
|
1563
|
-
}
|
|
1564
|
-
/**
|
|
1565
|
-
* Resolve a pending permission request from the client.
|
|
1566
|
-
* Pass `executionResult` when the client executed the action itself
|
|
1567
|
-
* (e.g., signed a transaction) so the engine can skip server-side execution.
|
|
1568
|
-
*/
|
|
1569
|
-
resolve(permissionId, approved, executionResult) {
|
|
1570
|
-
const resolver = this.pending.get(permissionId);
|
|
1571
|
-
if (!resolver) return false;
|
|
1572
|
-
resolver({ approved, executionResult });
|
|
1573
|
-
this.pending.delete(permissionId);
|
|
1574
|
-
return true;
|
|
1575
|
-
}
|
|
1576
|
-
/** Number of pending (unresolved) permission requests. */
|
|
1577
|
-
get size() {
|
|
1578
|
-
return this.pending.size;
|
|
1579
|
-
}
|
|
1580
|
-
/** Reject all pending permissions (e.g., on disconnect). */
|
|
1581
|
-
rejectAll() {
|
|
1582
|
-
for (const resolver of this.pending.values()) {
|
|
1583
|
-
resolver({ approved: false });
|
|
1584
|
-
}
|
|
1585
|
-
this.pending.clear();
|
|
1586
|
-
}
|
|
1587
|
-
};
|
|
1588
|
-
async function* engineToSSE(events, bridge) {
|
|
1577
|
+
async function* engineToSSE(events) {
|
|
1589
1578
|
for await (const event of events) {
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
type: "permission_request",
|
|
1595
|
-
permissionId,
|
|
1596
|
-
toolName: event.toolName,
|
|
1597
|
-
toolUseId: event.toolUseId,
|
|
1598
|
-
input: event.input,
|
|
1599
|
-
description: event.description
|
|
1600
|
-
});
|
|
1601
|
-
break;
|
|
1602
|
-
}
|
|
1603
|
-
case "error": {
|
|
1604
|
-
yield serializeSSE({
|
|
1605
|
-
type: "error",
|
|
1606
|
-
message: event.error.message
|
|
1607
|
-
});
|
|
1608
|
-
break;
|
|
1609
|
-
}
|
|
1610
|
-
default: {
|
|
1611
|
-
yield serializeSSE(event);
|
|
1612
|
-
break;
|
|
1613
|
-
}
|
|
1579
|
+
if (event.type === "error") {
|
|
1580
|
+
yield serializeSSE({ type: "error", message: event.error.message });
|
|
1581
|
+
} else {
|
|
1582
|
+
yield serializeSSE(event);
|
|
1614
1583
|
}
|
|
1615
1584
|
}
|
|
1616
1585
|
}
|
|
@@ -2213,6 +2182,6 @@ function mapStopReason(reason) {
|
|
|
2213
2182
|
}
|
|
2214
2183
|
}
|
|
2215
2184
|
|
|
2216
|
-
export { AnthropicProvider, CostTracker, DEFAULT_SYSTEM_PROMPT, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_SERVER_NAME, NaviTools,
|
|
2185
|
+
export { AnthropicProvider, CostTracker, DEFAULT_SYSTEM_PROMPT, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_SERVER_NAME, NaviTools, QueryEngine, READ_TOOLS, TxMutex, WRITE_TOOLS, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, balanceCheckTool, borrowTool, buildMcpTools, buildTool, claimRewardsTool, compactMessages, engineToSSE, estimateTokens, extractMcpText, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchWalletCoins, findTool, getDefaultTools, getMcpManager, getWalletAddress, hasNaviMcp, healthCheckTool, parseMcpJson, parseSSE, payApiTool, ratesInfoTool, registerEngineTools, repayDebtTool, requireAgent, runTools, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, withdrawTool };
|
|
2217
2186
|
//# sourceMappingURL=index.js.map
|
|
2218
2187
|
//# sourceMappingURL=index.js.map
|