@t2000/engine 1.25.0 → 1.25.2

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
@@ -3771,6 +3771,34 @@ var swapQuoteTool = buildTool({
3771
3771
  required: ["from", "to", "amount"]
3772
3772
  },
3773
3773
  isReadOnly: true,
3774
+ // [SPEC 20.2 / D-1 (a) follow-on, 2026-05-10] Quote results MUST NOT be
3775
+ // cross-turn deduped by microcompact. Every call legitimately produces a
3776
+ // new result — pool reserves move per block, slippage windows update, the
3777
+ // best route can shift if liquidity moves, and the result's `discoveredAt`
3778
+ // timestamp is different per call by definition.
3779
+ //
3780
+ // Pre-fix: microcompact's default `cacheable: true` replaced the second
3781
+ // identical-input swap_quote tool_result with a `[Same result as call #N
3782
+ // — swap_quote with identical inputs. Result unchanged.]` placeholder.
3783
+ // The placeholder lied — the route and `discoveredAt` had legitimately
3784
+ // updated. Audric's bundle fast-path (which reads quote results from the
3785
+ // persisted ledger to thread `step.cetusRoute`) lost the fresh route and
3786
+ // had to fall back to whichever earlier same-input call WAS preserved
3787
+ // (the "first-seen" anchor, often >30s old → rejected by audric's
3788
+ // `isCetusRouteFresh` 30s gate → fast path missed → bundle paid full
3789
+ // ~400-500ms `findSwapRoute()` round-trip at confirm time).
3790
+ //
3791
+ // Production smoke trace (2026-05-10, session s_1778362657811_c0ed9009a5fb):
3792
+ // T0 swap_quote(USDC,SUI,0.5) → route X discovered
3793
+ // T0+34s swap_quote(USDC,SUI,0.5) [bundle] → route Y discovered (FRESH)
3794
+ // T0+50s "Confirm" → fast-path walks history → walker sees placeholder
3795
+ // on route Y, falls back
3796
+ // to route X (52s old)
3797
+ // T0+52s prepare → cetusRoute STALE → fallback → no perf win
3798
+ //
3799
+ // With `cacheable: false`: route Y stays as full content in the ledger,
3800
+ // walker finds it (~18s old), passes the freshness gate, fast path fires.
3801
+ cacheable: false,
3774
3802
  async call(input, context) {
3775
3803
  const walletAddress = context.agent ? context.agent.address() : getWalletAddress(context);
3776
3804
  const sink = getTelemetrySink();
@@ -7640,7 +7668,7 @@ var QueryEngine = class {
7640
7668
  })),
7641
7669
  ...writeResultBlocks
7642
7670
  ];
7643
- const canonicalRouteText = response.approved ? buildCanonicalRouteText(action) : null;
7671
+ const canonicalRouteText = response.approved ? buildCanonicalRouteText(action, response) : null;
7644
7672
  if (canonicalRouteText) {
7645
7673
  allResults.push({ type: "text", text: canonicalRouteText });
7646
7674
  }
@@ -9000,16 +9028,33 @@ ${recipeCtx}`;
9000
9028
  }
9001
9029
  }
9002
9030
  };
9003
- function buildCanonicalRouteText(action) {
9031
+ function buildCanonicalRouteText(action, response) {
9032
+ const failedToolUseIds = /* @__PURE__ */ new Set();
9033
+ if (Array.isArray(action.steps) && action.steps.length > 0) {
9034
+ const stepResultByToolUseId = new Map(
9035
+ (response.stepResults ?? []).map((sr) => [sr.toolUseId, sr])
9036
+ );
9037
+ for (const step of action.steps) {
9038
+ const sr = stepResultByToolUseId.get(step.toolUseId);
9039
+ if (!sr || sr.isError === true) {
9040
+ failedToolUseIds.add(step.toolUseId);
9041
+ }
9042
+ }
9043
+ } else if (isExecutionResultFailure(response.executionResult)) {
9044
+ failedToolUseIds.add(action.toolUseId);
9045
+ }
9004
9046
  const swaps = [];
9005
9047
  if (Array.isArray(action.steps) && action.steps.length > 0) {
9006
9048
  for (const step of action.steps) {
9007
9049
  if (step.toolName === "swap_execute" && step.cetusRoute) {
9050
+ if (failedToolUseIds.has(step.toolUseId)) continue;
9008
9051
  swaps.push({ input: step.input, cetusRoute: step.cetusRoute });
9009
9052
  }
9010
9053
  }
9011
9054
  } else if (action.toolName === "swap_execute" && action.cetusRoute) {
9012
- swaps.push({ input: action.input, cetusRoute: action.cetusRoute });
9055
+ if (!failedToolUseIds.has(action.toolUseId)) {
9056
+ swaps.push({ input: action.input, cetusRoute: action.cetusRoute });
9057
+ }
9013
9058
  }
9014
9059
  if (swaps.length === 0) return null;
9015
9060
  const blocks = swaps.map(({ input, cetusRoute }) => {
@@ -9029,6 +9074,24 @@ function buildCanonicalRouteText(action) {
9029
9074
  });
9030
9075
  return blocks.join("\n\n");
9031
9076
  }
9077
+ function isExecutionResultFailure(executionResult) {
9078
+ if (executionResult === null || executionResult === void 0) return false;
9079
+ if (typeof executionResult !== "object") return false;
9080
+ const er = executionResult;
9081
+ if (er.success === false) return true;
9082
+ if (typeof er.error === "string" && er.error.length > 0) return true;
9083
+ if (er._bundleReverted === true) return true;
9084
+ if (er._sessionExpired === true) return true;
9085
+ if (er._txReverted === true) return true;
9086
+ if (er.data && typeof er.data === "object") {
9087
+ const d = er.data;
9088
+ if (typeof d.error === "string" && d.error.length > 0) return true;
9089
+ if (d._bundleReverted === true) return true;
9090
+ if (d._sessionExpired === true) return true;
9091
+ if (d._txReverted === true) return true;
9092
+ }
9093
+ return false;
9094
+ }
9032
9095
  function isCorruptHistoryError(err) {
9033
9096
  const msg = err instanceof Error ? err.message : String(err);
9034
9097
  return msg.includes("tool_use") && msg.includes("tool_result") || msg.includes("roles must alternate") || msg.includes("400") && msg.includes("invalid_request_error");