@t2000/engine 1.15.0 → 1.16.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 +31 -13
- package/dist/index.js +122 -65
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1032,26 +1032,42 @@ interface PendingAction {
|
|
|
1032
1032
|
steps?: PendingActionStep[];
|
|
1033
1033
|
/**
|
|
1034
1034
|
* [SPEC 7 v0.3 Quote-Refresh] Milliseconds since the upstream read tools
|
|
1035
|
-
* that fed this
|
|
1035
|
+
* that fed this action's composition completed. Engine stamps at emit
|
|
1036
1036
|
* time using `Date.now() - min(tool_result.timestamp)` across the listed
|
|
1037
1037
|
* `regenerateInput.toolUseIds`. Host renders as a "QUOTE Ns OLD" badge in
|
|
1038
|
-
* the PermissionCard header.
|
|
1038
|
+
* the PermissionCard header.
|
|
1039
|
+
*
|
|
1040
|
+
* **[SPEC 15 v0.7 follow-up — 2026-05-04]** Now also stamped on
|
|
1041
|
+
* single-write confirm-tier `pending_action`s when same-turn
|
|
1042
|
+
* regeneratable reads contributed (e.g. a confirm-tier
|
|
1043
|
+
* `swap_execute` whose Cetus quote is referenced via the prior
|
|
1044
|
+
* `swap_quote` read). Pre-v0.7 this was bundle-only.
|
|
1039
1045
|
*/
|
|
1040
1046
|
quoteAge?: number;
|
|
1041
1047
|
/**
|
|
1042
|
-
* [SPEC 7 v0.3 Quote-Refresh] True when the
|
|
1048
|
+
* [SPEC 7 v0.3 Quote-Refresh] True when the action was composed from
|
|
1043
1049
|
* re-runnable read tools (`swap_quote`, `rates_info`, `balance_check`,
|
|
1044
1050
|
* `portfolio_analysis`). False when amounts came from user-provided
|
|
1045
|
-
* inputs that don't depend on upstream quotes.
|
|
1046
|
-
*
|
|
1051
|
+
* inputs that don't depend on upstream quotes.
|
|
1052
|
+
*
|
|
1053
|
+
* **[SPEC 15 v0.7 follow-up — 2026-05-04]** Now populated for
|
|
1054
|
+
* single-write confirm-tier actions too — pre-v0.7 single-writes
|
|
1055
|
+
* always emitted `false` because the regenerate path was N≥2 only.
|
|
1056
|
+
* Closing that gap surfaced the Refresh-quote affordance for the
|
|
1057
|
+
* single-write confirm-tier scenario (e.g. $50 swap_execute).
|
|
1047
1058
|
*/
|
|
1048
1059
|
canRegenerate?: boolean;
|
|
1049
1060
|
/**
|
|
1050
1061
|
* [SPEC 7 v0.3 Quote-Refresh] Engine-internal payload listing which
|
|
1051
1062
|
* upstream read `tool_use` ids to re-fire when the user taps REGENERATE.
|
|
1052
1063
|
* Host echoes this back via `POST /api/engine/regenerate`; engine re-runs
|
|
1053
|
-
* each tool with the same input (no LLM call), rebuilds the
|
|
1054
|
-
* emits a fresh `pending_action` with
|
|
1064
|
+
* each tool with the same input (no LLM call), rebuilds the action, and
|
|
1065
|
+
* emits a fresh `pending_action` with a fresh `attemptId`.
|
|
1066
|
+
*
|
|
1067
|
+
* **[SPEC 15 v0.7 follow-up — 2026-05-04]** Populated for both
|
|
1068
|
+
* bundle (N≥2) and single-write (N=1) shapes; the engine's
|
|
1069
|
+
* `regenerateBundle()` rebuild branches on `action.steps?.length`
|
|
1070
|
+
* to pick the right composition path.
|
|
1055
1071
|
*/
|
|
1056
1072
|
regenerateInput?: {
|
|
1057
1073
|
toolUseIds: string[];
|
|
@@ -1906,15 +1922,17 @@ type RegenerateResult = RegenerateSuccess | RegenerateFailure;
|
|
|
1906
1922
|
* store after a successful regenerate.
|
|
1907
1923
|
*
|
|
1908
1924
|
* **Failure modes.**
|
|
1909
|
-
* - `pending_action_not_found` —
|
|
1910
|
-
*
|
|
1911
|
-
*
|
|
1925
|
+
* - `pending_action_not_found` — reserved for host-side mismatches
|
|
1926
|
+
* (session expired, attemptId mismatch). The engine itself never
|
|
1927
|
+
* returns this from `regenerateBundle`; the route surfaces it
|
|
1928
|
+
* pre-call. (Pre-v0.7 it also fired here for single-write
|
|
1929
|
+
* actions; lifted as part of single-write regenerate support.)
|
|
1912
1930
|
* - `cannot_regenerate` — the action's `canRegenerate` flag is
|
|
1913
1931
|
* false, OR no contributing read tool_use_ids could be located in
|
|
1914
1932
|
* session history.
|
|
1915
|
-
* - `engine_error` — a tool re-execution threw, OR
|
|
1916
|
-
*
|
|
1917
|
-
* original
|
|
1933
|
+
* - `engine_error` — a tool re-execution threw, OR action
|
|
1934
|
+
* rebuild rejected (defensive — should not happen if the
|
|
1935
|
+
* original action was valid).
|
|
1918
1936
|
*
|
|
1919
1937
|
* Errors in tool re-execution short-circuit the whole regenerate
|
|
1920
1938
|
* (bundle composition would inherit a broken read result). The host
|
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({
|
|
@@ -6781,6 +6799,18 @@ function shouldChainCoin(producer, consumer) {
|
|
|
6781
6799
|
if (!out || !inA) return false;
|
|
6782
6800
|
return out === inA;
|
|
6783
6801
|
}
|
|
6802
|
+
function computeRegenerateFields(readResults) {
|
|
6803
|
+
const regenerateToolUseIds = readResults.filter((r) => REGENERATABLE_READ_TOOLS.has(r.toolName)).map((r) => r.toolUseId);
|
|
6804
|
+
const canRegenerate = regenerateToolUseIds.length > 0;
|
|
6805
|
+
let quoteAge;
|
|
6806
|
+
if (canRegenerate) {
|
|
6807
|
+
const stalest = Math.min(
|
|
6808
|
+
...readResults.filter((r) => REGENERATABLE_READ_TOOLS.has(r.toolName)).map((r) => r.timestamp)
|
|
6809
|
+
);
|
|
6810
|
+
quoteAge = Math.max(0, Date.now() - stalest);
|
|
6811
|
+
}
|
|
6812
|
+
return { canRegenerate, regenerateToolUseIds, quoteAge };
|
|
6813
|
+
}
|
|
6784
6814
|
function composeBundleFromToolResults(input) {
|
|
6785
6815
|
if (input.pendingWrites.length < 2) {
|
|
6786
6816
|
throw new Error(
|
|
@@ -6819,15 +6849,7 @@ function composeBundleFromToolResults(input) {
|
|
|
6819
6849
|
});
|
|
6820
6850
|
}
|
|
6821
6851
|
}
|
|
6822
|
-
const regenerateToolUseIds = input.readResults
|
|
6823
|
-
const canRegenerate = regenerateToolUseIds.length > 0;
|
|
6824
|
-
let quoteAge;
|
|
6825
|
-
if (regenerateToolUseIds.length > 0) {
|
|
6826
|
-
const stalest = Math.min(
|
|
6827
|
-
...input.readResults.filter((r) => REGENERATABLE_READ_TOOLS.has(r.toolName)).map((r) => r.timestamp)
|
|
6828
|
-
);
|
|
6829
|
-
quoteAge = Math.max(0, Date.now() - stalest);
|
|
6830
|
-
}
|
|
6852
|
+
const { canRegenerate, regenerateToolUseIds, quoteAge } = computeRegenerateFields(input.readResults);
|
|
6831
6853
|
const allGuardInjections = [];
|
|
6832
6854
|
if (input.guardInjectionsByCallId) {
|
|
6833
6855
|
for (const call of input.pendingWrites) {
|
|
@@ -7960,6 +7982,7 @@ ${recipeCtx}`;
|
|
|
7960
7982
|
const writeGuardInjections = guardInjectionsByCallId[pendingWrite.call.id];
|
|
7961
7983
|
const modifiableFields = getModifiableFields(pendingWrite.call.name);
|
|
7962
7984
|
const attemptId = randomUUID();
|
|
7985
|
+
const singleWriteRegen = computeRegenerateFields(turnReadToolResults);
|
|
7963
7986
|
yield {
|
|
7964
7987
|
type: "pending_action",
|
|
7965
7988
|
action: {
|
|
@@ -7976,7 +7999,12 @@ ${recipeCtx}`;
|
|
|
7976
7999
|
...writeGuardInjections?.length ? { guardInjections: writeGuardInjections } : {},
|
|
7977
8000
|
...modifiableFields?.length ? { modifiableFields } : {},
|
|
7978
8001
|
turnIndex,
|
|
7979
|
-
attemptId
|
|
8002
|
+
attemptId,
|
|
8003
|
+
...singleWriteRegen.canRegenerate ? {
|
|
8004
|
+
canRegenerate: true,
|
|
8005
|
+
regenerateInput: { toolUseIds: singleWriteRegen.regenerateToolUseIds },
|
|
8006
|
+
...singleWriteRegen.quoteAge !== void 0 ? { quoteAge: singleWriteRegen.quoteAge } : {}
|
|
8007
|
+
} : {}
|
|
7980
8008
|
}
|
|
7981
8009
|
};
|
|
7982
8010
|
recordTurnOutcome("pending_action_single");
|
|
@@ -8204,13 +8232,6 @@ function harnessShapeForEffort(effort) {
|
|
|
8204
8232
|
}
|
|
8205
8233
|
}
|
|
8206
8234
|
async function regenerateBundle(engine, action) {
|
|
8207
|
-
if (!action.steps || action.steps.length < 2) {
|
|
8208
|
-
return {
|
|
8209
|
-
success: false,
|
|
8210
|
-
reason: "pending_action_not_found",
|
|
8211
|
-
message: "Action is not a multi-step bundle"
|
|
8212
|
-
};
|
|
8213
|
-
}
|
|
8214
8235
|
if (action.canRegenerate !== true) {
|
|
8215
8236
|
return {
|
|
8216
8237
|
success: false,
|
|
@@ -8324,11 +8345,6 @@ async function regenerateBundle(engine, action) {
|
|
|
8324
8345
|
{ role: "user", content: synthUserBlocks }
|
|
8325
8346
|
];
|
|
8326
8347
|
engine.loadMessages([...messages, ...synthMessages]);
|
|
8327
|
-
const pendingWrites = action.steps.map((step) => ({
|
|
8328
|
-
id: step.toolUseId,
|
|
8329
|
-
name: step.toolName,
|
|
8330
|
-
input: step.input
|
|
8331
|
-
}));
|
|
8332
8348
|
const readResults = newReads.map((r) => ({
|
|
8333
8349
|
toolUseId: r.toolUseId,
|
|
8334
8350
|
toolName: r.toolName,
|
|
@@ -8337,20 +8353,61 @@ async function regenerateBundle(engine, action) {
|
|
|
8337
8353
|
const assistantContent = action.assistantContent ?? [];
|
|
8338
8354
|
const completedResults = action.completedResults ?? [];
|
|
8339
8355
|
let newPendingAction;
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8356
|
+
if (action.steps && action.steps.length >= 2) {
|
|
8357
|
+
const pendingWrites = action.steps.map((step) => ({
|
|
8358
|
+
id: step.toolUseId,
|
|
8359
|
+
name: step.toolName,
|
|
8360
|
+
input: step.input
|
|
8361
|
+
}));
|
|
8362
|
+
try {
|
|
8363
|
+
newPendingAction = composeBundleFromToolResults({
|
|
8364
|
+
pendingWrites,
|
|
8365
|
+
tools,
|
|
8366
|
+
readResults,
|
|
8367
|
+
assistantContent,
|
|
8368
|
+
completedResults,
|
|
8369
|
+
turnIndex: action.turnIndex
|
|
8370
|
+
});
|
|
8371
|
+
} catch (err) {
|
|
8372
|
+
return {
|
|
8373
|
+
success: false,
|
|
8374
|
+
reason: "engine_error",
|
|
8375
|
+
message: err instanceof Error ? err.message : "Bundle rebuild failed"
|
|
8376
|
+
};
|
|
8377
|
+
}
|
|
8378
|
+
} else {
|
|
8379
|
+
const tool = findTool(tools, action.toolName);
|
|
8380
|
+
if (!tool) {
|
|
8381
|
+
return {
|
|
8382
|
+
success: false,
|
|
8383
|
+
reason: "engine_error",
|
|
8384
|
+
message: `Unknown tool '${action.toolName}' in single-write rebuild`
|
|
8385
|
+
};
|
|
8386
|
+
}
|
|
8387
|
+
const call = {
|
|
8388
|
+
id: action.toolUseId,
|
|
8389
|
+
name: action.toolName,
|
|
8390
|
+
input: action.input
|
|
8391
|
+
};
|
|
8392
|
+
const description = describeAction(tool, call);
|
|
8393
|
+
const modifiableFields = getModifiableFields(action.toolName);
|
|
8394
|
+
const { canRegenerate, regenerateToolUseIds, quoteAge } = computeRegenerateFields(readResults);
|
|
8395
|
+
newPendingAction = {
|
|
8396
|
+
toolName: action.toolName,
|
|
8397
|
+
toolUseId: action.toolUseId,
|
|
8398
|
+
input: action.input,
|
|
8399
|
+
description,
|
|
8345
8400
|
assistantContent,
|
|
8346
8401
|
completedResults,
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8402
|
+
...action.guardInjections?.length ? { guardInjections: action.guardInjections } : {},
|
|
8403
|
+
...modifiableFields?.length ? { modifiableFields } : {},
|
|
8404
|
+
turnIndex: action.turnIndex,
|
|
8405
|
+
attemptId: randomUUID(),
|
|
8406
|
+
...canRegenerate ? {
|
|
8407
|
+
canRegenerate: true,
|
|
8408
|
+
regenerateInput: { toolUseIds: regenerateToolUseIds },
|
|
8409
|
+
...quoteAge !== void 0 ? { quoteAge } : {}
|
|
8410
|
+
} : {}
|
|
8354
8411
|
};
|
|
8355
8412
|
}
|
|
8356
8413
|
return { success: true, newPendingAction, timelineEvents };
|