@aomi-labs/client 0.1.17 → 0.1.18
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/README.md +1 -1
- package/dist/cli.js +142 -12
- package/dist/index.cjs +25 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/aomi-transact/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -307,7 +307,7 @@ All config can be passed as flags (which take priority over env vars):
|
|
|
307
307
|
|
|
308
308
|
| Flag | Env Variable | Default | Description |
|
|
309
309
|
| ----------------------- | ----------------- | ---------------------- | -------------------------------------------- |
|
|
310
|
-
| `--backend-url` | `
|
|
310
|
+
| `--backend-url` | `AOMI_BACKEND_URL` | `https://api.aomi.dev` | Backend URL |
|
|
311
311
|
| `--api-key` | `AOMI_API_KEY` | — | API key for non-default apps |
|
|
312
312
|
| `--app` | `AOMI_APP` | `default` | App |
|
|
313
313
|
| `--model` | `AOMI_MODEL` | — | Model rig to apply before chat |
|
package/dist/cli.js
CHANGED
|
@@ -22,7 +22,7 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
|
22
22
|
// package.json
|
|
23
23
|
var package_default = {
|
|
24
24
|
name: "@aomi-labs/client",
|
|
25
|
-
version: "0.1.
|
|
25
|
+
version: "0.1.18",
|
|
26
26
|
description: "Platform-agnostic TypeScript client for the Aomi backend API",
|
|
27
27
|
type: "module",
|
|
28
28
|
main: "./dist/index.cjs",
|
|
@@ -68,17 +68,17 @@ var CliExit = class extends Error {
|
|
|
68
68
|
};
|
|
69
69
|
function fatal(message) {
|
|
70
70
|
const RED = "\x1B[31m";
|
|
71
|
-
const
|
|
72
|
-
const
|
|
71
|
+
const DIM2 = "\x1B[2m";
|
|
72
|
+
const RESET2 = "\x1B[0m";
|
|
73
73
|
const lines = message.split("\n");
|
|
74
74
|
const [headline, ...details] = lines;
|
|
75
|
-
console.error(`${RED}\u274C ${headline}${
|
|
75
|
+
console.error(`${RED}\u274C ${headline}${RESET2}`);
|
|
76
76
|
for (const detail of details) {
|
|
77
77
|
if (!detail.trim()) {
|
|
78
78
|
console.error("");
|
|
79
79
|
continue;
|
|
80
80
|
}
|
|
81
|
-
console.error(`${
|
|
81
|
+
console.error(`${DIM2}${detail}${RESET2}`);
|
|
82
82
|
}
|
|
83
83
|
throw new CliExit(1);
|
|
84
84
|
}
|
|
@@ -202,7 +202,7 @@ function getConfig(parsed) {
|
|
|
202
202
|
fatal("`--aa-provider` and `--aa-mode` cannot be used with `--eoa`.");
|
|
203
203
|
}
|
|
204
204
|
return {
|
|
205
|
-
baseUrl: (_d = (_c = parsed.flags["backend-url"]) != null ? _c : process.env.
|
|
205
|
+
baseUrl: (_d = (_c = parsed.flags["backend-url"]) != null ? _c : process.env.AOMI_BACKEND_URL) != null ? _d : "https://api.aomi.dev",
|
|
206
206
|
apiKey: (_e = parsed.flags["api-key"]) != null ? _e : process.env.AOMI_API_KEY,
|
|
207
207
|
app: (_g = (_f = parsed.flags["app"]) != null ? _f : process.env.AOMI_APP) != null ? _g : "default",
|
|
208
208
|
model: (_h = parsed.flags["model"]) != null ? _h : process.env.AOMI_MODEL,
|
|
@@ -1157,6 +1157,31 @@ var AomiClient = class {
|
|
|
1157
1157
|
}
|
|
1158
1158
|
return postState(this.baseUrl, "/api/control/model", payload, sessionId, apiKey);
|
|
1159
1159
|
}
|
|
1160
|
+
// ===========================================================================
|
|
1161
|
+
// Batch Simulation
|
|
1162
|
+
// ===========================================================================
|
|
1163
|
+
/**
|
|
1164
|
+
* Simulate pending transactions as an atomic batch.
|
|
1165
|
+
* Each tx sees state changes from previous txs (e.g., approve → swap).
|
|
1166
|
+
*/
|
|
1167
|
+
async simulateBatch(sessionId, txIds) {
|
|
1168
|
+
const url = joinApiPath(this.baseUrl, "/api/simulate");
|
|
1169
|
+
const headers = new Headers(
|
|
1170
|
+
withSessionHeader(sessionId, { "Content-Type": "application/json" })
|
|
1171
|
+
);
|
|
1172
|
+
if (this.apiKey) {
|
|
1173
|
+
headers.set(API_KEY_HEADER, this.apiKey);
|
|
1174
|
+
}
|
|
1175
|
+
const response = await fetch(url, {
|
|
1176
|
+
method: "POST",
|
|
1177
|
+
headers,
|
|
1178
|
+
body: JSON.stringify({ tx_ids: txIds })
|
|
1179
|
+
});
|
|
1180
|
+
if (!response.ok) {
|
|
1181
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1182
|
+
}
|
|
1183
|
+
return await response.json();
|
|
1184
|
+
}
|
|
1160
1185
|
};
|
|
1161
1186
|
|
|
1162
1187
|
// src/types.ts
|
|
@@ -2940,6 +2965,78 @@ async function sessionCommand(runtime) {
|
|
|
2940
2965
|
);
|
|
2941
2966
|
}
|
|
2942
2967
|
|
|
2968
|
+
// src/cli/commands/simulate.ts
|
|
2969
|
+
function requirePendingTx(state, txId) {
|
|
2970
|
+
var _a3;
|
|
2971
|
+
const pendingTx = ((_a3 = state.pendingTxs) != null ? _a3 : []).find((tx) => tx.id === txId);
|
|
2972
|
+
if (!pendingTx) {
|
|
2973
|
+
fatal(
|
|
2974
|
+
`No pending transaction with id "${txId}".
|
|
2975
|
+
Run \`aomi tx\` to see available IDs.`
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2978
|
+
return pendingTx;
|
|
2979
|
+
}
|
|
2980
|
+
async function simulateCommand(runtime) {
|
|
2981
|
+
var _a3;
|
|
2982
|
+
const state = readState();
|
|
2983
|
+
if (!state) {
|
|
2984
|
+
fatal("No active session. Run `aomi chat` first.");
|
|
2985
|
+
}
|
|
2986
|
+
const txIds = runtime.parsed.positional;
|
|
2987
|
+
if (txIds.length === 0) {
|
|
2988
|
+
fatal("Usage: aomi simulate <tx-id> [<tx-id> ...]\nRun `aomi tx` to see available IDs.");
|
|
2989
|
+
}
|
|
2990
|
+
for (const txId of txIds) {
|
|
2991
|
+
requirePendingTx(state, txId);
|
|
2992
|
+
}
|
|
2993
|
+
console.log(
|
|
2994
|
+
`${DIM}Simulating ${txIds.length} transaction(s) as atomic batch...${RESET}`
|
|
2995
|
+
);
|
|
2996
|
+
const client = new AomiClient({
|
|
2997
|
+
baseUrl: state.baseUrl,
|
|
2998
|
+
apiKey: state.apiKey
|
|
2999
|
+
});
|
|
3000
|
+
const response = await client.simulateBatch(state.sessionId, txIds);
|
|
3001
|
+
const { result } = response;
|
|
3002
|
+
const modeLabel = result.stateful ? "stateful (Anvil snapshot)" : "stateless (independent eth_call)";
|
|
3003
|
+
console.log(`
|
|
3004
|
+
Batch simulation (${modeLabel}):`);
|
|
3005
|
+
console.log(`From: ${result.from} | Network: ${result.network}
|
|
3006
|
+
`);
|
|
3007
|
+
for (const step of result.steps) {
|
|
3008
|
+
const icon = step.success ? `${GREEN}\u2713${RESET}` : `\x1B[31m\u2717${RESET}`;
|
|
3009
|
+
const label = step.label || `Step ${step.step}`;
|
|
3010
|
+
const gasInfo = step.gas_used ? ` | gas: ${step.gas_used.toLocaleString()}` : "";
|
|
3011
|
+
console.log(` ${icon} ${step.step}. ${label}`);
|
|
3012
|
+
console.log(` ${DIM}to: ${step.tx.to} | value: ${step.tx.value_eth} ETH${gasInfo}${RESET}`);
|
|
3013
|
+
if (!step.success && step.revert_reason) {
|
|
3014
|
+
console.log(` \x1B[31mRevert: ${step.revert_reason}${RESET}`);
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
if (result.total_gas) {
|
|
3018
|
+
console.log(`
|
|
3019
|
+
${DIM}Total gas: ${result.total_gas.toLocaleString()}${RESET}`);
|
|
3020
|
+
}
|
|
3021
|
+
if (result.fee) {
|
|
3022
|
+
const feeEth = (Number(result.fee.amount_wei) / 1e18).toFixed(6);
|
|
3023
|
+
console.log(
|
|
3024
|
+
`Service fee: ${feeEth} ETH \u2192 ${result.fee.recipient}`
|
|
3025
|
+
);
|
|
3026
|
+
}
|
|
3027
|
+
console.log();
|
|
3028
|
+
if (result.batch_success) {
|
|
3029
|
+
console.log(
|
|
3030
|
+
`${GREEN}All steps passed.${RESET} Run \`aomi sign ${txIds.join(" ")}\` to execute.`
|
|
3031
|
+
);
|
|
3032
|
+
} else {
|
|
3033
|
+
const failed = result.steps.find((s) => !s.success);
|
|
3034
|
+
console.log(
|
|
3035
|
+
`\x1B[31mBatch failed at step ${(_a3 = failed == null ? void 0 : failed.step) != null ? _a3 : "?"}.${RESET} Fix the issue and re-queue, or run \`aomi sign\` on the successful prefix.`
|
|
3036
|
+
);
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
|
|
2943
3040
|
// src/cli/commands/wallet.ts
|
|
2944
3041
|
import { createWalletClient, http } from "viem";
|
|
2945
3042
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
@@ -3491,7 +3588,7 @@ function txCommand() {
|
|
|
3491
3588
|
}
|
|
3492
3589
|
printDataFileLocation();
|
|
3493
3590
|
}
|
|
3494
|
-
function
|
|
3591
|
+
function requirePendingTx2(state, txId) {
|
|
3495
3592
|
var _a3;
|
|
3496
3593
|
const pendingTx = ((_a3 = state.pendingTxs) != null ? _a3 : []).find((tx) => tx.id === txId);
|
|
3497
3594
|
if (!pendingTx) {
|
|
@@ -3507,7 +3604,7 @@ function requirePendingTxs(state, txIds) {
|
|
|
3507
3604
|
if (uniqueIds.length !== txIds.length) {
|
|
3508
3605
|
fatal("Duplicate transaction IDs are not allowed in a single `aomi sign` call.");
|
|
3509
3606
|
}
|
|
3510
|
-
return uniqueIds.map((txId) =>
|
|
3607
|
+
return uniqueIds.map((txId) => requirePendingTx2(state, txId));
|
|
3511
3608
|
}
|
|
3512
3609
|
function rewriteSessionState(runtime, state) {
|
|
3513
3610
|
let changed = false;
|
|
@@ -3669,7 +3766,7 @@ async function executeTransactionWithFallback(params) {
|
|
|
3669
3766
|
}
|
|
3670
3767
|
}
|
|
3671
3768
|
async function signCommand(runtime) {
|
|
3672
|
-
var _a3, _b;
|
|
3769
|
+
var _a3, _b, _c, _d;
|
|
3673
3770
|
const txIds = runtime.parsed.positional;
|
|
3674
3771
|
if (txIds.length === 0) {
|
|
3675
3772
|
fatal(
|
|
@@ -3739,6 +3836,34 @@ async function signCommand(runtime) {
|
|
|
3739
3836
|
if (callList.length > 1 && rpcUrl && new Set(callList.map((call) => call.chainId)).size > 1) {
|
|
3740
3837
|
fatal("A single `--rpc-url` override cannot be used for a mixed-chain multi-sign request.");
|
|
3741
3838
|
}
|
|
3839
|
+
try {
|
|
3840
|
+
const simResponse = await session.client.simulateBatch(
|
|
3841
|
+
state.sessionId,
|
|
3842
|
+
pendingTxs.map((tx) => tx.id)
|
|
3843
|
+
);
|
|
3844
|
+
const { result: sim } = simResponse;
|
|
3845
|
+
if (!sim.batch_success) {
|
|
3846
|
+
const failed = sim.steps.find((s) => !s.success);
|
|
3847
|
+
fatal(
|
|
3848
|
+
`Simulation failed at step ${(_c = failed == null ? void 0 : failed.step) != null ? _c : "?"}: ${(_d = failed == null ? void 0 : failed.revert_reason) != null ? _d : "unknown"}`
|
|
3849
|
+
);
|
|
3850
|
+
}
|
|
3851
|
+
if (sim.fee) {
|
|
3852
|
+
const feeEth = (Number(sim.fee.amount_wei) / 1e18).toFixed(6);
|
|
3853
|
+
console.log(
|
|
3854
|
+
`Fee: ${feeEth} ETH \u2192 ${sim.fee.recipient.slice(0, 10)}...`
|
|
3855
|
+
);
|
|
3856
|
+
callList.push({
|
|
3857
|
+
to: sim.fee.recipient,
|
|
3858
|
+
value: sim.fee.amount_wei,
|
|
3859
|
+
chainId: primaryChainId
|
|
3860
|
+
});
|
|
3861
|
+
}
|
|
3862
|
+
} catch (e) {
|
|
3863
|
+
console.log(
|
|
3864
|
+
`${DIM}Simulation unavailable, skipping fee injection.${RESET}`
|
|
3865
|
+
);
|
|
3866
|
+
}
|
|
3742
3867
|
const decision = resolveCliExecutionDecision({
|
|
3743
3868
|
config: runtime.config,
|
|
3744
3869
|
chain,
|
|
@@ -3875,6 +4000,8 @@ Usage:
|
|
|
3875
4000
|
Delete a local session file (session-id or session-N)
|
|
3876
4001
|
aomi log Show full conversation history with tool results
|
|
3877
4002
|
aomi tx List pending and signed transactions
|
|
4003
|
+
aomi simulate <tx-id> [<tx-id> ...]
|
|
4004
|
+
Batch-simulate pending txs atomically (approve \u2192 swap)
|
|
3878
4005
|
aomi sign <tx-id> [<tx-id> ...] [--eoa | --aa] [--aa-provider <name>] [--aa-mode <mode>]
|
|
3879
4006
|
Sign and submit a pending transaction
|
|
3880
4007
|
aomi secret list List configured secrets for the active session
|
|
@@ -3914,7 +4041,7 @@ Default signing behavior:
|
|
|
3914
4041
|
fall back to EOA automatically if AA is unavailable
|
|
3915
4042
|
|
|
3916
4043
|
Environment (overridden by flags):
|
|
3917
|
-
|
|
4044
|
+
AOMI_BACKEND_URL Backend URL
|
|
3918
4045
|
AOMI_API_KEY API key
|
|
3919
4046
|
AOMI_APP App
|
|
3920
4047
|
AOMI_MODEL Model rig
|
|
@@ -3959,6 +4086,9 @@ async function main(runtime) {
|
|
|
3959
4086
|
case "sign":
|
|
3960
4087
|
await signCommand(runtime);
|
|
3961
4088
|
break;
|
|
4089
|
+
case "simulate":
|
|
4090
|
+
await simulateCommand(runtime);
|
|
4091
|
+
break;
|
|
3962
4092
|
case "status":
|
|
3963
4093
|
await statusCommand(runtime);
|
|
3964
4094
|
break;
|
|
@@ -3996,7 +4126,7 @@ function isPnpmExecWrapper() {
|
|
|
3996
4126
|
async function runCli(argv = process.argv) {
|
|
3997
4127
|
const runtime = createRuntime(argv);
|
|
3998
4128
|
const RED = "\x1B[31m";
|
|
3999
|
-
const
|
|
4129
|
+
const RESET2 = "\x1B[0m";
|
|
4000
4130
|
const strictExit = process.env.AOMI_CLI_STRICT_EXIT === "1";
|
|
4001
4131
|
try {
|
|
4002
4132
|
await main(runtime);
|
|
@@ -4009,7 +4139,7 @@ async function runCli(argv = process.argv) {
|
|
|
4009
4139
|
return;
|
|
4010
4140
|
}
|
|
4011
4141
|
const message = err instanceof Error ? err.message : String(err);
|
|
4012
|
-
console.error(`${RED}\u274C ${message}${
|
|
4142
|
+
console.error(`${RED}\u274C ${message}${RESET2}`);
|
|
4013
4143
|
process.exit(1);
|
|
4014
4144
|
}
|
|
4015
4145
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -615,6 +615,31 @@ var AomiClient = class {
|
|
|
615
615
|
}
|
|
616
616
|
return postState(this.baseUrl, "/api/control/model", payload, sessionId, apiKey);
|
|
617
617
|
}
|
|
618
|
+
// ===========================================================================
|
|
619
|
+
// Batch Simulation
|
|
620
|
+
// ===========================================================================
|
|
621
|
+
/**
|
|
622
|
+
* Simulate pending transactions as an atomic batch.
|
|
623
|
+
* Each tx sees state changes from previous txs (e.g., approve → swap).
|
|
624
|
+
*/
|
|
625
|
+
async simulateBatch(sessionId, txIds) {
|
|
626
|
+
const url = joinApiPath(this.baseUrl, "/api/simulate");
|
|
627
|
+
const headers = new Headers(
|
|
628
|
+
withSessionHeader(sessionId, { "Content-Type": "application/json" })
|
|
629
|
+
);
|
|
630
|
+
if (this.apiKey) {
|
|
631
|
+
headers.set(API_KEY_HEADER, this.apiKey);
|
|
632
|
+
}
|
|
633
|
+
const response = await fetch(url, {
|
|
634
|
+
method: "POST",
|
|
635
|
+
headers,
|
|
636
|
+
body: JSON.stringify({ tx_ids: txIds })
|
|
637
|
+
});
|
|
638
|
+
if (!response.ok) {
|
|
639
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
640
|
+
}
|
|
641
|
+
return await response.json();
|
|
642
|
+
}
|
|
618
643
|
};
|
|
619
644
|
|
|
620
645
|
// src/types.ts
|