@t2000/engine 1.14.0 → 1.15.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 +25 -21
- package/dist/index.js +51 -77
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1715,7 +1715,7 @@ declare function bundleShortestTtl(toolUseIds: string[], toolNamesById: Record<s
|
|
|
1715
1715
|
declare const REGENERATABLE_READ_TOOLS: ReadonlySet<string>;
|
|
1716
1716
|
|
|
1717
1717
|
/**
|
|
1718
|
-
* [Phase 0 → Phase
|
|
1718
|
+
* [Phase 0 → Phase 3a / SPEC 13] Maximum number of writes per atomic bundle.
|
|
1719
1719
|
*
|
|
1720
1720
|
* **History.**
|
|
1721
1721
|
* - Pre-Phase-0: 5 (F14-fix-2, 2026-05-03 morning).
|
|
@@ -1730,31 +1730,35 @@ declare const REGENERATABLE_READ_TOOLS: ReadonlySet<string>;
|
|
|
1730
1730
|
* `composeTx` orchestration loop) but didn't widen the cap. The
|
|
1731
1731
|
* primitive is what makes Phase 2's raise to 3 possible — without it,
|
|
1732
1732
|
* every additional step is another wallet-fetch race.
|
|
1733
|
-
* - Phase 2 (1.14.0
|
|
1734
|
-
*
|
|
1735
|
-
*
|
|
1736
|
-
*
|
|
1737
|
-
*
|
|
1738
|
-
*
|
|
1739
|
-
*
|
|
1740
|
-
*
|
|
1741
|
-
*
|
|
1742
|
-
*
|
|
1743
|
-
*
|
|
1744
|
-
*
|
|
1745
|
-
*
|
|
1746
|
-
*
|
|
1747
|
-
*
|
|
1748
|
-
*
|
|
1749
|
-
*
|
|
1750
|
-
*
|
|
1751
|
-
*
|
|
1733
|
+
* - Phase 2 (1.14.0): cap raised to 3. Composition rule was strict-
|
|
1734
|
+
* adjacency: every (step[i], step[i+1]) pair must be in `VALID_PAIRS`.
|
|
1735
|
+
* Strict adjacency rejected DAG shapes (`swap → save → send` —
|
|
1736
|
+
* last pair `save→send` not in whitelist even though step 3 doesn't
|
|
1737
|
+
* chain from step 2; it pulls a fresh wallet coin).
|
|
1738
|
+
* - **Phase 3a (1.15.0, this version): cap raised to 4. Composition rule
|
|
1739
|
+
* relaxed to DAG-aware: only pairs that actually chain via
|
|
1740
|
+
* `inputCoinFromStep` need whitelist checking. Standalone steps
|
|
1741
|
+
* interleaved between chained steps run wallet-mode independently
|
|
1742
|
+
* inside the same atomic PTB.** This unlocks Demo 1 ("swap 10% to
|
|
1743
|
+
* SUI, save 50% as USDsui, send $100 to Mom" — 4-op DAG with one
|
|
1744
|
+
* chain at step 1→2, three standalone wallet-mode steps).
|
|
1745
|
+
*
|
|
1746
|
+
* **DAG-aware semantics.** Pre-3a: every adjacent pair gates the entire
|
|
1747
|
+
* bundle. Phase 3a+: each (i, i+1) pair contributes IF a chain is wired
|
|
1748
|
+
* (via `shouldChainCoin`). Non-chained pairs are independent — they
|
|
1749
|
+
* each pre-fetch their own coin from the wallet inside the PTB. Atomic
|
|
1750
|
+
* settlement at the PTB level holds either way.
|
|
1751
|
+
*
|
|
1752
|
+
* **Phase 3b (deferred):** `swap_execute → swap_execute` whitelist add
|
|
1753
|
+
* for explicit multi-hop swap chains (rare; flag-gated when shipped).
|
|
1754
|
+
* **Phase 5+:** cap > 4 once production telemetry confirms zero edge-
|
|
1755
|
+
* case revert rate at cap=4.
|
|
1752
1756
|
*
|
|
1753
1757
|
* Hosts importing this constant for system-prompt construction get the
|
|
1754
1758
|
* current cap automatically. Bumping the cap is a one-line change here
|
|
1755
1759
|
* that propagates to prompts via the import.
|
|
1756
1760
|
*/
|
|
1757
|
-
declare const MAX_BUNDLE_OPS =
|
|
1761
|
+
declare const MAX_BUNDLE_OPS = 4;
|
|
1758
1762
|
/**
|
|
1759
1763
|
* [Phase 0 / SPEC 13] Whitelisted (producer, consumer) pairs for atomic
|
|
1760
1764
|
* bundling. Every key has the shape `${producer}->${consumer}`. Bundles
|
package/dist/index.js
CHANGED
|
@@ -3647,26 +3647,35 @@ var swapExecuteTool = buildTool({
|
|
|
3647
3647
|
},
|
|
3648
3648
|
async call(input, context) {
|
|
3649
3649
|
const agent = requireAgent(context);
|
|
3650
|
-
const
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3650
|
+
const sink = getTelemetrySink();
|
|
3651
|
+
const start = Date.now();
|
|
3652
|
+
try {
|
|
3653
|
+
const result = await agent.swap({
|
|
3654
|
+
from: input.from,
|
|
3655
|
+
to: input.to,
|
|
3656
|
+
amount: input.amount,
|
|
3657
|
+
byAmountIn: input.byAmountIn,
|
|
3658
|
+
slippage: input.slippage
|
|
3659
|
+
});
|
|
3660
|
+
sink.histogram("cetus.swap_execute_total_ms", Date.now() - start);
|
|
3661
|
+
sink.counter("cetus.swap_execute_count", { outcome: "success" });
|
|
3662
|
+
return {
|
|
3663
|
+
data: {
|
|
3664
|
+
tx: result.tx,
|
|
3665
|
+
fromToken: result.fromToken,
|
|
3666
|
+
toToken: result.toToken,
|
|
3667
|
+
fromAmount: result.fromAmount,
|
|
3668
|
+
toAmount: result.toAmount,
|
|
3669
|
+
priceImpact: result.priceImpact,
|
|
3670
|
+
route: result.route,
|
|
3671
|
+
gasCost: result.gasCost
|
|
3672
|
+
},
|
|
3673
|
+
displayText: `Swapped ${result.fromAmount} ${result.fromToken} for ${result.toAmount.toFixed(4)} ${result.toToken} (tx: ${result.tx.slice(0, 8)}...)`
|
|
3674
|
+
};
|
|
3675
|
+
} catch (err) {
|
|
3676
|
+
sink.counter("cetus.swap_execute_count", { outcome: "error" });
|
|
3677
|
+
throw err;
|
|
3678
|
+
}
|
|
3670
3679
|
}
|
|
3671
3680
|
});
|
|
3672
3681
|
var swapQuoteTool = buildTool({
|
|
@@ -3691,17 +3700,26 @@ var swapQuoteTool = buildTool({
|
|
|
3691
3700
|
isReadOnly: true,
|
|
3692
3701
|
async call(input, context) {
|
|
3693
3702
|
const walletAddress = context.agent ? context.agent.address() : getWalletAddress(context);
|
|
3694
|
-
const
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3703
|
+
const sink = getTelemetrySink();
|
|
3704
|
+
const start = Date.now();
|
|
3705
|
+
try {
|
|
3706
|
+
const result = await getSwapQuote({
|
|
3707
|
+
walletAddress,
|
|
3708
|
+
from: input.from,
|
|
3709
|
+
to: input.to,
|
|
3710
|
+
amount: input.amount,
|
|
3711
|
+
byAmountIn: input.byAmountIn
|
|
3712
|
+
});
|
|
3713
|
+
sink.histogram("cetus.find_route_ms", Date.now() - start);
|
|
3714
|
+
sink.counter("cetus.find_route_count", { outcome: "success" });
|
|
3715
|
+
return {
|
|
3716
|
+
data: result,
|
|
3717
|
+
displayText: `${result.fromAmount} ${result.fromToken} \u2192 ${result.toAmount.toFixed(4)} ${result.toToken} (impact: ${(result.priceImpact * 100).toFixed(2)}%, via ${result.route})`
|
|
3718
|
+
};
|
|
3719
|
+
} catch (err) {
|
|
3720
|
+
sink.counter("cetus.find_route_count", { outcome: "error" });
|
|
3721
|
+
throw err;
|
|
3722
|
+
}
|
|
3705
3723
|
}
|
|
3706
3724
|
});
|
|
3707
3725
|
var voloStakeTool = buildTool({
|
|
@@ -6737,7 +6755,7 @@ var REGENERATABLE_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
|
6737
6755
|
]);
|
|
6738
6756
|
|
|
6739
6757
|
// src/compose-bundle.ts
|
|
6740
|
-
var MAX_BUNDLE_OPS =
|
|
6758
|
+
var MAX_BUNDLE_OPS = 4;
|
|
6741
6759
|
var VALID_PAIRS = /* @__PURE__ */ new Set([
|
|
6742
6760
|
"swap_execute->send_transfer",
|
|
6743
6761
|
"swap_execute->save_deposit",
|
|
@@ -7885,7 +7903,7 @@ ${recipeCtx}`;
|
|
|
7885
7903
|
}
|
|
7886
7904
|
if (guardPassedWrites.length > MAX_BUNDLE_OPS) {
|
|
7887
7905
|
const cappedError = {
|
|
7888
|
-
error: `Atomic bundles are capped at ${MAX_BUNDLE_OPS} ops
|
|
7906
|
+
error: `Atomic bundles are capped at ${MAX_BUNDLE_OPS} ops. You attempted ${guardPassedWrites.length}. Execute these as ${guardPassedWrites.length} sequential single-write transactions: tell the user "I'll do this in ${guardPassedWrites.length} steps", then emit only the FIRST write. After it lands and the user confirms each step, emit the next.`,
|
|
7889
7907
|
_gate: "max_bundle_ops"
|
|
7890
7908
|
};
|
|
7891
7909
|
for (const write of guardPassedWrites) {
|
|
@@ -7916,50 +7934,6 @@ ${recipeCtx}`;
|
|
|
7916
7934
|
const turnIndex = this.messages.filter((m) => m.role === "assistant").length;
|
|
7917
7935
|
this.turnPaused = true;
|
|
7918
7936
|
if (allBundleable) {
|
|
7919
|
-
if (guardPassedWrites.length >= 2) {
|
|
7920
|
-
let badPair = null;
|
|
7921
|
-
for (let i = 0; i < guardPassedWrites.length - 1; i++) {
|
|
7922
|
-
const producer = guardPassedWrites[i].call.name;
|
|
7923
|
-
const consumer = guardPassedWrites[i + 1].call.name;
|
|
7924
|
-
const check = checkValidPair(producer, consumer);
|
|
7925
|
-
if (!check.ok) {
|
|
7926
|
-
badPair = check;
|
|
7927
|
-
break;
|
|
7928
|
-
}
|
|
7929
|
-
}
|
|
7930
|
-
if (badPair !== null) {
|
|
7931
|
-
const N = guardPassedWrites.length;
|
|
7932
|
-
const stepsPhrase = N === 2 ? "two steps" : `${N} steps`;
|
|
7933
|
-
const pairError = {
|
|
7934
|
-
error: `Bundle pair '${badPair.pair}' is not in the chaining whitelist. Whitelisted pairs: ${[...VALID_PAIRS].join(", ")}. Run these ${N} writes sequentially: tell the user "I'll do this in ${stepsPhrase}", emit only the first write, then the next after it lands and confirms.`,
|
|
7935
|
-
_gate: "pair_not_whitelisted"
|
|
7936
|
-
};
|
|
7937
|
-
for (const write of guardPassedWrites) {
|
|
7938
|
-
yield {
|
|
7939
|
-
type: "tool_result",
|
|
7940
|
-
toolName: write.call.name,
|
|
7941
|
-
toolUseId: write.call.id,
|
|
7942
|
-
result: pairError,
|
|
7943
|
-
isError: true
|
|
7944
|
-
};
|
|
7945
|
-
toolResultBlocks.push({
|
|
7946
|
-
type: "tool_result",
|
|
7947
|
-
toolUseId: write.call.id,
|
|
7948
|
-
content: JSON.stringify(pairError),
|
|
7949
|
-
isError: true
|
|
7950
|
-
});
|
|
7951
|
-
}
|
|
7952
|
-
this.turnPaused = false;
|
|
7953
|
-
this.messages.push({ role: "assistant", content: acc.assistantBlocks });
|
|
7954
|
-
this.messages.push({ role: "user", content: toolResultBlocks });
|
|
7955
|
-
getTelemetrySink().counter("engine.turn_outcome", {
|
|
7956
|
-
entry: freshPrompt !== null ? "submit" : "resume",
|
|
7957
|
-
outcome: "pair_not_whitelisted_continue",
|
|
7958
|
-
pair: badPair.pair
|
|
7959
|
-
});
|
|
7960
|
-
continue;
|
|
7961
|
-
}
|
|
7962
|
-
}
|
|
7963
7937
|
const completedResults = toolResultBlocks.map((b) => ({
|
|
7964
7938
|
toolUseId: b.toolUseId,
|
|
7965
7939
|
content: b.content,
|