@t2000/engine 1.18.0 → 1.19.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 +381 -16
- package/dist/index.js +462 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ function buildTool(opts) {
|
|
|
19
19
|
jsonSchema: opts.jsonSchema,
|
|
20
20
|
call: opts.call,
|
|
21
21
|
isReadOnly,
|
|
22
|
-
isConcurrencySafe: isReadOnly,
|
|
22
|
+
isConcurrencySafe: opts.isConcurrencySafe ?? isReadOnly,
|
|
23
23
|
permissionLevel: opts.permissionLevel ?? (isReadOnly ? "auto" : "confirm"),
|
|
24
24
|
flags: opts.flags ?? {},
|
|
25
25
|
preflight: opts.preflight,
|
|
@@ -5171,14 +5171,22 @@ var todoStatusSchema = z.enum(["pending", "in_progress", "completed"]);
|
|
|
5171
5171
|
var todoItemSchema = z.object({
|
|
5172
5172
|
id: z.string().min(1, "id must be a non-empty string").max(40, "id must be \u226440 chars (use a slug, not a sentence)"),
|
|
5173
5173
|
label: z.string().min(1, "label must be a non-empty string").max(80, "label must be \u226480 chars (the whole point of this tool is concision)"),
|
|
5174
|
-
status: todoStatusSchema
|
|
5174
|
+
status: todoStatusSchema,
|
|
5175
|
+
// [SPEC 9 v0.1.3 P9.3] Per-item persistence flag — opt this todo item
|
|
5176
|
+
// into the long-lived `Goal` row surface. Hosts that wire goal storage
|
|
5177
|
+
// (audric) write a Goal row with `content: label`, `status: 'in_progress'`,
|
|
5178
|
+
// `sourceSessionId: <currentSession>` when this flag is true. Default
|
|
5179
|
+
// false — most turn-scoped items don't survive the turn. Engine is
|
|
5180
|
+
// unaware of how/where the host persists; it just passes the flag
|
|
5181
|
+
// through on the `todo_update` side-channel event.
|
|
5182
|
+
persist: z.boolean().optional()
|
|
5175
5183
|
});
|
|
5176
5184
|
var inputSchema6 = z.object({
|
|
5177
5185
|
items: z.array(todoItemSchema).min(1, "items must contain at least 1 entry").max(8, "items must contain at most 8 entries (SPEC 8 ceiling)")
|
|
5178
5186
|
});
|
|
5179
5187
|
var updateTodoTool = buildTool({
|
|
5180
5188
|
name: "update_todo",
|
|
5181
|
-
description: "Declare or replace your plan for the current turn as a structured todo list. Call this when the user's ask is multi-step (\u22653 tools, \u22652 reasoning hops) so the user can see what you're doing as you do it. Each call replaces the entire list \u2014 the tool is idempotent. \n\nRules: 1\u20138 items, each label \u226480 chars, exactly 1 item must be `in_progress`. Use stable `id`s across calls within the same turn so the UI can track item transitions (e.g. `id: 'check-balance'` first as `pending`, later as `completed`). \n\nDO NOT call this for single-step asks ('balance', 'rate') \u2014 it's wasted tokens. DO call it before kicking off long flows where the user benefits from seeing the plan unfold ('save my idle USDC' \u2192 check balance \u2192 check rates \u2192 compute split \u2192 propose). \n\nThis call doesn't count against your turn budget \u2014 re-narrating the plan as items move from pending \u2192 in_progress \u2192 completed is encouraged.",
|
|
5189
|
+
description: "Declare or replace your plan for the current turn as a structured todo list. Call this when the user's ask is multi-step (\u22653 tools, \u22652 reasoning hops) so the user can see what you're doing as you do it. Each call replaces the entire list \u2014 the tool is idempotent. \n\nRules: 1\u20138 items, each label \u226480 chars, exactly 1 item must be `in_progress`. Use stable `id`s across calls within the same turn so the UI can track item transitions (e.g. `id: 'check-balance'` first as `pending`, later as `completed`). \n\nDO NOT call this for single-step asks ('balance', 'rate') \u2014 it's wasted tokens. DO call it before kicking off long flows where the user benefits from seeing the plan unfold ('save my idle USDC' \u2192 check balance \u2192 check rates \u2192 compute split \u2192 propose). \n\nThis call doesn't count against your turn budget \u2014 re-narrating the plan as items move from pending \u2192 in_progress \u2192 completed is encouraged. \n\n[SPEC 9 v0.1.3] To promote an item into a long-lived goal that survives across sessions, set `persist: true` on that item. Reserve this for multi-week commitments the user explicitly wants remembered (e.g. \"save $500 by month-end\", \"track NAVI USDC APY weekly\"). DO NOT set persist on within-turn steps (\"check balance\", \"compute split\") \u2014 those vanish when the turn ends, which is what you want. Default behaviour (no persist field) is don't-persist.",
|
|
5182
5190
|
inputSchema: inputSchema6,
|
|
5183
5191
|
jsonSchema: {
|
|
5184
5192
|
type: "object",
|
|
@@ -5202,6 +5210,10 @@ var updateTodoTool = buildTool({
|
|
|
5202
5210
|
type: "string",
|
|
5203
5211
|
enum: ["pending", "in_progress", "completed"],
|
|
5204
5212
|
description: "Lifecycle state. Exactly one item must be `in_progress` per call."
|
|
5213
|
+
},
|
|
5214
|
+
persist: {
|
|
5215
|
+
type: "boolean",
|
|
5216
|
+
description: 'Set true to promote this item into a long-lived goal that survives across sessions (e.g. "save $500 by month-end"). Default false \u2014 only set true when the item represents a multi-week / multi-session commitment, not a within-turn step. When false or omitted, the item lives only for this turn.'
|
|
5205
5217
|
}
|
|
5206
5218
|
},
|
|
5207
5219
|
required: ["id", "label", "status"]
|
|
@@ -5268,6 +5280,92 @@ var updateTodoTool = buildTool({
|
|
|
5268
5280
|
};
|
|
5269
5281
|
}
|
|
5270
5282
|
});
|
|
5283
|
+
var ADD_RECIPIENT_FORM = {
|
|
5284
|
+
fields: [
|
|
5285
|
+
{
|
|
5286
|
+
name: "name",
|
|
5287
|
+
label: "Nickname",
|
|
5288
|
+
kind: "text",
|
|
5289
|
+
required: true,
|
|
5290
|
+
placeholder: "Mom",
|
|
5291
|
+
helpText: "How you'll refer to this contact in chat."
|
|
5292
|
+
},
|
|
5293
|
+
{
|
|
5294
|
+
name: "identifier",
|
|
5295
|
+
label: "Audric handle, SuiNS name, or wallet address",
|
|
5296
|
+
// [v0.1.3 R6] Polymorphic kind — accepts handles, names, and 0x.
|
|
5297
|
+
// The host renderer treats this as a single text input with
|
|
5298
|
+
// help-text guidance; server-side `normalizeAddressInput` does
|
|
5299
|
+
// the resolution.
|
|
5300
|
+
kind: "sui-recipient",
|
|
5301
|
+
required: true,
|
|
5302
|
+
placeholder: "mom.audric.sui / alex.sui / 0x40cd\u20263e62",
|
|
5303
|
+
helpText: "Type @alice for an Audric user, alex.sui for any SuiNS, or paste a 0x address. We'll resolve it to the canonical wallet automatically."
|
|
5304
|
+
}
|
|
5305
|
+
]
|
|
5306
|
+
};
|
|
5307
|
+
var addRecipientTool = buildTool({
|
|
5308
|
+
name: "add_recipient",
|
|
5309
|
+
description: `Add a new contact to the user's saved-recipients list. Call this when you (the LLM) need to reference a contact that isn't saved yet \u2014 e.g. the user said "send $10 to Mom" but no contact named "Mom" exists. The user will fill in the nickname + identifier (an Audric handle, SuiNS name, or wallet address) via an inline form. The contact is persisted before this tool returns; the resumed call returns confirmation only. Do NOT call when the user manually opens the contact-add UI from settings \u2014 that's a separate user-initiated flow that doesn't need the LLM. Only call when YOU need to add a contact mid-conversation to make a downstream action work.`,
|
|
5310
|
+
inputSchema: z.object({
|
|
5311
|
+
name: z.string().min(1).optional(),
|
|
5312
|
+
identifier: z.string().min(1).optional()
|
|
5313
|
+
}),
|
|
5314
|
+
jsonSchema: {
|
|
5315
|
+
type: "object",
|
|
5316
|
+
properties: {
|
|
5317
|
+
name: {
|
|
5318
|
+
type: "string",
|
|
5319
|
+
description: 'Optional nickname for the contact ("Mom"). Omit to let the user fill the form.'
|
|
5320
|
+
},
|
|
5321
|
+
identifier: {
|
|
5322
|
+
type: "string",
|
|
5323
|
+
description: "Optional polymorphic identifier (Audric handle, SuiNS name, or 0x address). Omit to let the user fill the form."
|
|
5324
|
+
}
|
|
5325
|
+
},
|
|
5326
|
+
required: []
|
|
5327
|
+
},
|
|
5328
|
+
// Permission: read-only from the engine's perspective. The HOST writes
|
|
5329
|
+
// the Contact row in the resume endpoint; the tool's call() body is a
|
|
5330
|
+
// thin confirmation message. Treating as read-only keeps the engine's
|
|
5331
|
+
// permission gate from yielding `pending_action` (which would conflict
|
|
5332
|
+
// with the `pending_input` flow — you'd get a form, then a confirm card,
|
|
5333
|
+
// for what's semantically one user action).
|
|
5334
|
+
isReadOnly: true,
|
|
5335
|
+
// [SPEC 9 v0.1.3 P9.4] Opt out of EarlyToolDispatcher. Early-dispatch
|
|
5336
|
+
// runs the tool's call() mid-stream BEFORE the post-stream guard loop
|
|
5337
|
+
// (where preflight is invoked). If add_recipient ran via early-dispatch,
|
|
5338
|
+
// call() would fire with name/identifier=undefined and "save" garbage
|
|
5339
|
+
// before the form pause path is even consulted. Forcing the tool
|
|
5340
|
+
// through the post-stream loop guarantees preflight runs first.
|
|
5341
|
+
isConcurrencySafe: false,
|
|
5342
|
+
permissionLevel: "auto",
|
|
5343
|
+
flags: {},
|
|
5344
|
+
preflight: (input) => {
|
|
5345
|
+
if (!input.name || !input.identifier) {
|
|
5346
|
+
return {
|
|
5347
|
+
valid: false,
|
|
5348
|
+
needsInput: {
|
|
5349
|
+
schema: ADD_RECIPIENT_FORM,
|
|
5350
|
+
description: "Add a new contact"
|
|
5351
|
+
}
|
|
5352
|
+
};
|
|
5353
|
+
}
|
|
5354
|
+
return { valid: true };
|
|
5355
|
+
},
|
|
5356
|
+
async call(input) {
|
|
5357
|
+
const name = input.name;
|
|
5358
|
+
const identifier = input.identifier;
|
|
5359
|
+
return {
|
|
5360
|
+
data: {
|
|
5361
|
+
saved: true,
|
|
5362
|
+
name,
|
|
5363
|
+
identifier
|
|
5364
|
+
},
|
|
5365
|
+
displayText: `Saved ${name} (${identifier}) to contacts.`
|
|
5366
|
+
};
|
|
5367
|
+
}
|
|
5368
|
+
});
|
|
5271
5369
|
var tokenPricesTool = buildTool({
|
|
5272
5370
|
name: "token_prices",
|
|
5273
5371
|
description: '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 \u2014 they bundle the same prices into the standard cards.',
|
|
@@ -5467,7 +5565,70 @@ Only offer to execute actions you have tools for. If you retrieved a quote, data
|
|
|
5467
5565
|
## Safety
|
|
5468
5566
|
- Never encourage risky financial behavior.
|
|
5469
5567
|
- Warn when health factor < 1.5.
|
|
5470
|
-
- All amounts in USDC unless stated otherwise
|
|
5568
|
+
- All amounts in USDC unless stated otherwise.
|
|
5569
|
+
|
|
5570
|
+
## Proactive insights (only when there's a clear opportunity)
|
|
5571
|
+
- When you spot an unsolicited financial insight worth surfacing \u2014 idle balance worth saving, health factor approaching the warning band, APY drift on a known position, progress against a saved goal \u2014 wrap your ENTIRE response in a \`<proactive type="..." subjectKey="...">BODY</proactive>\` block.
|
|
5572
|
+
- The host renders proactive blocks with a distinct "\u2726 ADDED BY AUDRIC" lockup so the user knows this is your suggestion, not an answer to a question.
|
|
5573
|
+
- Allowed types (closed list \u2014 anything else is dropped): \`idle_balance\` (cash sitting idle that could earn yield), \`hf_warning\` (debt position approaching liquidation), \`apy_drift\` (rate change on a position they hold), \`goal_progress\` (update on a saved goal).
|
|
5574
|
+
- \`subjectKey\` is a stable identifier for the SPECIFIC subject \u2014 examples: \`USDC\` for an idle-balance insight on USDC, \`1.45\` for a HF warning at that level, \`save-500-by-may\` for goal progress. Same (type, subjectKey) won't fire twice in one session \u2014 pick the same key for the same subject so the engine cooldown works.
|
|
5575
|
+
- Cap: at most ONE proactive block per turn. Do NOT mix proactive insights with answers to user questions \u2014 if the user asked a question, answer it; emit a proactive block only when there's no user question OR when the question is unrelated to the insight.
|
|
5576
|
+
- Skip proactive blocks when nothing notable changed since the last turn, when the user is mid-flow on something else, or when you'd just be restating the financial-context block. Quality over quantity \u2014 a block ignored is worse than no block.`;
|
|
5577
|
+
|
|
5578
|
+
// src/proactive-marker.ts
|
|
5579
|
+
var VALID_TYPES = /* @__PURE__ */ new Set([
|
|
5580
|
+
"idle_balance",
|
|
5581
|
+
"hf_warning",
|
|
5582
|
+
"apy_drift",
|
|
5583
|
+
"goal_progress"
|
|
5584
|
+
]);
|
|
5585
|
+
var MARKER_REGEX = /<proactive\s+([^>]+)>([\s\S]*?)<\/proactive>/g;
|
|
5586
|
+
var ATTR_TYPE_REGEX = /\btype\s*=\s*"([^"]+)"/;
|
|
5587
|
+
var ATTR_SUBJECT_KEY_REGEX = /\bsubjectKey\s*=\s*"([^"]+)"/;
|
|
5588
|
+
function parseProactiveMarker(text) {
|
|
5589
|
+
if (!text.includes("<proactive")) return null;
|
|
5590
|
+
const matches = [];
|
|
5591
|
+
for (const match of text.matchAll(MARKER_REGEX)) {
|
|
5592
|
+
matches.push({ attrs: match[1] ?? "", body: match[2] ?? "" });
|
|
5593
|
+
}
|
|
5594
|
+
if (matches.length === 0) return null;
|
|
5595
|
+
for (const { attrs, body } of matches) {
|
|
5596
|
+
const typeMatch = attrs.match(ATTR_TYPE_REGEX);
|
|
5597
|
+
const subjectKeyMatch = attrs.match(ATTR_SUBJECT_KEY_REGEX);
|
|
5598
|
+
if (!typeMatch || !subjectKeyMatch) continue;
|
|
5599
|
+
const proactiveType = typeMatch[1];
|
|
5600
|
+
const subjectKey = subjectKeyMatch[1].trim();
|
|
5601
|
+
if (!VALID_TYPES.has(proactiveType)) continue;
|
|
5602
|
+
if (subjectKey.length === 0) continue;
|
|
5603
|
+
const trimmedBody = body.trim();
|
|
5604
|
+
if (trimmedBody.length === 0) continue;
|
|
5605
|
+
return {
|
|
5606
|
+
proactiveType,
|
|
5607
|
+
subjectKey,
|
|
5608
|
+
body: trimmedBody,
|
|
5609
|
+
markerCount: matches.length
|
|
5610
|
+
};
|
|
5611
|
+
}
|
|
5612
|
+
return null;
|
|
5613
|
+
}
|
|
5614
|
+
function stripProactiveMarkers(text) {
|
|
5615
|
+
if (!text.includes("<proactive")) return text;
|
|
5616
|
+
return text.replace(MARKER_REGEX, (_match, _attrs, body) => body);
|
|
5617
|
+
}
|
|
5618
|
+
function extractAllProactiveMarkers(text) {
|
|
5619
|
+
if (!text.includes("<proactive")) return [];
|
|
5620
|
+
const out = [];
|
|
5621
|
+
for (const match of text.matchAll(MARKER_REGEX)) {
|
|
5622
|
+
const attrs = match[1] ?? "";
|
|
5623
|
+
const typeMatch = attrs.match(ATTR_TYPE_REGEX);
|
|
5624
|
+
const subjectKeyMatch = attrs.match(ATTR_SUBJECT_KEY_REGEX);
|
|
5625
|
+
if (!typeMatch || !subjectKeyMatch) continue;
|
|
5626
|
+
const subjectKey = subjectKeyMatch[1].trim();
|
|
5627
|
+
if (subjectKey.length === 0) continue;
|
|
5628
|
+
out.push({ proactiveType: typeMatch[1], subjectKey });
|
|
5629
|
+
}
|
|
5630
|
+
return out;
|
|
5631
|
+
}
|
|
5471
5632
|
|
|
5472
5633
|
// src/cost.ts
|
|
5473
5634
|
var DEFAULT_INPUT_COST = 3 / 1e6;
|
|
@@ -6024,6 +6185,29 @@ function runGuards(tool, call, state, config, conversationContext, onGuardFired,
|
|
|
6024
6185
|
if (config.inputValidation !== false && tool.preflight) {
|
|
6025
6186
|
const check = tool.preflight(call.input);
|
|
6026
6187
|
if (!check.valid) {
|
|
6188
|
+
if ("needsInput" in check && check.needsInput) {
|
|
6189
|
+
const event2 = {
|
|
6190
|
+
timestamp: now,
|
|
6191
|
+
toolName: tool.name,
|
|
6192
|
+
toolUseId: call.id,
|
|
6193
|
+
gate: "input_validation",
|
|
6194
|
+
verdict: "pass",
|
|
6195
|
+
tier: "safety",
|
|
6196
|
+
message: check.needsInput.description
|
|
6197
|
+
};
|
|
6198
|
+
fire("pass", "safety", "input_validation", false);
|
|
6199
|
+
return {
|
|
6200
|
+
blocked: false,
|
|
6201
|
+
injections: [],
|
|
6202
|
+
events: [event2],
|
|
6203
|
+
needsInput: check.needsInput
|
|
6204
|
+
};
|
|
6205
|
+
}
|
|
6206
|
+
if (!("error" in check)) {
|
|
6207
|
+
throw new Error(
|
|
6208
|
+
`Preflight returned a non-needsInput, non-error invalid result for tool ${tool.name}`
|
|
6209
|
+
);
|
|
6210
|
+
}
|
|
6027
6211
|
const event = {
|
|
6028
6212
|
timestamp: now,
|
|
6029
6213
|
toolName: tool.name,
|
|
@@ -6945,6 +7129,26 @@ var QueryEngine = class {
|
|
|
6945
7129
|
// their `finally` block so they DON'T clear the cache mid-turn — the
|
|
6946
7130
|
// pending write may resume, and the cache should survive the pause.
|
|
6947
7131
|
turnPaused = false;
|
|
7132
|
+
// [SPEC 9 v0.1.1 P9.2 / R3] Per-engine-instance cooldown set for
|
|
7133
|
+
// proactive insight markers. Same `(proactiveType, subjectKey)` tuple
|
|
7134
|
+
// emitted twice in one session ⇒ second emission is suppressed (host
|
|
7135
|
+
// strips the wrapper, renders body as plain text). Cooldown is
|
|
7136
|
+
// per-session, not cross-session — a fresh QueryEngine on the next
|
|
7137
|
+
// user session starts with an empty set and may re-emit the same
|
|
7138
|
+
// tuple. Drops automatically when the engine is GC'd.
|
|
7139
|
+
//
|
|
7140
|
+
// Storage shape: serialised key `${type}:${subjectKey}` for cheap
|
|
7141
|
+
// Set membership without an extra hash function.
|
|
7142
|
+
proactiveCooldown = /* @__PURE__ */ new Set();
|
|
7143
|
+
// [SPEC 9 v0.1.3 P9.4] In-flight `pending_input` state, keyed by `inputId`.
|
|
7144
|
+
// Set when the agent loop hits a tool whose preflight returned `needsInput`;
|
|
7145
|
+
// consulted by `resumeWithInput()` to look up which paused tool call to
|
|
7146
|
+
// re-feed with the user's submitted values. Cleared on resume (whether
|
|
7147
|
+
// success or abandonment via a fresh `submitMessage`). Multiple concurrent
|
|
7148
|
+
// entries are allowed in principle (LLM could call two `add_recipient`s
|
|
7149
|
+
// in one turn) but in practice we yield + return on the FIRST hit, so
|
|
7150
|
+
// the map is almost always 0 or 1 entries deep.
|
|
7151
|
+
pendingInputs = /* @__PURE__ */ new Map();
|
|
6948
7152
|
constructor(config) {
|
|
6949
7153
|
this.provider = config.provider;
|
|
6950
7154
|
this.agent = config.agent;
|
|
@@ -7168,6 +7372,159 @@ var QueryEngine = class {
|
|
|
7168
7372
|
}
|
|
7169
7373
|
}
|
|
7170
7374
|
}
|
|
7375
|
+
/**
|
|
7376
|
+
* [SPEC 9 v0.1.3 P9.4] Resume a turn that paused on `pending_input`.
|
|
7377
|
+
*
|
|
7378
|
+
* Called by the host after the user submitted the inline form. The
|
|
7379
|
+
* `pendingInput` argument is the EXACT payload that was yielded as
|
|
7380
|
+
* `pending_input` (host stored it in session storage); `values` is the
|
|
7381
|
+
* `{ fieldName: value }` map the user submitted, post-host-validation
|
|
7382
|
+
* against `pendingInput.schema`.
|
|
7383
|
+
*
|
|
7384
|
+
* Engine responsibilities (in order):
|
|
7385
|
+
* 1. Push the captured `assistantContent` (assistant blocks from the
|
|
7386
|
+
* paused turn — includes the tool_use that triggered this pause).
|
|
7387
|
+
* 2. Run the paused tool's `call()` with `values` as input. Re-runs
|
|
7388
|
+
* preflight first as a defense-in-depth gate (host SHOULD have
|
|
7389
|
+
* validated against the schema, but malformed input would otherwise
|
|
7390
|
+
* poison the conversation history with an orphan tool_use).
|
|
7391
|
+
* 3. Combine `completedResults` (read tool_results that already ran in
|
|
7392
|
+
* the same turn before the pause) with the new tool_result into ONE
|
|
7393
|
+
* user-role message. Anthropic's API requires every tool_use to have
|
|
7394
|
+
* a tool_result in the immediately-following user message — splitting
|
|
7395
|
+
* them would produce two consecutive user messages, which the API
|
|
7396
|
+
* rejects.
|
|
7397
|
+
* 4. Yield `tool_result` for the host's timeline + run `agentLoop` to
|
|
7398
|
+
* continue the turn (LLM gets the resumed result and narrates).
|
|
7399
|
+
*
|
|
7400
|
+
* Mirrors `resumeWithToolResult` for the user-confirm case but feeds
|
|
7401
|
+
* the values back as the tool's INPUT (the call() runs here for the
|
|
7402
|
+
* first time) instead of as the tool's OUTPUT (the call() ran on the
|
|
7403
|
+
* client side via sponsored-tx for pending_action).
|
|
7404
|
+
*/
|
|
7405
|
+
async *resumeWithInput(pendingInput, values) {
|
|
7406
|
+
this.abortController = new AbortController();
|
|
7407
|
+
const signal = this.abortController.signal;
|
|
7408
|
+
if (pendingInput.assistantContent.length > 0) {
|
|
7409
|
+
this.messages.push({
|
|
7410
|
+
role: "assistant",
|
|
7411
|
+
content: pendingInput.assistantContent
|
|
7412
|
+
});
|
|
7413
|
+
}
|
|
7414
|
+
const tool = findTool(this.tools, pendingInput.toolName);
|
|
7415
|
+
let resumedToolResult;
|
|
7416
|
+
let toolResultEventPayload;
|
|
7417
|
+
if (!tool) {
|
|
7418
|
+
const errorPayload = {
|
|
7419
|
+
error: `Tool "${pendingInput.toolName}" not found on resume \u2014 engine may have been reconfigured between pause and resume.`,
|
|
7420
|
+
_hostBugMissingTool: true
|
|
7421
|
+
};
|
|
7422
|
+
resumedToolResult = {
|
|
7423
|
+
content: JSON.stringify(errorPayload),
|
|
7424
|
+
isError: true
|
|
7425
|
+
};
|
|
7426
|
+
toolResultEventPayload = { result: errorPayload, isError: true };
|
|
7427
|
+
} else {
|
|
7428
|
+
const preflightCheck = tool.preflight ? tool.preflight(values) : { valid: true };
|
|
7429
|
+
if (!preflightCheck.valid && "error" in preflightCheck) {
|
|
7430
|
+
const errorPayload = {
|
|
7431
|
+
error: `Form values failed re-validation: ${preflightCheck.error}`,
|
|
7432
|
+
_hostFormValidationFailed: true
|
|
7433
|
+
};
|
|
7434
|
+
resumedToolResult = {
|
|
7435
|
+
content: JSON.stringify(errorPayload),
|
|
7436
|
+
isError: true
|
|
7437
|
+
};
|
|
7438
|
+
toolResultEventPayload = { result: errorPayload, isError: true };
|
|
7439
|
+
} else if (!preflightCheck.valid && "needsInput" in preflightCheck) {
|
|
7440
|
+
const errorPayload = {
|
|
7441
|
+
error: "Tool requested another form on resume \u2014 multi-step forms are not supported in v0.1.3. Re-prompt the user with a fresh single-step request.",
|
|
7442
|
+
_multiStepFormUnsupported: true
|
|
7443
|
+
};
|
|
7444
|
+
resumedToolResult = {
|
|
7445
|
+
content: JSON.stringify(errorPayload),
|
|
7446
|
+
isError: true
|
|
7447
|
+
};
|
|
7448
|
+
toolResultEventPayload = { result: errorPayload, isError: true };
|
|
7449
|
+
} else {
|
|
7450
|
+
const parsed = tool.inputSchema.safeParse(values);
|
|
7451
|
+
if (!parsed.success) {
|
|
7452
|
+
const errorPayload = {
|
|
7453
|
+
error: `Invalid input on resume: ${parsed.error.issues.map((i) => i.message).join(", ")}`,
|
|
7454
|
+
_hostFormZodFailed: true
|
|
7455
|
+
};
|
|
7456
|
+
resumedToolResult = {
|
|
7457
|
+
content: JSON.stringify(errorPayload),
|
|
7458
|
+
isError: true
|
|
7459
|
+
};
|
|
7460
|
+
toolResultEventPayload = { result: errorPayload, isError: true };
|
|
7461
|
+
} else {
|
|
7462
|
+
const context = {
|
|
7463
|
+
agent: this.agent,
|
|
7464
|
+
mcpManager: this.mcpManager,
|
|
7465
|
+
walletAddress: this.walletAddress,
|
|
7466
|
+
suiRpcUrl: this.suiRpcUrl,
|
|
7467
|
+
serverPositions: this.serverPositions,
|
|
7468
|
+
positionFetcher: this.positionFetcher,
|
|
7469
|
+
env: this.env,
|
|
7470
|
+
signal,
|
|
7471
|
+
priceCache: this.priceCache,
|
|
7472
|
+
permissionConfig: this.permissionConfig,
|
|
7473
|
+
sessionSpendUsd: this.sessionSpendUsd,
|
|
7474
|
+
blockvisionApiKey: this.blockvisionApiKey,
|
|
7475
|
+
portfolioCache: this.portfolioCache
|
|
7476
|
+
};
|
|
7477
|
+
try {
|
|
7478
|
+
const callResult = await tool.call(parsed.data, context);
|
|
7479
|
+
resumedToolResult = {
|
|
7480
|
+
content: JSON.stringify(callResult.data),
|
|
7481
|
+
isError: false
|
|
7482
|
+
};
|
|
7483
|
+
toolResultEventPayload = { result: callResult.data, isError: false };
|
|
7484
|
+
} catch (err) {
|
|
7485
|
+
const message = err instanceof Error ? err.message : "Tool execution failed";
|
|
7486
|
+
const errorPayload = { error: message };
|
|
7487
|
+
resumedToolResult = {
|
|
7488
|
+
content: JSON.stringify(errorPayload),
|
|
7489
|
+
isError: true
|
|
7490
|
+
};
|
|
7491
|
+
toolResultEventPayload = { result: errorPayload, isError: true };
|
|
7492
|
+
}
|
|
7493
|
+
}
|
|
7494
|
+
}
|
|
7495
|
+
}
|
|
7496
|
+
const userMessageBlocks = [
|
|
7497
|
+
...pendingInput.completedResults.map((r) => ({
|
|
7498
|
+
type: "tool_result",
|
|
7499
|
+
toolUseId: r.toolUseId,
|
|
7500
|
+
content: r.content,
|
|
7501
|
+
isError: r.isError
|
|
7502
|
+
})),
|
|
7503
|
+
{
|
|
7504
|
+
type: "tool_result",
|
|
7505
|
+
toolUseId: pendingInput.toolUseId,
|
|
7506
|
+
content: resumedToolResult.content,
|
|
7507
|
+
isError: resumedToolResult.isError
|
|
7508
|
+
}
|
|
7509
|
+
];
|
|
7510
|
+
this.messages.push({ role: "user", content: userMessageBlocks });
|
|
7511
|
+
yield {
|
|
7512
|
+
type: "tool_result",
|
|
7513
|
+
toolName: pendingInput.toolName,
|
|
7514
|
+
toolUseId: pendingInput.toolUseId,
|
|
7515
|
+
result: toolResultEventPayload.result,
|
|
7516
|
+
isError: toolResultEventPayload.isError
|
|
7517
|
+
};
|
|
7518
|
+
this.pendingInputs.delete(pendingInput.inputId);
|
|
7519
|
+
this.turnPaused = false;
|
|
7520
|
+
try {
|
|
7521
|
+
yield* this.agentLoop(null, signal, false);
|
|
7522
|
+
} finally {
|
|
7523
|
+
if (!this.turnPaused) {
|
|
7524
|
+
this.turnReadCache.clear();
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7527
|
+
}
|
|
7171
7528
|
/**
|
|
7172
7529
|
* [v1.5] Auto-run configured read tools after a successful write,
|
|
7173
7530
|
* push their results into the conversation, and yield `tool_result`
|
|
@@ -7338,6 +7695,25 @@ var QueryEngine = class {
|
|
|
7338
7695
|
}
|
|
7339
7696
|
loadMessages(messages) {
|
|
7340
7697
|
this.messages = [...messages];
|
|
7698
|
+
this.rehydrateProactiveCooldown();
|
|
7699
|
+
}
|
|
7700
|
+
/**
|
|
7701
|
+
* [SPEC 9 v0.1.1 P9.2 / R3] Walk loaded assistant text blocks and seed the
|
|
7702
|
+
* cooldown set with every parseable `(proactiveType, subjectKey)` tuple.
|
|
7703
|
+
* Called automatically from `loadMessages`. Idempotent — safe to call on
|
|
7704
|
+
* an already-populated set; duplicates are absorbed by Set semantics.
|
|
7705
|
+
*/
|
|
7706
|
+
rehydrateProactiveCooldown() {
|
|
7707
|
+
for (const message of this.messages) {
|
|
7708
|
+
if (message.role !== "assistant") continue;
|
|
7709
|
+
const blocks = Array.isArray(message.content) ? message.content : [];
|
|
7710
|
+
for (const block of blocks) {
|
|
7711
|
+
if (block.type !== "text" || typeof block.text !== "string") continue;
|
|
7712
|
+
for (const { proactiveType, subjectKey } of extractAllProactiveMarkers(block.text)) {
|
|
7713
|
+
this.proactiveCooldown.add(`${proactiveType}:${subjectKey}`);
|
|
7714
|
+
}
|
|
7715
|
+
}
|
|
7716
|
+
}
|
|
7341
7717
|
}
|
|
7342
7718
|
/**
|
|
7343
7719
|
* [v0.46.7] Run a read-only tool out-of-band, using the engine's tool
|
|
@@ -7745,6 +8121,45 @@ ${recipeCtx}`;
|
|
|
7745
8121
|
});
|
|
7746
8122
|
continue;
|
|
7747
8123
|
}
|
|
8124
|
+
if (check.needsInput) {
|
|
8125
|
+
const inputId = randomUUID();
|
|
8126
|
+
const pendingInput = {
|
|
8127
|
+
inputId,
|
|
8128
|
+
toolName: call.name,
|
|
8129
|
+
toolUseId: call.id,
|
|
8130
|
+
schema: check.needsInput.schema,
|
|
8131
|
+
description: check.needsInput.description,
|
|
8132
|
+
assistantContent: acc.assistantBlocks,
|
|
8133
|
+
completedResults: toolResultBlocks.map((b) => ({
|
|
8134
|
+
toolUseId: b.toolUseId,
|
|
8135
|
+
content: b.content,
|
|
8136
|
+
isError: b.isError ?? false
|
|
8137
|
+
}))
|
|
8138
|
+
};
|
|
8139
|
+
this.pendingInputs.set(inputId, pendingInput);
|
|
8140
|
+
this.turnPaused = true;
|
|
8141
|
+
getTelemetrySink().counter("engine.pending_input_emitted", {
|
|
8142
|
+
tool: call.name
|
|
8143
|
+
});
|
|
8144
|
+
yield {
|
|
8145
|
+
type: "pending_input",
|
|
8146
|
+
inputId,
|
|
8147
|
+
toolName: call.name,
|
|
8148
|
+
toolUseId: call.id,
|
|
8149
|
+
schema: check.needsInput.schema,
|
|
8150
|
+
description: check.needsInput.description,
|
|
8151
|
+
// [SPEC 9 v0.1.3 P9.4] Round-trip fields on the wire so
|
|
8152
|
+
// stateless hosts (audric — request-scoped engines) can
|
|
8153
|
+
// persist + echo back on resume. In-process hosts (CLI,
|
|
8154
|
+
// long-lived engine instances) can ignore — the engine
|
|
8155
|
+
// also stashes the state on `this.pendingInputs[inputId]`
|
|
8156
|
+
// for in-memory recall.
|
|
8157
|
+
assistantContent: pendingInput.assistantContent,
|
|
8158
|
+
completedResults: pendingInput.completedResults
|
|
8159
|
+
};
|
|
8160
|
+
recordTurnOutcome("pending_input");
|
|
8161
|
+
return;
|
|
8162
|
+
}
|
|
7748
8163
|
if (check.injections.length > 0) {
|
|
7749
8164
|
call._guardInjections = check.injections;
|
|
7750
8165
|
}
|
|
@@ -8081,6 +8496,32 @@ ${recipeCtx}`;
|
|
|
8081
8496
|
yield { type: "text_delta", text: event.text };
|
|
8082
8497
|
break;
|
|
8083
8498
|
}
|
|
8499
|
+
case "text_done": {
|
|
8500
|
+
if (event.proactiveMarker) {
|
|
8501
|
+
const { proactiveType, subjectKey, body, markerCount } = event.proactiveMarker;
|
|
8502
|
+
const dedupKey = `${proactiveType}:${subjectKey}`;
|
|
8503
|
+
const suppressed = this.proactiveCooldown.has(dedupKey);
|
|
8504
|
+
if (!suppressed) this.proactiveCooldown.add(dedupKey);
|
|
8505
|
+
const sink = getTelemetrySink();
|
|
8506
|
+
if (suppressed) {
|
|
8507
|
+
sink.counter("audric.harness.proactive_text_suppressed_count", { reason: "cooldown" }, 1);
|
|
8508
|
+
} else {
|
|
8509
|
+
sink.counter("audric.harness.proactive_text_emitted_count", { type: proactiveType }, 1);
|
|
8510
|
+
}
|
|
8511
|
+
if (markerCount > 1) {
|
|
8512
|
+
sink.counter("audric.harness.proactive_marker_violations_count", {}, 1);
|
|
8513
|
+
}
|
|
8514
|
+
yield {
|
|
8515
|
+
type: "proactive_text",
|
|
8516
|
+
proactiveType,
|
|
8517
|
+
subjectKey,
|
|
8518
|
+
body,
|
|
8519
|
+
suppressed,
|
|
8520
|
+
markerCount
|
|
8521
|
+
};
|
|
8522
|
+
}
|
|
8523
|
+
break;
|
|
8524
|
+
}
|
|
8084
8525
|
case "tool_use_done": {
|
|
8085
8526
|
if (acc.text) {
|
|
8086
8527
|
acc.assistantBlocks.push({ type: "text", text: acc.text });
|
|
@@ -8680,7 +9121,7 @@ function classifyEffort(model, userMessage, matchedRecipe, sessionWriteCount) {
|
|
|
8680
9121
|
}
|
|
8681
9122
|
|
|
8682
9123
|
// src/eval-summary.ts
|
|
8683
|
-
var
|
|
9124
|
+
var MARKER_REGEX2 = /<eval_summary>([\s\S]*?)<\/eval_summary>/g;
|
|
8684
9125
|
var VALID_STATUSES = /* @__PURE__ */ new Set([
|
|
8685
9126
|
"good",
|
|
8686
9127
|
"warning",
|
|
@@ -8690,7 +9131,7 @@ var VALID_STATUSES = /* @__PURE__ */ new Set([
|
|
|
8690
9131
|
function parseEvalSummary(thinkingText) {
|
|
8691
9132
|
if (!thinkingText.includes("<eval_summary>")) return null;
|
|
8692
9133
|
const matches = [];
|
|
8693
|
-
for (const match of thinkingText.matchAll(
|
|
9134
|
+
for (const match of thinkingText.matchAll(MARKER_REGEX2)) {
|
|
8694
9135
|
matches.push(match[1] ?? "");
|
|
8695
9136
|
}
|
|
8696
9137
|
if (matches.length === 0) return null;
|
|
@@ -9223,6 +9664,7 @@ var AnthropicProvider = class {
|
|
|
9223
9664
|
const stream = params.signal ? this.client.messages.stream(streamParams, { signal: params.signal }) : this.client.messages.stream(streamParams);
|
|
9224
9665
|
const toolInputBuffers = /* @__PURE__ */ new Map();
|
|
9225
9666
|
const thinkingBuffers = /* @__PURE__ */ new Map();
|
|
9667
|
+
const textBuffers = /* @__PURE__ */ new Map();
|
|
9226
9668
|
let outputTokensFromStart = 0;
|
|
9227
9669
|
try {
|
|
9228
9670
|
for await (const event of stream) {
|
|
@@ -9264,12 +9706,16 @@ var AnthropicProvider = class {
|
|
|
9264
9706
|
thinkingBuffers.set(event.index, { type: "thinking", text: "", signature: "" });
|
|
9265
9707
|
} else if (block.type === "redacted_thinking") {
|
|
9266
9708
|
thinkingBuffers.set(event.index, { type: "redacted_thinking", data: block.data ?? "" });
|
|
9709
|
+
} else if (block.type === "text") {
|
|
9710
|
+
textBuffers.set(event.index, { text: "" });
|
|
9267
9711
|
}
|
|
9268
9712
|
break;
|
|
9269
9713
|
}
|
|
9270
9714
|
case "content_block_delta": {
|
|
9271
9715
|
const delta = event.delta;
|
|
9272
9716
|
if (delta.type === "text_delta") {
|
|
9717
|
+
const buf = textBuffers.get(event.index);
|
|
9718
|
+
if (buf) buf.text += delta.text ?? "";
|
|
9273
9719
|
yield { type: "text_delta", text: delta.text };
|
|
9274
9720
|
} else if (delta.type === "input_json_delta") {
|
|
9275
9721
|
const buf = toolInputBuffers.get(event.index);
|
|
@@ -9323,6 +9769,15 @@ var AnthropicProvider = class {
|
|
|
9323
9769
|
yield { type: "redacted_thinking", data: thinkBuf.data };
|
|
9324
9770
|
thinkingBuffers.delete(event.index);
|
|
9325
9771
|
}
|
|
9772
|
+
const textBuf = textBuffers.get(event.index);
|
|
9773
|
+
if (textBuf) {
|
|
9774
|
+
const proactiveMarker = parseProactiveMarker(textBuf.text);
|
|
9775
|
+
yield {
|
|
9776
|
+
type: "text_done",
|
|
9777
|
+
...proactiveMarker ? { proactiveMarker } : {}
|
|
9778
|
+
};
|
|
9779
|
+
textBuffers.delete(event.index);
|
|
9780
|
+
}
|
|
9326
9781
|
break;
|
|
9327
9782
|
}
|
|
9328
9783
|
case "message_delta": {
|
|
@@ -9531,6 +9986,6 @@ function sanitizeAnthropicMessages(messages) {
|
|
|
9531
9986
|
return merged;
|
|
9532
9987
|
}
|
|
9533
9988
|
|
|
9534
|
-
export { AnthropicProvider, BalanceTracker, CANVAS_TEMPLATES, ContextBudget, CostTracker, DEFAULT_GUARD_CONFIG, DEFAULT_LEASE_SEC, DEFAULT_PERMISSION_CONFIG, DEFAULT_POLL_BUDGET_MS, DEFAULT_POLL_INTERVAL_MS, DEFAULT_SYSTEM_PROMPT, DEFAULT_TOOL_TTL_MS, EFFORT_THINKING_BUDGET_CAPS, EarlyToolDispatcher, InMemoryDefiCacheStore, InMemoryFetchLock, InMemoryNaviCacheStore, InMemoryWalletCacheStore, InvalidAddressError, MAX_BUNDLE_OPS, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_ADDR_TTL_SEC, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_RATES_TTL_SEC, NAVI_SERVER_NAME, NaviTools, PERMISSION_PRESETS, QueryEngine, READ_TOOLS, REGENERATABLE_READ_TOOLS, RecipeRegistry, RetryTracker, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SuinsNotRegisteredError, SuinsRpcError, TOOL_FLAGS, TOOL_MODIFIABLE_FIELDS, TOOL_TTL_MS, TxMutex, VALID_PAIRS, WRITE_TOOLS, _resetNaviCircuitBreaker, activitySummaryTool, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, applyToolFlags, awaitOrFetch, balanceCheckTool, borrowTool, budgetToolResult, buildCachedSystemPrompt, buildMcpTools, buildProactivenessInstructions, buildProfileContext, buildSelfEvaluationInstruction, buildStateContext, buildTool, bundleShortestTtl, checkValidPair, claimRewardsTool, clampThinkingForEffort, classifyEffort, clearPortfolioCache, clearPortfolioCacheFor, clearPriceMapCache, compactMessages, composeBundleFromToolResults, computeRegenerateFields, createGuardRunnerState, engineToSSE, estimateTokens, explainTxTool, extractConversationText, extractMcpText, fetchAddressDefiPortfolio, fetchAddressPortfolio, fetchAudricHistory, fetchAudricPortfolio, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchTokenPrices, fetchWalletCoins, findTool, getAudricApiBase, getDefaultTools, getDefiCacheStore, getFetchLock, getMcpManager, getModifiableFields, getNaviCacheStore, getTelemetrySink, getToolFlags, getWalletAddress, getWalletCacheStore, guardArtifactPreview, guardStaleData, harnessShapeForEffort, hasNaviMcp, healthCheckTool, isBundleableTool, loadRecipes, looksLikeSuiNs, microcompact, mppServicesTool, naviKey, normalizeAddressInput, parseEvalSummary, parseMcpJson, parseRecipe, parseSSE, payApiTool, portfolioAnalysisTool, protocolDeepDiveTool, ratesInfoTool, regenerateBundle, registerEngineTools, renderCanvasTool, repayDebtTool, requireAgent, resetDefiCacheStore, resetFetchLock, resetNaviCacheStore, resetTelemetrySink, resetWalletCacheStore, resolveAddressToSuinsViaRpc, resolvePermissionTier, resolveSuinsTool, resolveSuinsViaRpc, resolveUsdValue, runGuards, runTools, saveContactTool, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, setDefiCacheStore, setFetchLock, setNaviCacheStore, setTelemetrySink, setWalletCacheStore, spendingAnalyticsTool, swapExecuteTool, swapQuoteTool, tokenPricesTool, toolNameToOperation, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, updateGuardStateAfterToolResult, updateTodoTool, validateHistory, voloStakeTool, voloStatsTool, voloUnstakeTool, webSearchTool, withdrawTool, yieldSummaryTool };
|
|
9989
|
+
export { AnthropicProvider, BalanceTracker, CANVAS_TEMPLATES, ContextBudget, CostTracker, DEFAULT_GUARD_CONFIG, DEFAULT_LEASE_SEC, DEFAULT_PERMISSION_CONFIG, DEFAULT_POLL_BUDGET_MS, DEFAULT_POLL_INTERVAL_MS, DEFAULT_SYSTEM_PROMPT, DEFAULT_TOOL_TTL_MS, EFFORT_THINKING_BUDGET_CAPS, EarlyToolDispatcher, InMemoryDefiCacheStore, InMemoryFetchLock, InMemoryNaviCacheStore, InMemoryWalletCacheStore, InvalidAddressError, MAX_BUNDLE_OPS, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_ADDR_TTL_SEC, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_RATES_TTL_SEC, NAVI_SERVER_NAME, NaviTools, PERMISSION_PRESETS, QueryEngine, READ_TOOLS, REGENERATABLE_READ_TOOLS, RecipeRegistry, RetryTracker, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SuinsNotRegisteredError, SuinsRpcError, TOOL_FLAGS, TOOL_MODIFIABLE_FIELDS, TOOL_TTL_MS, TxMutex, VALID_PAIRS, WRITE_TOOLS, _resetNaviCircuitBreaker, activitySummaryTool, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, addRecipientTool, applyToolFlags, awaitOrFetch, balanceCheckTool, borrowTool, budgetToolResult, buildCachedSystemPrompt, buildMcpTools, buildProactivenessInstructions, buildProfileContext, buildSelfEvaluationInstruction, buildStateContext, buildTool, bundleShortestTtl, checkValidPair, claimRewardsTool, clampThinkingForEffort, classifyEffort, clearPortfolioCache, clearPortfolioCacheFor, clearPriceMapCache, compactMessages, composeBundleFromToolResults, computeRegenerateFields, createGuardRunnerState, engineToSSE, estimateTokens, explainTxTool, extractAllProactiveMarkers, extractConversationText, extractMcpText, fetchAddressDefiPortfolio, fetchAddressPortfolio, fetchAudricHistory, fetchAudricPortfolio, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchTokenPrices, fetchWalletCoins, findTool, getAudricApiBase, getDefaultTools, getDefiCacheStore, getFetchLock, getMcpManager, getModifiableFields, getNaviCacheStore, getTelemetrySink, getToolFlags, getWalletAddress, getWalletCacheStore, guardArtifactPreview, guardStaleData, harnessShapeForEffort, hasNaviMcp, healthCheckTool, isBundleableTool, loadRecipes, looksLikeSuiNs, microcompact, mppServicesTool, naviKey, normalizeAddressInput, parseEvalSummary, parseMcpJson, parseProactiveMarker, parseRecipe, parseSSE, payApiTool, portfolioAnalysisTool, protocolDeepDiveTool, ratesInfoTool, regenerateBundle, registerEngineTools, renderCanvasTool, repayDebtTool, requireAgent, resetDefiCacheStore, resetFetchLock, resetNaviCacheStore, resetTelemetrySink, resetWalletCacheStore, resolveAddressToSuinsViaRpc, resolvePermissionTier, resolveSuinsTool, resolveSuinsViaRpc, resolveUsdValue, runGuards, runTools, saveContactTool, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, setDefiCacheStore, setFetchLock, setNaviCacheStore, setTelemetrySink, setWalletCacheStore, spendingAnalyticsTool, stripProactiveMarkers, swapExecuteTool, swapQuoteTool, tokenPricesTool, toolNameToOperation, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, updateGuardStateAfterToolResult, updateTodoTool, validateHistory, voloStakeTool, voloStatsTool, voloUnstakeTool, webSearchTool, withdrawTool, yieldSummaryTool };
|
|
9535
9990
|
//# sourceMappingURL=index.js.map
|
|
9536
9991
|
//# sourceMappingURL=index.js.map
|