@aomi-labs/client 0.1.16 → 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 +27 -1
- package/dist/cli.js +190 -28
- 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/README.md +46 -0
- package/skills/aomi-app-builder/SKILL.md +178 -0
- package/skills/aomi-app-builder/agents/openai.yaml +4 -0
- package/skills/aomi-app-builder/references/aomi-sdk-patterns.md +191 -0
- package/skills/aomi-app-builder/references/spec-to-tools.md +149 -0
- package/skills/aomi-transact/SKILL.md +12 -6
package/README.md
CHANGED
|
@@ -126,6 +126,7 @@ npx @aomi-labs/client chat "swap 1 ETH" --verbose # stream tool calls + r
|
|
|
126
126
|
npx @aomi-labs/client app list # list available apps
|
|
127
127
|
npx @aomi-labs/client model list # list available models
|
|
128
128
|
npx @aomi-labs/client model set claude-sonnet-4 # switch the current session model
|
|
129
|
+
npx @aomi-labs/client session new # create a fresh active session
|
|
129
130
|
npx @aomi-labs/client secret list # list configured secret handles
|
|
130
131
|
npx @aomi-labs/client --secret ALCHEMY_API_KEY=... # ingest a secret for the active session
|
|
131
132
|
npx @aomi-labs/client log # show full conversation history
|
|
@@ -149,6 +150,31 @@ npx @aomi-labs/client chat "send 0 ETH to myself" \
|
|
|
149
150
|
The address is persisted in the state file, so subsequent commands in the same
|
|
150
151
|
session don't need it again.
|
|
151
152
|
|
|
153
|
+
### Chain selection
|
|
154
|
+
|
|
155
|
+
Use `--chain <id>` for the current command when the task is chain-specific:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
$ npx @aomi-labs/client chat "swap 1 POL for USDC on Polygon" --chain 137
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Use `AOMI_CHAIN_ID` when several consecutive commands should share the same
|
|
162
|
+
chain context.
|
|
163
|
+
|
|
164
|
+
### Fresh sessions
|
|
165
|
+
|
|
166
|
+
Use `--new-session` when you want a command to start a fresh backend/local
|
|
167
|
+
session instead of reusing the currently active one:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
$ npx @aomi-labs/client chat "show my balances" --new-session
|
|
171
|
+
$ npx @aomi-labs/client --secret ALCHEMY_API_KEY=... --new-session
|
|
172
|
+
$ npx @aomi-labs/client session new
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
This is useful when starting a new operator flow or a new external chat thread
|
|
176
|
+
and you do not want stale session state to bleed into the next run.
|
|
177
|
+
|
|
152
178
|
### Model selection
|
|
153
179
|
|
|
154
180
|
The CLI can discover and switch backend models for the active session:
|
|
@@ -281,7 +307,7 @@ All config can be passed as flags (which take priority over env vars):
|
|
|
281
307
|
|
|
282
308
|
| Flag | Env Variable | Default | Description |
|
|
283
309
|
| ----------------------- | ----------------- | ---------------------- | -------------------------------------------- |
|
|
284
|
-
| `--backend-url` | `
|
|
310
|
+
| `--backend-url` | `AOMI_BACKEND_URL` | `https://api.aomi.dev` | Backend URL |
|
|
285
311
|
| `--api-key` | `AOMI_API_KEY` | — | API key for non-default apps |
|
|
286
312
|
| `--app` | `AOMI_APP` | `default` | App |
|
|
287
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
|
}
|
|
@@ -139,6 +139,12 @@ function parseSecret(value, secrets) {
|
|
|
139
139
|
secrets[value.slice(0, eqIdx)] = value.slice(eqIdx + 1);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
+
function normalizePrivateKey(value) {
|
|
143
|
+
if (value === void 0) return void 0;
|
|
144
|
+
const trimmed = value.trim();
|
|
145
|
+
if (!trimmed) return void 0;
|
|
146
|
+
return trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
|
|
147
|
+
}
|
|
142
148
|
function parseArgs(argv) {
|
|
143
149
|
const raw = argv.slice(2);
|
|
144
150
|
const command = raw[0] && !raw[0].startsWith("-") ? raw[0] : void 0;
|
|
@@ -196,12 +202,15 @@ function getConfig(parsed) {
|
|
|
196
202
|
fatal("`--aa-provider` and `--aa-mode` cannot be used with `--eoa`.");
|
|
197
203
|
}
|
|
198
204
|
return {
|
|
199
|
-
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",
|
|
200
206
|
apiKey: (_e = parsed.flags["api-key"]) != null ? _e : process.env.AOMI_API_KEY,
|
|
201
207
|
app: (_g = (_f = parsed.flags["app"]) != null ? _f : process.env.AOMI_APP) != null ? _g : "default",
|
|
202
208
|
model: (_h = parsed.flags["model"]) != null ? _h : process.env.AOMI_MODEL,
|
|
209
|
+
freshSession: parsed.flags["new-session"] === "true",
|
|
203
210
|
publicKey: (_i = parsed.flags["public-key"]) != null ? _i : process.env.AOMI_PUBLIC_KEY,
|
|
204
|
-
privateKey: (
|
|
211
|
+
privateKey: normalizePrivateKey(
|
|
212
|
+
(_j = parsed.flags["private-key"]) != null ? _j : process.env.PRIVATE_KEY
|
|
213
|
+
),
|
|
205
214
|
chainRpcUrl: (_k = parsed.flags["rpc-url"]) != null ? _k : process.env.CHAIN_RPC_URL,
|
|
206
215
|
chain: parseChainId((_l = parsed.flags["chain"]) != null ? _l : process.env.AOMI_CHAIN_ID),
|
|
207
216
|
secrets: parsed.secrets,
|
|
@@ -1148,6 +1157,31 @@ var AomiClient = class {
|
|
|
1148
1157
|
}
|
|
1149
1158
|
return postState(this.baseUrl, "/api/control/model", payload, sessionId, apiKey);
|
|
1150
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
|
+
}
|
|
1151
1185
|
};
|
|
1152
1186
|
|
|
1153
1187
|
// src/types.ts
|
|
@@ -1792,20 +1826,29 @@ function buildCliUserState(publicKey, chainId) {
|
|
|
1792
1826
|
}
|
|
1793
1827
|
|
|
1794
1828
|
// src/cli/context.ts
|
|
1795
|
-
function
|
|
1829
|
+
function buildSessionState(runtime) {
|
|
1830
|
+
const { config } = runtime;
|
|
1831
|
+
return {
|
|
1832
|
+
sessionId: crypto.randomUUID(),
|
|
1833
|
+
baseUrl: config.baseUrl,
|
|
1834
|
+
app: config.app,
|
|
1835
|
+
model: config.model,
|
|
1836
|
+
apiKey: config.apiKey,
|
|
1837
|
+
publicKey: config.publicKey,
|
|
1838
|
+
chainId: config.chain,
|
|
1839
|
+
clientId: crypto.randomUUID()
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
function createFreshSessionState(runtime) {
|
|
1843
|
+
const state = buildSessionState(runtime);
|
|
1844
|
+
writeState(state);
|
|
1845
|
+
return state;
|
|
1846
|
+
}
|
|
1847
|
+
function getOrCreateSession(runtime, options = {}) {
|
|
1796
1848
|
const { config } = runtime;
|
|
1797
|
-
let state = readState();
|
|
1849
|
+
let state = options.fresh || config.freshSession ? createFreshSessionState(runtime) : readState();
|
|
1798
1850
|
if (!state) {
|
|
1799
|
-
state =
|
|
1800
|
-
sessionId: crypto.randomUUID(),
|
|
1801
|
-
baseUrl: config.baseUrl,
|
|
1802
|
-
app: config.app,
|
|
1803
|
-
apiKey: config.apiKey,
|
|
1804
|
-
publicKey: config.publicKey,
|
|
1805
|
-
chainId: config.chain,
|
|
1806
|
-
clientId: crypto.randomUUID()
|
|
1807
|
-
};
|
|
1808
|
-
writeState(state);
|
|
1851
|
+
state = createFreshSessionState(runtime);
|
|
1809
1852
|
} else {
|
|
1810
1853
|
let changed = false;
|
|
1811
1854
|
if (config.baseUrl !== state.baseUrl) {
|
|
@@ -1987,7 +2030,9 @@ async function chatCommand(runtime) {
|
|
|
1987
2030
|
fatal("Usage: aomi chat <message>");
|
|
1988
2031
|
}
|
|
1989
2032
|
const verbose = runtime.parsed.flags["verbose"] === "true" || runtime.parsed.flags["v"] === "true";
|
|
1990
|
-
const { session, state } = getOrCreateSession(runtime
|
|
2033
|
+
const { session, state } = getOrCreateSession(runtime, {
|
|
2034
|
+
fresh: runtime.config.freshSession
|
|
2035
|
+
});
|
|
1991
2036
|
try {
|
|
1992
2037
|
await ingestSecretsIfPresent(runtime, state, session.client);
|
|
1993
2038
|
await applyRequestedModelIfPresent(runtime, session, state);
|
|
@@ -2740,7 +2785,9 @@ async function ingestSecretsCommand(runtime) {
|
|
|
2740
2785
|
if (secretEntries.length === 0) {
|
|
2741
2786
|
fatal("Usage: aomi --secret NAME=value [NAME=value ...]");
|
|
2742
2787
|
}
|
|
2743
|
-
const { session, state } = getOrCreateSession(runtime
|
|
2788
|
+
const { session, state } = getOrCreateSession(runtime, {
|
|
2789
|
+
fresh: runtime.config.freshSession
|
|
2790
|
+
});
|
|
2744
2791
|
try {
|
|
2745
2792
|
const handles = await ingestSecretsIfPresent(
|
|
2746
2793
|
runtime,
|
|
@@ -2873,6 +2920,12 @@ async function sessionsCommand(_runtime) {
|
|
|
2873
2920
|
async function sessionCommand(runtime) {
|
|
2874
2921
|
const subcommand = runtime.parsed.positional[0];
|
|
2875
2922
|
const selector = runtime.parsed.positional[1];
|
|
2923
|
+
if (subcommand === "new") {
|
|
2924
|
+
const state = createFreshSessionState(runtime);
|
|
2925
|
+
console.log(`Active session set to ${state.sessionId} (new).`);
|
|
2926
|
+
printDataFileLocation();
|
|
2927
|
+
return;
|
|
2928
|
+
}
|
|
2876
2929
|
if (subcommand === "resume") {
|
|
2877
2930
|
if (!selector) {
|
|
2878
2931
|
fatal("Usage: aomi session resume <session-id|session-N|N>");
|
|
@@ -2908,10 +2961,82 @@ async function sessionCommand(runtime) {
|
|
|
2908
2961
|
return;
|
|
2909
2962
|
}
|
|
2910
2963
|
fatal(
|
|
2911
|
-
"Usage: aomi session list\n aomi session resume <session-id|session-N|N>\n aomi session delete <session-id|session-N|N>"
|
|
2964
|
+
"Usage: aomi session list\n aomi session new\n aomi session resume <session-id|session-N|N>\n aomi session delete <session-id|session-N|N>"
|
|
2912
2965
|
);
|
|
2913
2966
|
}
|
|
2914
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
|
+
|
|
2915
3040
|
// src/cli/commands/wallet.ts
|
|
2916
3041
|
import { createWalletClient, http } from "viem";
|
|
2917
3042
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
@@ -3463,7 +3588,7 @@ function txCommand() {
|
|
|
3463
3588
|
}
|
|
3464
3589
|
printDataFileLocation();
|
|
3465
3590
|
}
|
|
3466
|
-
function
|
|
3591
|
+
function requirePendingTx2(state, txId) {
|
|
3467
3592
|
var _a3;
|
|
3468
3593
|
const pendingTx = ((_a3 = state.pendingTxs) != null ? _a3 : []).find((tx) => tx.id === txId);
|
|
3469
3594
|
if (!pendingTx) {
|
|
@@ -3479,7 +3604,7 @@ function requirePendingTxs(state, txIds) {
|
|
|
3479
3604
|
if (uniqueIds.length !== txIds.length) {
|
|
3480
3605
|
fatal("Duplicate transaction IDs are not allowed in a single `aomi sign` call.");
|
|
3481
3606
|
}
|
|
3482
|
-
return uniqueIds.map((txId) =>
|
|
3607
|
+
return uniqueIds.map((txId) => requirePendingTx2(state, txId));
|
|
3483
3608
|
}
|
|
3484
3609
|
function rewriteSessionState(runtime, state) {
|
|
3485
3610
|
let changed = false;
|
|
@@ -3641,7 +3766,7 @@ async function executeTransactionWithFallback(params) {
|
|
|
3641
3766
|
}
|
|
3642
3767
|
}
|
|
3643
3768
|
async function signCommand(runtime) {
|
|
3644
|
-
var _a3, _b;
|
|
3769
|
+
var _a3, _b, _c, _d;
|
|
3645
3770
|
const txIds = runtime.parsed.positional;
|
|
3646
3771
|
if (txIds.length === 0) {
|
|
3647
3772
|
fatal(
|
|
@@ -3711,6 +3836,34 @@ async function signCommand(runtime) {
|
|
|
3711
3836
|
if (callList.length > 1 && rpcUrl && new Set(callList.map((call) => call.chainId)).size > 1) {
|
|
3712
3837
|
fatal("A single `--rpc-url` override cannot be used for a mixed-chain multi-sign request.");
|
|
3713
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
|
+
}
|
|
3714
3867
|
const decision = resolveCliExecutionDecision({
|
|
3715
3868
|
config: runtime.config,
|
|
3716
3869
|
chain,
|
|
@@ -3840,12 +3993,15 @@ Usage:
|
|
|
3840
3993
|
aomi model set <rig> Set the active model for the current session
|
|
3841
3994
|
aomi chain list List supported chains
|
|
3842
3995
|
aomi session list List local sessions with metadata
|
|
3996
|
+
aomi session new Start a fresh local/backend session and make it active
|
|
3843
3997
|
aomi session resume <id>
|
|
3844
3998
|
Resume a local session (session-id or session-N)
|
|
3845
3999
|
aomi session delete <id>
|
|
3846
4000
|
Delete a local session file (session-id or session-N)
|
|
3847
4001
|
aomi log Show full conversation history with tool results
|
|
3848
4002
|
aomi tx List pending and signed transactions
|
|
4003
|
+
aomi simulate <tx-id> [<tx-id> ...]
|
|
4004
|
+
Batch-simulate pending txs atomically (approve \u2192 swap)
|
|
3849
4005
|
aomi sign <tx-id> [<tx-id> ...] [--eoa | --aa] [--aa-provider <name>] [--aa-mode <mode>]
|
|
3850
4006
|
Sign and submit a pending transaction
|
|
3851
4007
|
aomi secret list List configured secrets for the active session
|
|
@@ -3860,6 +4016,8 @@ Options:
|
|
|
3860
4016
|
--api-key <key> API key for non-default apps
|
|
3861
4017
|
--app <name> App (default: "default")
|
|
3862
4018
|
--model <rig> Set the active model for this session
|
|
4019
|
+
--new-session Create a fresh active session for this command
|
|
4020
|
+
--chain <id> Active chain for chat/session context
|
|
3863
4021
|
--public-key <addr> Wallet address (so the agent knows your wallet)
|
|
3864
4022
|
--private-key <key> Hex private key for signing
|
|
3865
4023
|
--rpc-url <url> RPC URL for transaction submission
|
|
@@ -3883,10 +4041,11 @@ Default signing behavior:
|
|
|
3883
4041
|
fall back to EOA automatically if AA is unavailable
|
|
3884
4042
|
|
|
3885
4043
|
Environment (overridden by flags):
|
|
3886
|
-
|
|
4044
|
+
AOMI_BACKEND_URL Backend URL
|
|
3887
4045
|
AOMI_API_KEY API key
|
|
3888
4046
|
AOMI_APP App
|
|
3889
4047
|
AOMI_MODEL Model rig
|
|
4048
|
+
AOMI_CHAIN_ID Active chain for chat/session context
|
|
3890
4049
|
AOMI_PUBLIC_KEY Wallet address
|
|
3891
4050
|
AOMI_AA_PROVIDER AA provider: alchemy | pimlico
|
|
3892
4051
|
AOMI_AA_MODE AA mode: 4337 | 7702
|
|
@@ -3927,6 +4086,9 @@ async function main(runtime) {
|
|
|
3927
4086
|
case "sign":
|
|
3928
4087
|
await signCommand(runtime);
|
|
3929
4088
|
break;
|
|
4089
|
+
case "simulate":
|
|
4090
|
+
await simulateCommand(runtime);
|
|
4091
|
+
break;
|
|
3930
4092
|
case "status":
|
|
3931
4093
|
await statusCommand(runtime);
|
|
3932
4094
|
break;
|
|
@@ -3964,7 +4126,7 @@ function isPnpmExecWrapper() {
|
|
|
3964
4126
|
async function runCli(argv = process.argv) {
|
|
3965
4127
|
const runtime = createRuntime(argv);
|
|
3966
4128
|
const RED = "\x1B[31m";
|
|
3967
|
-
const
|
|
4129
|
+
const RESET2 = "\x1B[0m";
|
|
3968
4130
|
const strictExit = process.env.AOMI_CLI_STRICT_EXIT === "1";
|
|
3969
4131
|
try {
|
|
3970
4132
|
await main(runtime);
|
|
@@ -3977,7 +4139,7 @@ async function runCli(argv = process.argv) {
|
|
|
3977
4139
|
return;
|
|
3978
4140
|
}
|
|
3979
4141
|
const message = err instanceof Error ? err.message : String(err);
|
|
3980
|
-
console.error(`${RED}\u274C ${message}${
|
|
4142
|
+
console.error(`${RED}\u274C ${message}${RESET2}`);
|
|
3981
4143
|
process.exit(1);
|
|
3982
4144
|
}
|
|
3983
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
|