@t2000/engine 1.12.0 → 1.13.1

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 CHANGED
@@ -934,6 +934,29 @@ interface PendingActionStep {
934
934
  description: string;
935
935
  /** Optional modifiable fields for THIS step (rare in v1; sourced from `tool-modifiable-fields.ts`). */
936
936
  modifiableFields?: PendingActionModifiableField[];
937
+ /**
938
+ * [SPEC 13 Phase 1] Index of an earlier step whose output coin handle
939
+ * is consumed as THIS step's input coin. When set, the host's
940
+ * `composeTx({ steps })` call must thread `priorOutputs[N]` into this
941
+ * step's appender as `inputCoin` (chain mode), skipping the wallet
942
+ * pre-fetch path. The producer at index `N` MUST be a tool that
943
+ * returns a coin handle (`withdraw`, `borrow`, `swap_execute`,
944
+ * `volo_stake`, `volo_unstake`); the consumer at this index MUST be
945
+ * a tool that accepts an input coin (`save_deposit`, `repay_debt`,
946
+ * `send_transfer`, `swap_execute`, `volo_stake`, `volo_unstake`).
947
+ *
948
+ * Populated by `composeBundleFromToolResults` for whitelisted
949
+ * producer→consumer pairs (see `compose-bundle.ts` `VALID_PAIRS`).
950
+ * Hosts that don't yet honour this field fall back to wallet-mode
951
+ * coin fetching at execute time — which is exactly the pre-Phase-1
952
+ * behaviour and remains correct for the 7 Phase 0 whitelisted pairs
953
+ * because every producer in those pairs leaves its output in the
954
+ * user's wallet via a terminal `tx.transferObjects([coin], sender)`.
955
+ *
956
+ * Pre-condition (validated by `composeTx` at execute time):
957
+ * `inputCoinFromStep < currentStepIndex` (forward-only references).
958
+ */
959
+ inputCoinFromStep?: number;
937
960
  }
938
961
  /**
939
962
  * Serializable description of a write tool that needs user approval.
package/dist/index.js CHANGED
@@ -5506,7 +5506,8 @@ function describeAction(tool, call) {
5506
5506
  const input = call.input;
5507
5507
  switch (tool.name) {
5508
5508
  case "save_deposit": {
5509
- return `Save ${input.amount} USDC into lending`;
5509
+ const sAsset = input.asset ?? "USDC";
5510
+ return `Save ${input.amount} ${sAsset} into lending`;
5510
5511
  }
5511
5512
  case "withdraw": {
5512
5513
  const wAsset = input.asset ?? "";
@@ -5514,10 +5515,14 @@ function describeAction(tool, call) {
5514
5515
  }
5515
5516
  case "send_transfer":
5516
5517
  return `Send $${input.amount} to ${input.to}`;
5517
- case "borrow":
5518
- return `Borrow $${input.amount} against collateral`;
5519
- case "repay_debt":
5520
- return `Repay $${input.amount} of outstanding debt`;
5518
+ case "borrow": {
5519
+ const bAsset = input.asset ?? "USDC";
5520
+ return `Borrow $${input.amount} ${bAsset} against collateral`;
5521
+ }
5522
+ case "repay_debt": {
5523
+ const rAsset = input.asset ?? "USDC";
5524
+ return `Repay $${input.amount} ${rAsset} of outstanding debt`;
5525
+ }
5521
5526
  case "claim_rewards":
5522
5527
  return "Claim all pending protocol rewards";
5523
5528
  case "pay_api": {
@@ -6746,6 +6751,36 @@ function checkValidPair(producer, consumer) {
6746
6751
  const pair = `${producer}->${consumer}`;
6747
6752
  return VALID_PAIRS.has(pair) ? { ok: true, pair } : { ok: false, pair };
6748
6753
  }
6754
+ function inferProducerOutputAsset(toolName, input) {
6755
+ if (typeof input !== "object" || input === null) return null;
6756
+ const i = input;
6757
+ if (toolName === "swap_execute") {
6758
+ return typeof i.to === "string" ? i.to.toLowerCase() : null;
6759
+ }
6760
+ if (toolName === "withdraw" || toolName === "borrow") {
6761
+ return typeof i.asset === "string" ? i.asset.toLowerCase() : "usdc";
6762
+ }
6763
+ return null;
6764
+ }
6765
+ function inferConsumerInputAsset(toolName, input) {
6766
+ if (typeof input !== "object" || input === null) return null;
6767
+ const i = input;
6768
+ if (toolName === "send_transfer" || toolName === "save_deposit" || toolName === "repay_debt") {
6769
+ return typeof i.asset === "string" ? i.asset.toLowerCase() : "usdc";
6770
+ }
6771
+ if (toolName === "swap_execute") {
6772
+ return typeof i.from === "string" ? i.from.toLowerCase() : null;
6773
+ }
6774
+ return null;
6775
+ }
6776
+ function shouldChainCoin(producer, consumer) {
6777
+ const pair = `${producer.name}->${consumer.name}`;
6778
+ if (!VALID_PAIRS.has(pair)) return false;
6779
+ const out = inferProducerOutputAsset(producer.name, producer.input);
6780
+ const inA = inferConsumerInputAsset(consumer.name, consumer.input);
6781
+ if (!out || !inA) return false;
6782
+ return out === inA;
6783
+ }
6749
6784
  function composeBundleFromToolResults(input) {
6750
6785
  if (input.pendingWrites.length < 2) {
6751
6786
  throw new Error(
@@ -6773,6 +6808,17 @@ function composeBundleFromToolResults(input) {
6773
6808
  ...modifiableFields?.length ? { modifiableFields } : {}
6774
6809
  };
6775
6810
  });
6811
+ for (let i = 1; i < input.pendingWrites.length; i++) {
6812
+ const producer = input.pendingWrites[i - 1];
6813
+ const consumer = input.pendingWrites[i];
6814
+ if (shouldChainCoin(producer, consumer)) {
6815
+ steps[i].inputCoinFromStep = i - 1;
6816
+ getTelemetrySink().counter("engine.bundle_chain_mode_set", {
6817
+ producer: producer.name,
6818
+ consumer: consumer.name
6819
+ });
6820
+ }
6821
+ }
6776
6822
  const regenerateToolUseIds = input.readResults.filter((r) => REGENERATABLE_READ_TOOLS.has(r.toolName)).map((r) => r.toolUseId);
6777
6823
  const canRegenerate = regenerateToolUseIds.length > 0;
6778
6824
  let quoteAge;