@t2000/engine 1.24.7 → 1.24.9

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 CHANGED
@@ -5758,6 +5758,12 @@ Only offer to execute actions you have tools for. If you retrieved a quote, data
5758
5758
  - **\`swap_quote\` returns \`{ errorCode: 'SWAP_FAILED', recoverable: true }\`**: no route or insufficient liquidity. Call \`balance_check\` to confirm the source token is held with the expected amount, then either: try a smaller amount, or ask the user if they want to swap via an intermediate token (e.g. via SUI).
5759
5759
  - **Always check \`recoverable: true\` first** \u2014 if a tool result has that flag, do the suggested next action without asking the user. Recovery is the agent's job.
5760
5760
 
5761
+ ## Unrecognized swap tokens \u2014 typo check first, then resolve obscure tokens via NAVI search
5762
+ - The supported-tokens hint in your system prompt is **NOT exhaustive**. Many real, tradeable Sui tokens (Spring SUI / sSUI, mSUI, hasui variants, ecosystem launches, etc.) are NOT in that hint but ARE swappable on Cetus once you resolve the full coin type via \`navi_navi_search_tokens\`.
5763
+ - **First turn \u2014 when the user names a token you don't immediately recognize**: it's reasonable to ask "did you mean \`<closest match>\`?" if the symbol looks like a likely typo of a common token (e.g. "SSUI" \u2192 could be SUI). This saves a wasted tool call when it's just a typo.
5764
+ - **Second turn \u2014 when the user clarifies they really mean the obscure token** (e.g. "no I mean Spring SUI", "yes I meant sSUI not SUI", "the spring sui token", they pass a full coin type \`0x...::spring_sui::SPRING_SUI\`, OR they simply repeat the same symbol): DO NOT ask again. Call \`navi_navi_search_tokens\` with the symbol or name \u2192 take the returned full coin type \u2192 retry \`swap_quote\` with that full type. The recovery path is your job, not the user's.
5765
+ - **Skip the typo-check entirely when the input is unambiguous** \u2014 if the user types a full coin type (\`0x...::module::TYPE\`) or names a token via clearly non-typo language ("the spring sui token", "swap my hasui"), call \`navi_navi_search_tokens\` immediately. No clarifying question.
5766
+
5761
5767
  ## Authentication (you CANNOT log users in or out)
5762
5768
  - You have NO tool to log users in, log users out, sign them in, or sign them out. You cannot end their session, switch accounts, or clear cookies.
5763
5769
  - If a user types "logout", "sign out", "log out", "exit", or any variant: tell them "Tap the avatar in the top-right and choose Sign Out" \u2014 do NOT narrate fake success. Saying "you're logged out" when they aren't is the worst possible behavior.
@@ -7808,6 +7814,7 @@ var QueryEngine = class {
7808
7814
  * the fresh tool results and narrates from them.
7809
7815
  */
7810
7816
  async *runPostWriteRefresh(action, response, signal) {
7817
+ const totalStart = Date.now();
7811
7818
  const isBundle = Array.isArray(action.steps) && action.steps.length > 0;
7812
7819
  const refreshSet = /* @__PURE__ */ new Set();
7813
7820
  if (isBundle) {
@@ -7849,10 +7856,17 @@ var QueryEngine = class {
7849
7856
  blockvisionApiKey: this.blockvisionApiKey,
7850
7857
  portfolioCache: this.portfolioCache
7851
7858
  };
7859
+ const cacheInvalidationStart = Date.now();
7852
7860
  if (this.walletAddress) {
7853
7861
  this.portfolioCache?.delete(this.walletAddress);
7854
7862
  await clearPortfolioCacheFor(this.walletAddress);
7855
7863
  }
7864
+ getTelemetrySink().histogram(
7865
+ "engine.pwr.cache_invalidation_ms",
7866
+ Date.now() - cacheInvalidationStart,
7867
+ { has_wallet: this.walletAddress ? "1" : "0" }
7868
+ );
7869
+ const sleepStart = Date.now();
7856
7870
  if (!signal.aborted) {
7857
7871
  await new Promise((resolve) => {
7858
7872
  const t = setTimeout(resolve, 1500);
@@ -7862,14 +7876,26 @@ var QueryEngine = class {
7862
7876
  }, { once: true });
7863
7877
  });
7864
7878
  }
7879
+ getTelemetrySink().histogram(
7880
+ "engine.pwr.sleep_ms",
7881
+ Date.now() - sleepStart,
7882
+ { aborted: signal.aborted ? "1" : "0" }
7883
+ );
7865
7884
  if (signal.aborted) return;
7885
+ const refreshStart = Date.now();
7866
7886
  const idStem = `pwr_${action.toolUseId.slice(-6)}`;
7867
7887
  const refreshes = await Promise.all(
7868
7888
  refreshTools.map(async (tool, idx) => {
7869
7889
  const id = `${idStem}_${idx}_${tool.name}`;
7890
+ const toolStart = Date.now();
7870
7891
  try {
7871
7892
  const parsed = tool.inputSchema.safeParse({});
7872
7893
  if (!parsed.success) {
7894
+ getTelemetrySink().histogram(
7895
+ "engine.pwr.tool_ms",
7896
+ Date.now() - toolStart,
7897
+ { tool: tool.name, outcome: "invalid_input" }
7898
+ );
7873
7899
  return {
7874
7900
  tool,
7875
7901
  id,
@@ -7882,6 +7908,11 @@ var QueryEngine = class {
7882
7908
  }
7883
7909
  const { context: toolCtx, readAttemptCount } = withRetryStats(context);
7884
7910
  const result = await tool.call(parsed.data, toolCtx);
7911
+ getTelemetrySink().histogram(
7912
+ "engine.pwr.tool_ms",
7913
+ Date.now() - toolStart,
7914
+ { tool: tool.name, outcome: "success" }
7915
+ );
7885
7916
  return {
7886
7917
  tool,
7887
7918
  id,
@@ -7890,6 +7921,11 @@ var QueryEngine = class {
7890
7921
  attemptCount: readAttemptCount()
7891
7922
  };
7892
7923
  } catch (err) {
7924
+ getTelemetrySink().histogram(
7925
+ "engine.pwr.tool_ms",
7926
+ Date.now() - toolStart,
7927
+ { tool: tool.name, outcome: "error" }
7928
+ );
7893
7929
  return {
7894
7930
  tool,
7895
7931
  id,
@@ -7902,6 +7938,14 @@ var QueryEngine = class {
7902
7938
  }
7903
7939
  })
7904
7940
  );
7941
+ getTelemetrySink().histogram(
7942
+ "engine.pwr.refresh_total_ms",
7943
+ Date.now() - refreshStart,
7944
+ {
7945
+ tool_count: String(refreshTools.length),
7946
+ is_bundle: isBundle ? "1" : "0"
7947
+ }
7948
+ );
7905
7949
  const refreshUses = refreshes.map((r) => ({
7906
7950
  type: "tool_use",
7907
7951
  id: r.id,
@@ -7933,6 +7977,14 @@ var QueryEngine = class {
7933
7977
  ...r.attemptCount !== void 0 ? { attemptCount: r.attemptCount } : {}
7934
7978
  };
7935
7979
  }
7980
+ getTelemetrySink().histogram(
7981
+ "engine.pwr.total_ms",
7982
+ Date.now() - totalStart,
7983
+ {
7984
+ tool_count: String(refreshTools.length),
7985
+ is_bundle: isBundle ? "1" : "0"
7986
+ }
7987
+ );
7936
7988
  }
7937
7989
  interrupt() {
7938
7990
  this.abortController?.abort();