@aomi-labs/client 0.1.8 → 0.1.10

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/cli.js CHANGED
@@ -70,22 +70,24 @@ ${list}`);
70
70
  function resolveExecutionMode(flags) {
71
71
  const flagAA = flags["aa"] === "true";
72
72
  const flagEoa = flags["eoa"] === "true";
73
+ const hasAASelection = flags["aa-provider"] !== void 0 || flags["aa-mode"] !== void 0;
73
74
  if (flagAA && flagEoa) {
74
75
  fatal("Choose only one of `--aa` or `--eoa`.");
75
76
  }
76
77
  if (flagAA) return "aa";
77
78
  if (flagEoa) return "eoa";
78
- return "aa";
79
+ if (hasAASelection) return "aa";
80
+ return "auto";
79
81
  }
80
82
  function parseAAProvider(value) {
81
- if (value === void 0) return void 0;
83
+ if (value === void 0 || value.trim() === "") return void 0;
82
84
  if (value === "alchemy" || value === "pimlico") {
83
85
  return value;
84
86
  }
85
87
  fatal("Unsupported AA provider. Use `alchemy` or `pimlico`.");
86
88
  }
87
89
  function parseAAMode(value) {
88
- if (value === void 0) return void 0;
90
+ if (value === void 0 || value.trim() === "") return void 0;
89
91
  if (value === "4337" || value === "7702") {
90
92
  return value;
91
93
  }
@@ -1136,6 +1138,7 @@ function unwrapSystemEvent(event) {
1136
1138
  }
1137
1139
 
1138
1140
  // src/wallet-utils.ts
1141
+ import { getAddress } from "viem";
1139
1142
  function asRecord(value) {
1140
1143
  if (!value || typeof value !== "object" || Array.isArray(value))
1141
1144
  return void 0;
@@ -1159,12 +1162,25 @@ function parseChainId2(value) {
1159
1162
  const parsed = Number.parseInt(trimmed, 10);
1160
1163
  return Number.isFinite(parsed) ? parsed : void 0;
1161
1164
  }
1165
+ function normalizeAddress(value) {
1166
+ if (typeof value !== "string") return void 0;
1167
+ const trimmed = value.trim();
1168
+ if (!trimmed) return void 0;
1169
+ try {
1170
+ return getAddress(trimmed);
1171
+ } catch (e) {
1172
+ if (/^0x[0-9a-fA-F]{40}$/.test(trimmed)) {
1173
+ return getAddress(trimmed.toLowerCase());
1174
+ }
1175
+ return void 0;
1176
+ }
1177
+ }
1162
1178
  function normalizeTxPayload(payload) {
1163
1179
  var _a3, _b, _c;
1164
1180
  const root = asRecord(payload);
1165
1181
  const args = getToolArgs(payload);
1166
1182
  const ctx = asRecord(root == null ? void 0 : root.ctx);
1167
- const to = typeof args.to === "string" ? args.to : void 0;
1183
+ const to = normalizeAddress(args.to);
1168
1184
  if (!to) return null;
1169
1185
  const valueRaw = args.value;
1170
1186
  const value = typeof valueRaw === "string" ? valueRaw : typeof valueRaw === "number" && Number.isFinite(valueRaw) ? String(Math.trunc(valueRaw)) : void 0;
@@ -1570,6 +1586,22 @@ var ClientSession = class extends TypedEventEmitter {
1570
1586
  }
1571
1587
  };
1572
1588
 
1589
+ // src/cli/user-state.ts
1590
+ function buildCliUserState(publicKey, chainId) {
1591
+ if (publicKey === void 0 && chainId === void 0) {
1592
+ return void 0;
1593
+ }
1594
+ const userState = {};
1595
+ if (publicKey !== void 0) {
1596
+ userState.address = publicKey;
1597
+ userState.isConnected = true;
1598
+ }
1599
+ if (chainId !== void 0) {
1600
+ userState.chainId = chainId;
1601
+ }
1602
+ return userState;
1603
+ }
1604
+
1573
1605
  // src/cli/context.ts
1574
1606
  function getOrCreateSession(runtime) {
1575
1607
  const { config } = runtime;
@@ -1617,8 +1649,9 @@ function getOrCreateSession(runtime) {
1617
1649
  publicKey: state.publicKey
1618
1650
  }
1619
1651
  );
1620
- if (state.publicKey) {
1621
- session.resolveWallet(state.publicKey, state.chainId);
1652
+ const userState = buildCliUserState(state.publicKey, state.chainId);
1653
+ if (userState) {
1654
+ session.resolveUserState(userState);
1622
1655
  }
1623
1656
  return { session, state };
1624
1657
  }
@@ -1749,8 +1782,9 @@ async function chatCommand(runtime) {
1749
1782
  const { session, state } = getOrCreateSession(runtime);
1750
1783
  try {
1751
1784
  await applyRequestedModelIfPresent(runtime, session, state);
1752
- if (state.publicKey) {
1753
- session.resolveWallet(state.publicKey, state.chainId);
1785
+ const userState = buildCliUserState(state.publicKey, state.chainId);
1786
+ if (userState) {
1787
+ session.resolveUserState(userState);
1754
1788
  }
1755
1789
  const capturedRequests = [];
1756
1790
  let printedAgentCount = 0;
@@ -1882,225 +1916,255 @@ async function chatCommand(runtime) {
1882
1916
  }
1883
1917
  }
1884
1918
 
1885
- // src/cli/commands/control.ts
1886
- async function statusCommand(runtime) {
1887
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
1888
- if (!readState()) {
1889
- console.log("No active session");
1890
- printDataFileLocation();
1891
- return;
1919
+ // src/aa/types.ts
1920
+ function getAAChainConfig(config, calls, chainsById) {
1921
+ if (!config.enabled || calls.length === 0) {
1922
+ return null;
1892
1923
  }
1893
- const { session, state } = getOrCreateSession(runtime);
1894
- try {
1895
- const apiState = await session.client.fetchState(state.sessionId);
1896
- console.log(
1897
- JSON.stringify(
1898
- {
1899
- sessionId: state.sessionId,
1900
- baseUrl: state.baseUrl,
1901
- app: state.app,
1902
- model: (_a3 = state.model) != null ? _a3 : null,
1903
- isProcessing: (_b = apiState.is_processing) != null ? _b : false,
1904
- messageCount: (_d = (_c = apiState.messages) == null ? void 0 : _c.length) != null ? _d : 0,
1905
- title: (_e = apiState.title) != null ? _e : null,
1906
- pendingTxs: (_g = (_f = state.pendingTxs) == null ? void 0 : _f.length) != null ? _g : 0,
1907
- signedTxs: (_i = (_h = state.signedTxs) == null ? void 0 : _h.length) != null ? _i : 0
1908
- },
1909
- null,
1910
- 2
1911
- )
1912
- );
1913
- printDataFileLocation();
1914
- } finally {
1915
- session.close();
1924
+ const chainIds = Array.from(new Set(calls.map((call) => call.chainId)));
1925
+ if (chainIds.length !== 1) {
1926
+ return null;
1916
1927
  }
1917
- }
1918
- async function eventsCommand(runtime) {
1919
- if (!readState()) {
1920
- console.log("No active session");
1921
- return;
1928
+ const chainId = chainIds[0];
1929
+ if (!chainsById[chainId]) {
1930
+ return null;
1922
1931
  }
1923
- const { session, state } = getOrCreateSession(runtime);
1924
- try {
1925
- const events = await session.client.getSystemEvents(state.sessionId);
1926
- console.log(JSON.stringify(events, null, 2));
1927
- } finally {
1928
- session.close();
1932
+ const chainConfig = config.chains.find((item) => item.chainId === chainId);
1933
+ if (!(chainConfig == null ? void 0 : chainConfig.enabled)) {
1934
+ return null;
1929
1935
  }
1930
- }
1931
- async function modelsCommand(runtime) {
1932
- var _a3, _b;
1933
- const client = createControlClient(runtime);
1934
- const state = readState();
1935
- const sessionId = (_a3 = state == null ? void 0 : state.sessionId) != null ? _a3 : crypto.randomUUID();
1936
- const models = await client.getModels(sessionId, {
1937
- apiKey: (_b = runtime.config.apiKey) != null ? _b : state == null ? void 0 : state.apiKey
1938
- });
1939
- if (models.length === 0) {
1940
- console.log("No models available.");
1941
- return;
1936
+ if (calls.length > 1 && !chainConfig.allowBatching) {
1937
+ return null;
1942
1938
  }
1943
- for (const model of models) {
1944
- const marker = (state == null ? void 0 : state.model) === model ? " (current)" : "";
1945
- console.log(`${model}${marker}`);
1939
+ return chainConfig;
1940
+ }
1941
+ function buildAAExecutionPlan(config, chainConfig) {
1942
+ const mode = chainConfig.supportedModes.includes(chainConfig.defaultMode) ? chainConfig.defaultMode : chainConfig.supportedModes[0];
1943
+ if (!mode) {
1944
+ throw new Error(`No smart account mode configured for chain ${chainConfig.chainId}`);
1946
1945
  }
1946
+ return {
1947
+ provider: config.provider,
1948
+ chainId: chainConfig.chainId,
1949
+ mode,
1950
+ batchingEnabled: chainConfig.allowBatching,
1951
+ sponsorship: chainConfig.sponsorship,
1952
+ fallbackToEoa: config.fallbackToEoa
1953
+ };
1947
1954
  }
1948
- async function modelCommand(runtime) {
1949
- var _a3;
1950
- const subcommand = runtime.parsed.positional[0];
1951
- if (!subcommand || subcommand === "current") {
1952
- const state2 = readState();
1953
- if (!state2) {
1954
- console.log("No active session");
1955
- printDataFileLocation();
1956
- return;
1955
+ function mapCall(call) {
1956
+ return {
1957
+ to: call.to,
1958
+ value: BigInt(call.value),
1959
+ data: call.data ? call.data : void 0
1960
+ };
1961
+ }
1962
+ var DEFAULT_AA_CONFIG = {
1963
+ enabled: true,
1964
+ provider: "alchemy",
1965
+ fallbackToEoa: true,
1966
+ chains: [
1967
+ {
1968
+ chainId: 1,
1969
+ enabled: true,
1970
+ defaultMode: "7702",
1971
+ supportedModes: ["4337", "7702"],
1972
+ allowBatching: true,
1973
+ sponsorship: "optional"
1974
+ },
1975
+ {
1976
+ chainId: 137,
1977
+ enabled: true,
1978
+ defaultMode: "4337",
1979
+ supportedModes: ["4337", "7702"],
1980
+ allowBatching: true,
1981
+ sponsorship: "optional"
1982
+ },
1983
+ {
1984
+ chainId: 42161,
1985
+ enabled: true,
1986
+ defaultMode: "4337",
1987
+ supportedModes: ["4337", "7702"],
1988
+ allowBatching: true,
1989
+ sponsorship: "optional"
1990
+ },
1991
+ {
1992
+ chainId: 10,
1993
+ enabled: true,
1994
+ defaultMode: "4337",
1995
+ supportedModes: ["4337", "7702"],
1996
+ allowBatching: true,
1997
+ sponsorship: "optional"
1998
+ },
1999
+ {
2000
+ chainId: 8453,
2001
+ enabled: true,
2002
+ defaultMode: "4337",
2003
+ supportedModes: ["4337", "7702"],
2004
+ allowBatching: true,
2005
+ sponsorship: "optional"
1957
2006
  }
1958
- console.log((_a3 = state2.model) != null ? _a3 : "(default backend model)");
1959
- printDataFileLocation();
1960
- return;
1961
- }
1962
- if (subcommand !== "set") {
1963
- fatal("Usage: aomi model set <rig>\n aomi model current");
1964
- }
1965
- const model = runtime.parsed.positional.slice(1).join(" ").trim();
1966
- if (!model) {
1967
- fatal("Usage: aomi model set <rig>");
2007
+ ]
2008
+ };
2009
+ var DISABLED_PROVIDER_STATE = {
2010
+ plan: null,
2011
+ AA: void 0,
2012
+ isPending: false,
2013
+ error: null
2014
+ };
2015
+ async function executeWalletCalls(params) {
2016
+ const {
2017
+ callList,
2018
+ currentChainId,
2019
+ capabilities,
2020
+ localPrivateKey,
2021
+ providerState,
2022
+ sendCallsSyncAsync,
2023
+ sendTransactionAsync,
2024
+ switchChainAsync,
2025
+ chainsById,
2026
+ getPreferredRpcUrl: getPreferredRpcUrl2
2027
+ } = params;
2028
+ if (providerState.plan && providerState.AA) {
2029
+ return executeViaAA(callList, providerState);
1968
2030
  }
1969
- const { session, state } = getOrCreateSession(runtime);
1970
- try {
1971
- await applyModelSelection(session, state, model);
1972
- console.log(`Model set to ${model}`);
1973
- printDataFileLocation();
1974
- } finally {
1975
- session.close();
2031
+ if (providerState.plan && providerState.error && !providerState.plan.fallbackToEoa) {
2032
+ throw providerState.error;
1976
2033
  }
2034
+ return executeViaEoa({
2035
+ callList,
2036
+ currentChainId,
2037
+ capabilities,
2038
+ localPrivateKey,
2039
+ sendCallsSyncAsync,
2040
+ sendTransactionAsync,
2041
+ switchChainAsync,
2042
+ chainsById,
2043
+ getPreferredRpcUrl: getPreferredRpcUrl2
2044
+ });
1977
2045
  }
1978
-
1979
- // src/cli/tables.ts
1980
- var MAX_TABLE_VALUE_WIDTH = 72;
1981
- var MAX_TX_JSON_WIDTH = 96;
1982
- var MAX_TX_ROWS = 8;
1983
- function truncateCell(value, maxWidth) {
1984
- if (value.length <= maxWidth) return value;
1985
- return `${value.slice(0, maxWidth - 1)}\u2026`;
1986
- }
1987
- function padRight(value, width) {
1988
- return value.padEnd(width, " ");
1989
- }
1990
- function estimateTokenCount(messages) {
2046
+ async function executeViaAA(callList, providerState) {
1991
2047
  var _a3;
1992
- let totalChars = 0;
1993
- for (const message of messages) {
1994
- const content = formatLogContent(message.content);
1995
- if (content) {
1996
- totalChars += content.length + 1;
1997
- }
1998
- if ((_a3 = message.tool_result) == null ? void 0 : _a3[1]) {
1999
- totalChars += message.tool_result[1].length;
2000
- }
2048
+ const AA = providerState.AA;
2049
+ const plan = providerState.plan;
2050
+ if (!AA || !plan) {
2051
+ throw (_a3 = providerState.error) != null ? _a3 : new Error("smart_account_unavailable");
2001
2052
  }
2002
- return Math.round(totalChars / 4);
2003
- }
2004
- function toPendingTxMetadata(tx) {
2005
- var _a3, _b, _c, _d;
2006
- return {
2007
- id: tx.id,
2008
- kind: tx.kind,
2009
- to: (_a3 = tx.to) != null ? _a3 : null,
2010
- value: (_b = tx.value) != null ? _b : null,
2011
- chainId: (_c = tx.chainId) != null ? _c : null,
2012
- description: (_d = tx.description) != null ? _d : null,
2013
- timestamp: new Date(tx.timestamp).toISOString()
2014
- };
2015
- }
2016
- function toSignedTxMetadata(tx) {
2017
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
2053
+ const callsPayload = callList.map(mapCall);
2054
+ const receipt = callList.length > 1 ? await AA.sendBatchTransaction(callsPayload) : await AA.sendTransaction(callsPayload[0]);
2055
+ const txHash = receipt.transactionHash;
2056
+ const providerPrefix = AA.provider.toLowerCase();
2018
2057
  return {
2019
- id: tx.id,
2020
- kind: tx.kind,
2021
- txHash: (_a3 = tx.txHash) != null ? _a3 : null,
2022
- txHashes: (_b = tx.txHashes) != null ? _b : null,
2023
- executionKind: (_c = tx.executionKind) != null ? _c : null,
2024
- aaProvider: (_d = tx.aaProvider) != null ? _d : null,
2025
- aaMode: (_e = tx.aaMode) != null ? _e : null,
2026
- batched: (_f = tx.batched) != null ? _f : null,
2027
- sponsored: (_g = tx.sponsored) != null ? _g : null,
2028
- AAAddress: (_h = tx.AAAddress) != null ? _h : null,
2029
- delegationAddress: (_i = tx.delegationAddress) != null ? _i : null,
2030
- signature: (_j = tx.signature) != null ? _j : null,
2031
- from: (_k = tx.from) != null ? _k : null,
2032
- to: (_l = tx.to) != null ? _l : null,
2033
- value: (_m = tx.value) != null ? _m : null,
2034
- chainId: (_n = tx.chainId) != null ? _n : null,
2035
- description: (_o = tx.description) != null ? _o : null,
2036
- timestamp: new Date(tx.timestamp).toISOString()
2058
+ txHash,
2059
+ txHashes: [txHash],
2060
+ executionKind: `${providerPrefix}_${AA.mode}`,
2061
+ batched: callList.length > 1,
2062
+ sponsored: plan.sponsorship !== "disabled",
2063
+ AAAddress: AA.AAAddress,
2064
+ delegationAddress: AA.mode === "7702" ? AA.delegationAddress : void 0
2037
2065
  };
2038
2066
  }
2039
- function printKeyValueTable(rows, color = CYAN) {
2040
- const labels = rows.map(([label]) => label);
2041
- const values = rows.map(
2042
- ([, value]) => truncateCell(value, MAX_TABLE_VALUE_WIDTH)
2043
- );
2044
- const keyWidth = Math.max("field".length, ...labels.map((label) => label.length));
2045
- const valueWidth = Math.max("value".length, ...values.map((value) => value.length));
2046
- const border = `+${"-".repeat(keyWidth + 2)}+${"-".repeat(valueWidth + 2)}+`;
2047
- console.log(`${color}${border}${RESET}`);
2048
- console.log(
2049
- `${color}| ${padRight("field", keyWidth)} | ${padRight("value", valueWidth)} |${RESET}`
2050
- );
2051
- console.log(`${color}${border}${RESET}`);
2052
- for (let i = 0; i < rows.length; i++) {
2053
- console.log(
2054
- `${color}| ${padRight(labels[i], keyWidth)} | ${padRight(values[i], valueWidth)} |${RESET}`
2055
- );
2056
- console.log(`${color}${border}${RESET}`);
2067
+ async function executeViaEoa({
2068
+ callList,
2069
+ currentChainId,
2070
+ capabilities,
2071
+ localPrivateKey,
2072
+ sendCallsSyncAsync,
2073
+ sendTransactionAsync,
2074
+ switchChainAsync,
2075
+ chainsById,
2076
+ getPreferredRpcUrl: getPreferredRpcUrl2
2077
+ }) {
2078
+ var _a3, _b;
2079
+ const { createPublicClient, createWalletClient: createWalletClient2, http: http2 } = await import("viem");
2080
+ const { privateKeyToAccount: privateKeyToAccount3 } = await import("viem/accounts");
2081
+ const hashes = [];
2082
+ if (localPrivateKey) {
2083
+ for (const call of callList) {
2084
+ const chain = chainsById[call.chainId];
2085
+ if (!chain) {
2086
+ throw new Error(`Unsupported chain ${call.chainId}`);
2087
+ }
2088
+ const rpcUrl = getPreferredRpcUrl2(chain);
2089
+ if (!rpcUrl) {
2090
+ throw new Error(`No RPC for chain ${call.chainId}`);
2091
+ }
2092
+ const account = privateKeyToAccount3(localPrivateKey);
2093
+ const walletClient = createWalletClient2({
2094
+ account,
2095
+ chain,
2096
+ transport: http2(rpcUrl)
2097
+ });
2098
+ const hash = await walletClient.sendTransaction({
2099
+ account,
2100
+ to: call.to,
2101
+ value: BigInt(call.value),
2102
+ data: call.data ? call.data : void 0
2103
+ });
2104
+ const publicClient = createPublicClient({
2105
+ chain,
2106
+ transport: http2(rpcUrl)
2107
+ });
2108
+ await publicClient.waitForTransactionReceipt({ hash });
2109
+ hashes.push(hash);
2110
+ }
2111
+ return {
2112
+ txHash: hashes[hashes.length - 1],
2113
+ txHashes: hashes,
2114
+ executionKind: "eoa",
2115
+ batched: hashes.length > 1,
2116
+ sponsored: false
2117
+ };
2057
2118
  }
2058
- }
2059
- function printTransactionTable(pendingTxs, signedTxs, color = GREEN) {
2060
- const rows = [
2061
- ...pendingTxs.map((tx) => ({
2062
- status: "pending",
2063
- metadata: toPendingTxMetadata(tx)
2064
- })),
2065
- ...signedTxs.map((tx) => ({
2066
- status: "signed",
2067
- metadata: toSignedTxMetadata(tx)
2068
- }))
2069
- ];
2070
- if (rows.length === 0) {
2071
- console.log(`${YELLOW}No transactions in local CLI state.${RESET}`);
2072
- return;
2119
+ const chainIds = Array.from(new Set(callList.map((call) => call.chainId)));
2120
+ if (chainIds.length > 1) {
2121
+ throw new Error("mixed_chain_bundle_not_supported");
2073
2122
  }
2074
- const visibleRows = rows.slice(0, MAX_TX_ROWS);
2075
- const statusWidth = Math.max(
2076
- "status".length,
2077
- ...visibleRows.map((row) => row.status.length)
2078
- );
2079
- const jsonCells = visibleRows.map(
2080
- (row) => truncateCell(JSON.stringify(row.metadata), MAX_TX_JSON_WIDTH)
2081
- );
2082
- const jsonWidth = Math.max("metadata_json".length, ...jsonCells.map((v) => v.length));
2083
- const border = `+${"-".repeat(statusWidth + 2)}+${"-".repeat(jsonWidth + 2)}+`;
2084
- console.log(`${color}${border}${RESET}`);
2085
- console.log(
2086
- `${color}| ${padRight("status", statusWidth)} | ${padRight("metadata_json", jsonWidth)} |${RESET}`
2087
- );
2088
- console.log(`${color}${border}${RESET}`);
2089
- for (let i = 0; i < visibleRows.length; i++) {
2090
- console.log(
2091
- `${color}| ${padRight(visibleRows[i].status, statusWidth)} | ${padRight(jsonCells[i], jsonWidth)} |${RESET}`
2092
- );
2093
- console.log(`${color}${border}${RESET}`);
2123
+ const chainId = chainIds[0];
2124
+ if (currentChainId !== chainId) {
2125
+ await switchChainAsync({ chainId });
2094
2126
  }
2095
- if (rows.length > MAX_TX_ROWS) {
2096
- const omitted = rows.length - MAX_TX_ROWS;
2097
- console.log(`${DIM}${omitted} transaction rows omitted${RESET}`);
2127
+ const chainCaps = capabilities == null ? void 0 : capabilities[`eip155:${chainId}`];
2128
+ const atomicStatus = (_a3 = chainCaps == null ? void 0 : chainCaps.atomic) == null ? void 0 : _a3.status;
2129
+ const canUseSendCalls = atomicStatus === "supported" || atomicStatus === "ready";
2130
+ if (canUseSendCalls) {
2131
+ const batchResult = await sendCallsSyncAsync({
2132
+ calls: callList.map(mapCall),
2133
+ capabilities: {
2134
+ atomic: {
2135
+ required: true
2136
+ }
2137
+ }
2138
+ });
2139
+ const receipts = (_b = batchResult.receipts) != null ? _b : [];
2140
+ for (const receipt of receipts) {
2141
+ if (receipt.transactionHash) {
2142
+ hashes.push(receipt.transactionHash);
2143
+ }
2144
+ }
2145
+ } else {
2146
+ for (const call of callList) {
2147
+ const hash = await sendTransactionAsync({
2148
+ chainId: call.chainId,
2149
+ to: call.to,
2150
+ value: BigInt(call.value),
2151
+ data: call.data ? call.data : void 0
2152
+ });
2153
+ hashes.push(hash);
2154
+ }
2098
2155
  }
2156
+ return {
2157
+ txHash: hashes[hashes.length - 1],
2158
+ txHashes: hashes,
2159
+ executionKind: "eoa",
2160
+ batched: hashes.length > 1,
2161
+ sponsored: false
2162
+ };
2099
2163
  }
2100
2164
 
2101
- // src/cli/commands/history.ts
2102
- async function logCommand(runtime) {
2103
- var _a3, _b, _c, _d, _e;
2165
+ // src/cli/commands/control.ts
2166
+ async function statusCommand(runtime) {
2167
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2104
2168
  if (!readState()) {
2105
2169
  console.log("No active session");
2106
2170
  printDataFileLocation();
@@ -2109,438 +2173,475 @@ async function logCommand(runtime) {
2109
2173
  const { session, state } = getOrCreateSession(runtime);
2110
2174
  try {
2111
2175
  const apiState = await session.client.fetchState(state.sessionId);
2112
- const messages = (_a3 = apiState.messages) != null ? _a3 : [];
2113
- const pendingTxs = (_b = state.pendingTxs) != null ? _b : [];
2114
- const signedTxs = (_c = state.signedTxs) != null ? _c : [];
2115
- const toolCalls = messages.filter((msg) => Boolean(msg.tool_result)).length;
2116
- const tokenCountEstimate = estimateTokenCount(messages);
2117
- const topic = (_d = apiState.title) != null ? _d : "Untitled Session";
2118
- if (messages.length === 0) {
2119
- console.log("No messages in this session.");
2120
- printDataFileLocation();
2121
- return;
2122
- }
2123
- console.log(`------ Session id: ${state.sessionId} ------`);
2124
- printKeyValueTable([
2125
- ["topic", topic],
2126
- ["msg count", String(messages.length)],
2127
- ["token count", `${tokenCountEstimate} (estimated)`],
2128
- ["tool calls", String(toolCalls)],
2129
- [
2130
- "transactions",
2131
- `${pendingTxs.length + signedTxs.length} (${pendingTxs.length} pending, ${signedTxs.length} signed)`
2132
- ]
2133
- ]);
2134
- console.log("Transactions metadata (JSON):");
2135
- printTransactionTable(pendingTxs, signedTxs);
2136
- console.log("-------------------- Messages --------------------");
2137
- for (const msg of messages) {
2138
- const content = formatLogContent(msg.content);
2139
- let time = "";
2140
- if (msg.timestamp) {
2141
- const raw = msg.timestamp;
2142
- const numeric = /^\d+$/.test(raw) ? parseInt(raw, 10) : NaN;
2143
- const date = !Number.isNaN(numeric) ? new Date(numeric < 1e12 ? numeric * 1e3 : numeric) : new Date(raw);
2144
- time = Number.isNaN(date.getTime()) ? "" : `${DIM}${date.toLocaleTimeString()}${RESET} `;
2145
- }
2146
- const sender = (_e = msg.sender) != null ? _e : "unknown";
2147
- if (sender === "user") {
2148
- if (content) {
2149
- console.log(`${time}${CYAN}\u{1F464} You:${RESET} ${content}`);
2150
- }
2151
- } else if (sender === "agent" || sender === "assistant") {
2152
- if (msg.tool_result) {
2153
- const [toolName, result] = msg.tool_result;
2154
- console.log(
2155
- `${time}${GREEN}\u{1F527} [${toolName}]${RESET} ${formatToolResultPreview(result)}`
2156
- );
2157
- }
2158
- if (content) {
2159
- console.log(`${time}${CYAN}\u{1F916} Agent:${RESET} ${content}`);
2160
- }
2161
- } else if (sender === "system") {
2162
- if (content && !content.startsWith("Response of system endpoint:")) {
2163
- console.log(`${time}${YELLOW}\u2699\uFE0F System:${RESET} ${content}`);
2164
- }
2165
- } else {
2166
- if (content) {
2167
- console.log(`${time}${DIM}[${sender}]${RESET} ${content}`);
2168
- }
2169
- }
2170
- }
2171
- console.log(`
2172
- ${DIM}\u2014 ${messages.length} messages \u2014${RESET}`);
2176
+ console.log(
2177
+ JSON.stringify(
2178
+ {
2179
+ sessionId: state.sessionId,
2180
+ baseUrl: state.baseUrl,
2181
+ app: state.app,
2182
+ model: (_a3 = state.model) != null ? _a3 : null,
2183
+ chainId: (_b = state.chainId) != null ? _b : null,
2184
+ isProcessing: (_c = apiState.is_processing) != null ? _c : false,
2185
+ messageCount: (_e = (_d = apiState.messages) == null ? void 0 : _d.length) != null ? _e : 0,
2186
+ title: (_f = apiState.title) != null ? _f : null,
2187
+ pendingTxs: (_h = (_g = state.pendingTxs) == null ? void 0 : _g.length) != null ? _h : 0,
2188
+ signedTxs: (_j = (_i = state.signedTxs) == null ? void 0 : _i.length) != null ? _j : 0
2189
+ },
2190
+ null,
2191
+ 2
2192
+ )
2193
+ );
2173
2194
  printDataFileLocation();
2174
2195
  } finally {
2175
2196
  session.close();
2176
2197
  }
2177
2198
  }
2178
- function closeCommand(runtime) {
2179
- if (readState()) {
2180
- const { session } = getOrCreateSession(runtime);
2181
- session.close();
2182
- }
2183
- clearState();
2184
- console.log("Session closed");
2185
- }
2186
-
2187
- // src/cli/commands/sessions.ts
2188
- async function fetchRemoteSessionStats(record) {
2189
- var _a3, _b;
2190
- const client = new AomiClient({
2191
- baseUrl: record.state.baseUrl,
2192
- apiKey: record.state.apiKey
2193
- });
2199
+ async function eventsCommand(runtime) {
2200
+ if (!readState()) {
2201
+ console.log("No active session");
2202
+ return;
2203
+ }
2204
+ const { session, state } = getOrCreateSession(runtime);
2194
2205
  try {
2195
- const apiState = await client.fetchState(record.sessionId);
2196
- const messages = (_a3 = apiState.messages) != null ? _a3 : [];
2197
- return {
2198
- topic: (_b = apiState.title) != null ? _b : "Untitled Session",
2199
- messageCount: messages.length,
2200
- tokenCountEstimate: estimateTokenCount(messages),
2201
- toolCalls: messages.filter((msg) => Boolean(msg.tool_result)).length
2202
- };
2203
- } catch (e) {
2204
- return null;
2206
+ const events = await session.client.getSystemEvents(state.sessionId);
2207
+ console.log(JSON.stringify(events, null, 2));
2208
+ } finally {
2209
+ session.close();
2205
2210
  }
2206
2211
  }
2207
- function printSessionSummary(record, stats, isActive) {
2212
+ async function appsCommand(runtime) {
2208
2213
  var _a3, _b, _c;
2209
- const pendingTxs = (_a3 = record.state.pendingTxs) != null ? _a3 : [];
2210
- const signedTxs = (_b = record.state.signedTxs) != null ? _b : [];
2211
- const header = isActive ? `\u{1F9F5} Session id: ${record.sessionId} (session-${record.localId}, active)` : `\u{1F9F5} Session id: ${record.sessionId} (session-${record.localId})`;
2212
- console.log(`${YELLOW}------ ${header} ------${RESET}`);
2213
- printKeyValueTable([
2214
- ["\u{1F9E0} topic", (_c = stats == null ? void 0 : stats.topic) != null ? _c : "Unavailable (fetch failed)"],
2215
- ["\u{1F4AC} msg count", stats ? String(stats.messageCount) : "n/a"],
2216
- [
2217
- "\u{1F9EE} token count",
2218
- stats ? `${stats.tokenCountEstimate} (estimated)` : "n/a"
2219
- ],
2220
- ["\u{1F6E0} tool calls", stats ? String(stats.toolCalls) : "n/a"],
2221
- [
2222
- "\u{1F4B8} transactions",
2223
- `${pendingTxs.length + signedTxs.length} (${pendingTxs.length} pending, ${signedTxs.length} signed)`
2224
- ]
2225
- ]);
2226
- console.log();
2227
- console.log(`${YELLOW}\u{1F4BE} Transactions metadata (JSON):${RESET}`);
2228
- printTransactionTable(pendingTxs, signedTxs);
2214
+ const client = createControlClient(runtime);
2215
+ const state = readState();
2216
+ const sessionId = (_a3 = state == null ? void 0 : state.sessionId) != null ? _a3 : crypto.randomUUID();
2217
+ const apps = await client.getApps(sessionId, {
2218
+ publicKey: runtime.config.publicKey,
2219
+ apiKey: (_b = runtime.config.apiKey) != null ? _b : state == null ? void 0 : state.apiKey
2220
+ });
2221
+ if (apps.length === 0) {
2222
+ console.log("No apps available.");
2223
+ return;
2224
+ }
2225
+ const currentApp = (_c = state == null ? void 0 : state.app) != null ? _c : runtime.config.app;
2226
+ for (const app of apps) {
2227
+ const marker = currentApp === app ? " (current)" : "";
2228
+ console.log(`${app}${marker}`);
2229
+ }
2229
2230
  }
2230
- async function sessionsCommand(_runtime) {
2231
- var _a3;
2232
- const sessions = listStoredSessions().sort((a, b) => b.updatedAt - a.updatedAt);
2233
- if (sessions.length === 0) {
2234
- console.log("No local sessions.");
2235
- printDataFileLocation();
2231
+ async function modelsCommand(runtime) {
2232
+ var _a3, _b;
2233
+ const client = createControlClient(runtime);
2234
+ const state = readState();
2235
+ const sessionId = (_a3 = state == null ? void 0 : state.sessionId) != null ? _a3 : crypto.randomUUID();
2236
+ const models = await client.getModels(sessionId, {
2237
+ apiKey: (_b = runtime.config.apiKey) != null ? _b : state == null ? void 0 : state.apiKey
2238
+ });
2239
+ if (models.length === 0) {
2240
+ console.log("No models available.");
2236
2241
  return;
2237
2242
  }
2238
- const activeSessionId = (_a3 = readState()) == null ? void 0 : _a3.sessionId;
2239
- const statsResults = await Promise.all(
2240
- sessions.map((record) => fetchRemoteSessionStats(record))
2241
- );
2242
- for (let i = 0; i < sessions.length; i++) {
2243
- printSessionSummary(
2244
- sessions[i],
2245
- statsResults[i],
2246
- sessions[i].sessionId === activeSessionId
2247
- );
2248
- if (i < sessions.length - 1) {
2249
- console.log();
2250
- }
2243
+ for (const model of models) {
2244
+ const marker = (state == null ? void 0 : state.model) === model ? " (current)" : "";
2245
+ console.log(`${model}${marker}`);
2251
2246
  }
2252
- printDataFileLocation();
2253
2247
  }
2254
- function sessionCommand(runtime) {
2248
+ async function appCommand(runtime) {
2249
+ var _a3;
2255
2250
  const subcommand = runtime.parsed.positional[0];
2256
- const selector = runtime.parsed.positional[1];
2257
- if (subcommand === "resume") {
2258
- if (!selector) {
2259
- fatal("Usage: aomi session resume <session-id|session-N|N>");
2260
- }
2261
- const resumed = setActiveSession(selector);
2262
- if (!resumed) {
2263
- fatal(`No local session found for selector "${selector}".`);
2251
+ if (!subcommand || subcommand === "current") {
2252
+ const state = readState();
2253
+ if (!state) {
2254
+ console.log("No active session");
2255
+ printDataFileLocation();
2256
+ return;
2264
2257
  }
2265
- console.log(`Active session set to ${resumed.sessionId} (session-${resumed.localId}).`);
2258
+ console.log((_a3 = state.app) != null ? _a3 : "(default)");
2266
2259
  printDataFileLocation();
2267
2260
  return;
2268
2261
  }
2269
- if (subcommand === "delete") {
2270
- if (!selector) {
2271
- fatal("Usage: aomi session delete <session-id|session-N|N>");
2272
- }
2273
- const deleted = deleteStoredSession(selector);
2274
- if (!deleted) {
2275
- fatal(`No local session found for selector "${selector}".`);
2276
- }
2277
- console.log(`Deleted local session ${deleted.sessionId} (session-${deleted.localId}).`);
2278
- const active = readState();
2279
- if (active) {
2280
- console.log(`Active session: ${active.sessionId}`);
2281
- } else {
2262
+ if (subcommand === "list") {
2263
+ await appsCommand(runtime);
2264
+ return;
2265
+ }
2266
+ fatal("Usage: aomi app list\n aomi app current");
2267
+ }
2268
+ async function modelCommand(runtime) {
2269
+ var _a3;
2270
+ const subcommand = runtime.parsed.positional[0];
2271
+ if (!subcommand || subcommand === "current") {
2272
+ const state2 = readState();
2273
+ if (!state2) {
2282
2274
  console.log("No active session");
2275
+ printDataFileLocation();
2276
+ return;
2283
2277
  }
2278
+ console.log((_a3 = state2.model) != null ? _a3 : "(default backend model)");
2284
2279
  printDataFileLocation();
2285
2280
  return;
2286
2281
  }
2287
- fatal(
2288
- "Usage: aomi session resume <session-id|session-N|N>\n aomi session delete <session-id|session-N|N>"
2289
- );
2290
- }
2291
-
2292
- // src/cli/commands/wallet.ts
2293
- import { createWalletClient, http } from "viem";
2294
- import { createInterface } from "readline/promises";
2295
- import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
2296
- import * as viemChains from "viem/chains";
2297
-
2298
- // src/aa/types.ts
2299
- function getAAChainConfig(config, calls, chainsById) {
2300
- if (!config.enabled || calls.length === 0) {
2301
- return null;
2282
+ if (subcommand === "list") {
2283
+ await modelsCommand(runtime);
2284
+ return;
2302
2285
  }
2303
- const chainIds = Array.from(new Set(calls.map((call) => call.chainId)));
2304
- if (chainIds.length !== 1) {
2305
- return null;
2286
+ if (subcommand !== "set") {
2287
+ fatal("Usage: aomi model list\n aomi model set <rig>\n aomi model current");
2306
2288
  }
2307
- const chainId = chainIds[0];
2308
- if (!chainsById[chainId]) {
2309
- return null;
2289
+ const model = runtime.parsed.positional.slice(1).join(" ").trim();
2290
+ if (!model) {
2291
+ fatal("Usage: aomi model set <rig>");
2310
2292
  }
2311
- const chainConfig = config.chains.find((item) => item.chainId === chainId);
2312
- if (!(chainConfig == null ? void 0 : chainConfig.enabled)) {
2313
- return null;
2293
+ const { session, state } = getOrCreateSession(runtime);
2294
+ try {
2295
+ await applyModelSelection(session, state, model);
2296
+ console.log(`Model set to ${model}`);
2297
+ printDataFileLocation();
2298
+ } finally {
2299
+ session.close();
2314
2300
  }
2315
- if (calls.length > 1 && !chainConfig.allowBatching) {
2316
- return null;
2301
+ }
2302
+ function chainsCommand() {
2303
+ var _a3;
2304
+ const state = readState();
2305
+ const currentChainId = state == null ? void 0 : state.chainId;
2306
+ for (const id of SUPPORTED_CHAIN_IDS) {
2307
+ const name = (_a3 = CHAIN_NAMES[id]) != null ? _a3 : `Chain ${id}`;
2308
+ const aaChain = DEFAULT_AA_CONFIG.chains.find((c) => c.chainId === id);
2309
+ const aaInfo = (aaChain == null ? void 0 : aaChain.enabled) ? ` AA: ${aaChain.defaultMode} (${aaChain.supportedModes.join(", ")})` : "";
2310
+ const marker = currentChainId === id ? " (current)" : "";
2311
+ console.log(`${id} ${name}${aaInfo}${marker}`);
2317
2312
  }
2318
- return chainConfig;
2319
2313
  }
2320
- function buildAAExecutionPlan(config, chainConfig) {
2321
- const mode = chainConfig.supportedModes.includes(chainConfig.defaultMode) ? chainConfig.defaultMode : chainConfig.supportedModes[0];
2322
- if (!mode) {
2323
- throw new Error(`No smart account mode configured for chain ${chainConfig.chainId}`);
2314
+ function chainCommand(runtime) {
2315
+ const subcommand = runtime.parsed.positional[0];
2316
+ if (!subcommand || subcommand === "list") {
2317
+ chainsCommand();
2318
+ return;
2319
+ }
2320
+ fatal("Usage: aomi chain list");
2321
+ }
2322
+
2323
+ // src/cli/tables.ts
2324
+ var MAX_TABLE_VALUE_WIDTH = 72;
2325
+ var MAX_TX_JSON_WIDTH = 96;
2326
+ var MAX_TX_ROWS = 8;
2327
+ function truncateCell(value, maxWidth) {
2328
+ if (value.length <= maxWidth) return value;
2329
+ return `${value.slice(0, maxWidth - 1)}\u2026`;
2330
+ }
2331
+ function padRight(value, width) {
2332
+ return value.padEnd(width, " ");
2333
+ }
2334
+ function estimateTokenCount(messages) {
2335
+ var _a3;
2336
+ let totalChars = 0;
2337
+ for (const message of messages) {
2338
+ const content = formatLogContent(message.content);
2339
+ if (content) {
2340
+ totalChars += content.length + 1;
2341
+ }
2342
+ if ((_a3 = message.tool_result) == null ? void 0 : _a3[1]) {
2343
+ totalChars += message.tool_result[1].length;
2344
+ }
2324
2345
  }
2346
+ return Math.round(totalChars / 4);
2347
+ }
2348
+ function toPendingTxMetadata(tx) {
2349
+ var _a3, _b, _c, _d;
2325
2350
  return {
2326
- provider: config.provider,
2327
- chainId: chainConfig.chainId,
2328
- mode,
2329
- batchingEnabled: chainConfig.allowBatching,
2330
- sponsorship: chainConfig.sponsorship,
2331
- fallbackToEoa: config.fallbackToEoa
2351
+ id: tx.id,
2352
+ kind: tx.kind,
2353
+ to: (_a3 = tx.to) != null ? _a3 : null,
2354
+ value: (_b = tx.value) != null ? _b : null,
2355
+ chainId: (_c = tx.chainId) != null ? _c : null,
2356
+ description: (_d = tx.description) != null ? _d : null,
2357
+ timestamp: new Date(tx.timestamp).toISOString()
2332
2358
  };
2333
2359
  }
2334
- function mapCall(call) {
2360
+ function toSignedTxMetadata(tx) {
2361
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
2335
2362
  return {
2336
- to: call.to,
2337
- value: BigInt(call.value),
2338
- data: call.data ? call.data : void 0
2363
+ id: tx.id,
2364
+ kind: tx.kind,
2365
+ txHash: (_a3 = tx.txHash) != null ? _a3 : null,
2366
+ txHashes: (_b = tx.txHashes) != null ? _b : null,
2367
+ executionKind: (_c = tx.executionKind) != null ? _c : null,
2368
+ aaProvider: (_d = tx.aaProvider) != null ? _d : null,
2369
+ aaMode: (_e = tx.aaMode) != null ? _e : null,
2370
+ batched: (_f = tx.batched) != null ? _f : null,
2371
+ sponsored: (_g = tx.sponsored) != null ? _g : null,
2372
+ AAAddress: (_h = tx.AAAddress) != null ? _h : null,
2373
+ delegationAddress: (_i = tx.delegationAddress) != null ? _i : null,
2374
+ signature: (_j = tx.signature) != null ? _j : null,
2375
+ from: (_k = tx.from) != null ? _k : null,
2376
+ to: (_l = tx.to) != null ? _l : null,
2377
+ value: (_m = tx.value) != null ? _m : null,
2378
+ chainId: (_n = tx.chainId) != null ? _n : null,
2379
+ description: (_o = tx.description) != null ? _o : null,
2380
+ timestamp: new Date(tx.timestamp).toISOString()
2339
2381
  };
2340
2382
  }
2341
- var DEFAULT_AA_CONFIG = {
2342
- enabled: true,
2343
- provider: "alchemy",
2344
- fallbackToEoa: true,
2345
- chains: [
2346
- {
2347
- chainId: 1,
2348
- enabled: true,
2349
- defaultMode: "7702",
2350
- supportedModes: ["4337", "7702"],
2351
- allowBatching: true,
2352
- sponsorship: "optional"
2353
- },
2354
- {
2355
- chainId: 137,
2356
- enabled: true,
2357
- defaultMode: "4337",
2358
- supportedModes: ["4337", "7702"],
2359
- allowBatching: true,
2360
- sponsorship: "optional"
2361
- },
2362
- {
2363
- chainId: 42161,
2364
- enabled: true,
2365
- defaultMode: "4337",
2366
- supportedModes: ["4337", "7702"],
2367
- allowBatching: true,
2368
- sponsorship: "optional"
2369
- },
2370
- {
2371
- chainId: 10,
2372
- enabled: true,
2373
- defaultMode: "4337",
2374
- supportedModes: ["4337", "7702"],
2375
- allowBatching: true,
2376
- sponsorship: "optional"
2377
- },
2378
- {
2379
- chainId: 8453,
2380
- enabled: true,
2381
- defaultMode: "4337",
2382
- supportedModes: ["4337", "7702"],
2383
- allowBatching: true,
2384
- sponsorship: "optional"
2385
- }
2386
- ]
2387
- };
2388
- var DISABLED_PROVIDER_STATE = {
2389
- plan: null,
2390
- AA: void 0,
2391
- isPending: false,
2392
- error: null
2393
- };
2394
- async function executeWalletCalls(params) {
2395
- const {
2396
- callList,
2397
- currentChainId,
2398
- capabilities,
2399
- localPrivateKey,
2400
- providerState,
2401
- sendCallsSyncAsync,
2402
- sendTransactionAsync,
2403
- switchChainAsync,
2404
- chainsById,
2405
- getPreferredRpcUrl: getPreferredRpcUrl2
2406
- } = params;
2407
- if (providerState.plan && providerState.AA) {
2408
- return executeViaAA(callList, providerState);
2409
- }
2410
- if (providerState.plan && providerState.error && !providerState.plan.fallbackToEoa) {
2411
- throw providerState.error;
2383
+ function printKeyValueTable(rows, color = CYAN) {
2384
+ const labels = rows.map(([label]) => label);
2385
+ const values = rows.map(
2386
+ ([, value]) => truncateCell(value, MAX_TABLE_VALUE_WIDTH)
2387
+ );
2388
+ const keyWidth = Math.max("field".length, ...labels.map((label) => label.length));
2389
+ const valueWidth = Math.max("value".length, ...values.map((value) => value.length));
2390
+ const border = `+${"-".repeat(keyWidth + 2)}+${"-".repeat(valueWidth + 2)}+`;
2391
+ console.log(`${color}${border}${RESET}`);
2392
+ console.log(
2393
+ `${color}| ${padRight("field", keyWidth)} | ${padRight("value", valueWidth)} |${RESET}`
2394
+ );
2395
+ console.log(`${color}${border}${RESET}`);
2396
+ for (let i = 0; i < rows.length; i++) {
2397
+ console.log(
2398
+ `${color}| ${padRight(labels[i], keyWidth)} | ${padRight(values[i], valueWidth)} |${RESET}`
2399
+ );
2400
+ console.log(`${color}${border}${RESET}`);
2412
2401
  }
2413
- return executeViaEoa({
2414
- callList,
2415
- currentChainId,
2416
- capabilities,
2417
- localPrivateKey,
2418
- sendCallsSyncAsync,
2419
- sendTransactionAsync,
2420
- switchChainAsync,
2421
- chainsById,
2422
- getPreferredRpcUrl: getPreferredRpcUrl2
2423
- });
2424
2402
  }
2425
- async function executeViaAA(callList, providerState) {
2426
- var _a3;
2427
- const AA = providerState.AA;
2428
- const plan = providerState.plan;
2429
- if (!AA || !plan) {
2430
- throw (_a3 = providerState.error) != null ? _a3 : new Error("smart_account_unavailable");
2403
+ function printTransactionTable(pendingTxs, signedTxs, color = GREEN) {
2404
+ const rows = [
2405
+ ...pendingTxs.map((tx) => ({
2406
+ status: "pending",
2407
+ metadata: toPendingTxMetadata(tx)
2408
+ })),
2409
+ ...signedTxs.map((tx) => ({
2410
+ status: "signed",
2411
+ metadata: toSignedTxMetadata(tx)
2412
+ }))
2413
+ ];
2414
+ if (rows.length === 0) {
2415
+ console.log(`${YELLOW}No transactions in local CLI state.${RESET}`);
2416
+ return;
2417
+ }
2418
+ const visibleRows = rows.slice(0, MAX_TX_ROWS);
2419
+ const statusWidth = Math.max(
2420
+ "status".length,
2421
+ ...visibleRows.map((row) => row.status.length)
2422
+ );
2423
+ const jsonCells = visibleRows.map(
2424
+ (row) => truncateCell(JSON.stringify(row.metadata), MAX_TX_JSON_WIDTH)
2425
+ );
2426
+ const jsonWidth = Math.max("metadata_json".length, ...jsonCells.map((v) => v.length));
2427
+ const border = `+${"-".repeat(statusWidth + 2)}+${"-".repeat(jsonWidth + 2)}+`;
2428
+ console.log(`${color}${border}${RESET}`);
2429
+ console.log(
2430
+ `${color}| ${padRight("status", statusWidth)} | ${padRight("metadata_json", jsonWidth)} |${RESET}`
2431
+ );
2432
+ console.log(`${color}${border}${RESET}`);
2433
+ for (let i = 0; i < visibleRows.length; i++) {
2434
+ console.log(
2435
+ `${color}| ${padRight(visibleRows[i].status, statusWidth)} | ${padRight(jsonCells[i], jsonWidth)} |${RESET}`
2436
+ );
2437
+ console.log(`${color}${border}${RESET}`);
2438
+ }
2439
+ if (rows.length > MAX_TX_ROWS) {
2440
+ const omitted = rows.length - MAX_TX_ROWS;
2441
+ console.log(`${DIM}${omitted} transaction rows omitted${RESET}`);
2431
2442
  }
2432
- const callsPayload = callList.map(mapCall);
2433
- const receipt = callList.length > 1 ? await AA.sendBatchTransaction(callsPayload) : await AA.sendTransaction(callsPayload[0]);
2434
- const txHash = receipt.transactionHash;
2435
- const providerPrefix = AA.provider.toLowerCase();
2436
- return {
2437
- txHash,
2438
- txHashes: [txHash],
2439
- executionKind: `${providerPrefix}_${AA.mode}`,
2440
- batched: callList.length > 1,
2441
- sponsored: plan.sponsorship !== "disabled",
2442
- AAAddress: AA.AAAddress,
2443
- delegationAddress: AA.mode === "7702" ? AA.delegationAddress : void 0
2444
- };
2445
2443
  }
2446
- async function executeViaEoa({
2447
- callList,
2448
- currentChainId,
2449
- capabilities,
2450
- localPrivateKey,
2451
- sendCallsSyncAsync,
2452
- sendTransactionAsync,
2453
- switchChainAsync,
2454
- chainsById,
2455
- getPreferredRpcUrl: getPreferredRpcUrl2
2456
- }) {
2457
- var _a3, _b;
2458
- const { createPublicClient, createWalletClient: createWalletClient2, http: http2 } = await import("viem");
2459
- const { privateKeyToAccount: privateKeyToAccount3 } = await import("viem/accounts");
2460
- const hashes = [];
2461
- if (localPrivateKey) {
2462
- for (const call of callList) {
2463
- const chain = chainsById[call.chainId];
2464
- if (!chain) {
2465
- throw new Error(`Unsupported chain ${call.chainId}`);
2444
+
2445
+ // src/cli/commands/history.ts
2446
+ async function logCommand(runtime) {
2447
+ var _a3, _b, _c, _d, _e;
2448
+ if (!readState()) {
2449
+ console.log("No active session");
2450
+ printDataFileLocation();
2451
+ return;
2452
+ }
2453
+ const { session, state } = getOrCreateSession(runtime);
2454
+ try {
2455
+ const apiState = await session.client.fetchState(state.sessionId);
2456
+ const messages = (_a3 = apiState.messages) != null ? _a3 : [];
2457
+ const pendingTxs = (_b = state.pendingTxs) != null ? _b : [];
2458
+ const signedTxs = (_c = state.signedTxs) != null ? _c : [];
2459
+ const toolCalls = messages.filter((msg) => Boolean(msg.tool_result)).length;
2460
+ const tokenCountEstimate = estimateTokenCount(messages);
2461
+ const topic = (_d = apiState.title) != null ? _d : "Untitled Session";
2462
+ if (messages.length === 0) {
2463
+ console.log("No messages in this session.");
2464
+ printDataFileLocation();
2465
+ return;
2466
+ }
2467
+ console.log(`------ Session id: ${state.sessionId} ------`);
2468
+ printKeyValueTable([
2469
+ ["topic", topic],
2470
+ ["msg count", String(messages.length)],
2471
+ ["token count", `${tokenCountEstimate} (estimated)`],
2472
+ ["tool calls", String(toolCalls)],
2473
+ [
2474
+ "transactions",
2475
+ `${pendingTxs.length + signedTxs.length} (${pendingTxs.length} pending, ${signedTxs.length} signed)`
2476
+ ]
2477
+ ]);
2478
+ console.log("Transactions metadata (JSON):");
2479
+ printTransactionTable(pendingTxs, signedTxs);
2480
+ console.log("-------------------- Messages --------------------");
2481
+ for (const msg of messages) {
2482
+ const content = formatLogContent(msg.content);
2483
+ let time = "";
2484
+ if (msg.timestamp) {
2485
+ const raw = msg.timestamp;
2486
+ const numeric = /^\d+$/.test(raw) ? parseInt(raw, 10) : NaN;
2487
+ const date = !Number.isNaN(numeric) ? new Date(numeric < 1e12 ? numeric * 1e3 : numeric) : new Date(raw);
2488
+ time = Number.isNaN(date.getTime()) ? "" : `${DIM}${date.toLocaleTimeString()}${RESET} `;
2466
2489
  }
2467
- const rpcUrl = getPreferredRpcUrl2(chain);
2468
- if (!rpcUrl) {
2469
- throw new Error(`No RPC for chain ${call.chainId}`);
2490
+ const sender = (_e = msg.sender) != null ? _e : "unknown";
2491
+ if (sender === "user") {
2492
+ if (content) {
2493
+ console.log(`${time}${CYAN}\u{1F464} You:${RESET} ${content}`);
2494
+ }
2495
+ } else if (sender === "agent" || sender === "assistant") {
2496
+ if (msg.tool_result) {
2497
+ const [toolName, result] = msg.tool_result;
2498
+ console.log(
2499
+ `${time}${GREEN}\u{1F527} [${toolName}]${RESET} ${formatToolResultPreview(result)}`
2500
+ );
2501
+ }
2502
+ if (content) {
2503
+ console.log(`${time}${CYAN}\u{1F916} Agent:${RESET} ${content}`);
2504
+ }
2505
+ } else if (sender === "system") {
2506
+ if (content && !content.startsWith("Response of system endpoint:")) {
2507
+ console.log(`${time}${YELLOW}\u2699\uFE0F System:${RESET} ${content}`);
2508
+ }
2509
+ } else {
2510
+ if (content) {
2511
+ console.log(`${time}${DIM}[${sender}]${RESET} ${content}`);
2512
+ }
2470
2513
  }
2471
- const account = privateKeyToAccount3(localPrivateKey);
2472
- const walletClient = createWalletClient2({
2473
- account,
2474
- chain,
2475
- transport: http2(rpcUrl)
2476
- });
2477
- const hash = await walletClient.sendTransaction({
2478
- account,
2479
- to: call.to,
2480
- value: BigInt(call.value),
2481
- data: call.data ? call.data : void 0
2482
- });
2483
- const publicClient = createPublicClient({
2484
- chain,
2485
- transport: http2(rpcUrl)
2486
- });
2487
- await publicClient.waitForTransactionReceipt({ hash });
2488
- hashes.push(hash);
2489
2514
  }
2515
+ console.log(`
2516
+ ${DIM}\u2014 ${messages.length} messages \u2014${RESET}`);
2517
+ printDataFileLocation();
2518
+ } finally {
2519
+ session.close();
2520
+ }
2521
+ }
2522
+ function closeCommand(runtime) {
2523
+ if (readState()) {
2524
+ const { session } = getOrCreateSession(runtime);
2525
+ session.close();
2526
+ }
2527
+ clearState();
2528
+ console.log("Session closed");
2529
+ }
2530
+
2531
+ // src/cli/commands/sessions.ts
2532
+ async function fetchRemoteSessionStats(record) {
2533
+ var _a3, _b;
2534
+ const client = new AomiClient({
2535
+ baseUrl: record.state.baseUrl,
2536
+ apiKey: record.state.apiKey
2537
+ });
2538
+ try {
2539
+ const apiState = await client.fetchState(record.sessionId);
2540
+ const messages = (_a3 = apiState.messages) != null ? _a3 : [];
2490
2541
  return {
2491
- txHash: hashes[hashes.length - 1],
2492
- txHashes: hashes,
2493
- executionKind: "eoa",
2494
- batched: hashes.length > 1,
2495
- sponsored: false
2542
+ topic: (_b = apiState.title) != null ? _b : "Untitled Session",
2543
+ messageCount: messages.length,
2544
+ tokenCountEstimate: estimateTokenCount(messages),
2545
+ toolCalls: messages.filter((msg) => Boolean(msg.tool_result)).length
2496
2546
  };
2547
+ } catch (e) {
2548
+ return null;
2497
2549
  }
2498
- const chainIds = Array.from(new Set(callList.map((call) => call.chainId)));
2499
- if (chainIds.length > 1) {
2500
- throw new Error("mixed_chain_bundle_not_supported");
2550
+ }
2551
+ function printSessionSummary(record, stats, isActive) {
2552
+ var _a3, _b, _c;
2553
+ const pendingTxs = (_a3 = record.state.pendingTxs) != null ? _a3 : [];
2554
+ const signedTxs = (_b = record.state.signedTxs) != null ? _b : [];
2555
+ const header = isActive ? `\u{1F9F5} Session id: ${record.sessionId} (session-${record.localId}, active)` : `\u{1F9F5} Session id: ${record.sessionId} (session-${record.localId})`;
2556
+ console.log(`${YELLOW}------ ${header} ------${RESET}`);
2557
+ printKeyValueTable([
2558
+ ["\u{1F9E0} topic", (_c = stats == null ? void 0 : stats.topic) != null ? _c : "Unavailable (fetch failed)"],
2559
+ ["\u{1F4AC} msg count", stats ? String(stats.messageCount) : "n/a"],
2560
+ [
2561
+ "\u{1F9EE} token count",
2562
+ stats ? `${stats.tokenCountEstimate} (estimated)` : "n/a"
2563
+ ],
2564
+ ["\u{1F6E0} tool calls", stats ? String(stats.toolCalls) : "n/a"],
2565
+ [
2566
+ "\u{1F4B8} transactions",
2567
+ `${pendingTxs.length + signedTxs.length} (${pendingTxs.length} pending, ${signedTxs.length} signed)`
2568
+ ]
2569
+ ]);
2570
+ console.log();
2571
+ console.log(`${YELLOW}\u{1F4BE} Transactions metadata (JSON):${RESET}`);
2572
+ printTransactionTable(pendingTxs, signedTxs);
2573
+ }
2574
+ async function sessionsCommand(_runtime) {
2575
+ var _a3;
2576
+ const sessions = listStoredSessions().sort((a, b) => b.updatedAt - a.updatedAt);
2577
+ if (sessions.length === 0) {
2578
+ console.log("No local sessions.");
2579
+ printDataFileLocation();
2580
+ return;
2501
2581
  }
2502
- const chainId = chainIds[0];
2503
- if (currentChainId !== chainId) {
2504
- await switchChainAsync({ chainId });
2582
+ const activeSessionId = (_a3 = readState()) == null ? void 0 : _a3.sessionId;
2583
+ const statsResults = await Promise.all(
2584
+ sessions.map((record) => fetchRemoteSessionStats(record))
2585
+ );
2586
+ for (let i = 0; i < sessions.length; i++) {
2587
+ printSessionSummary(
2588
+ sessions[i],
2589
+ statsResults[i],
2590
+ sessions[i].sessionId === activeSessionId
2591
+ );
2592
+ if (i < sessions.length - 1) {
2593
+ console.log();
2594
+ }
2505
2595
  }
2506
- const chainCaps = capabilities == null ? void 0 : capabilities[`eip155:${chainId}`];
2507
- const atomicStatus = (_a3 = chainCaps == null ? void 0 : chainCaps.atomic) == null ? void 0 : _a3.status;
2508
- const canUseSendCalls = atomicStatus === "supported" || atomicStatus === "ready";
2509
- if (canUseSendCalls) {
2510
- const batchResult = await sendCallsSyncAsync({
2511
- calls: callList.map(mapCall),
2512
- capabilities: {
2513
- atomic: {
2514
- required: true
2515
- }
2516
- }
2517
- });
2518
- const receipts = (_b = batchResult.receipts) != null ? _b : [];
2519
- for (const receipt of receipts) {
2520
- if (receipt.transactionHash) {
2521
- hashes.push(receipt.transactionHash);
2522
- }
2596
+ printDataFileLocation();
2597
+ }
2598
+ async function sessionCommand(runtime) {
2599
+ const subcommand = runtime.parsed.positional[0];
2600
+ const selector = runtime.parsed.positional[1];
2601
+ if (subcommand === "resume") {
2602
+ if (!selector) {
2603
+ fatal("Usage: aomi session resume <session-id|session-N|N>");
2523
2604
  }
2524
- } else {
2525
- for (const call of callList) {
2526
- const hash = await sendTransactionAsync({
2527
- chainId: call.chainId,
2528
- to: call.to,
2529
- value: BigInt(call.value),
2530
- data: call.data ? call.data : void 0
2531
- });
2532
- hashes.push(hash);
2605
+ const resumed = setActiveSession(selector);
2606
+ if (!resumed) {
2607
+ fatal(`No local session found for selector "${selector}".`);
2533
2608
  }
2609
+ console.log(`Active session set to ${resumed.sessionId} (session-${resumed.localId}).`);
2610
+ printDataFileLocation();
2611
+ return;
2534
2612
  }
2535
- return {
2536
- txHash: hashes[hashes.length - 1],
2537
- txHashes: hashes,
2538
- executionKind: "eoa",
2539
- batched: hashes.length > 1,
2540
- sponsored: false
2541
- };
2613
+ if (subcommand === "delete") {
2614
+ if (!selector) {
2615
+ fatal("Usage: aomi session delete <session-id|session-N|N>");
2616
+ }
2617
+ const deleted = deleteStoredSession(selector);
2618
+ if (!deleted) {
2619
+ fatal(`No local session found for selector "${selector}".`);
2620
+ }
2621
+ console.log(`Deleted local session ${deleted.sessionId} (session-${deleted.localId}).`);
2622
+ const active = readState();
2623
+ if (active) {
2624
+ console.log(`Active session: ${active.sessionId}`);
2625
+ } else {
2626
+ console.log("No active session");
2627
+ }
2628
+ printDataFileLocation();
2629
+ return;
2630
+ }
2631
+ if (subcommand === "list") {
2632
+ await sessionsCommand(runtime);
2633
+ return;
2634
+ }
2635
+ fatal(
2636
+ "Usage: aomi session list\n aomi session resume <session-id|session-N|N>\n aomi session delete <session-id|session-N|N>"
2637
+ );
2542
2638
  }
2543
2639
 
2640
+ // src/cli/commands/wallet.ts
2641
+ import { createWalletClient, http } from "viem";
2642
+ import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
2643
+ import * as viemChains from "viem/chains";
2644
+
2544
2645
  // src/aa/env.ts
2545
2646
  var ALCHEMY_API_KEY_ENVS = [
2546
2647
  "ALCHEMY_API_KEY",
@@ -2775,28 +2876,50 @@ async function createAAProviderState(options) {
2775
2876
  apiKey: options.apiKey
2776
2877
  });
2777
2878
  }
2778
- function getOwnerParams(owner) {
2779
- if (!owner) {
2780
- return null;
2781
- }
2782
- if ("privateKey" in owner) {
2783
- return {
2879
+ function getDirectOwnerParams(owner) {
2880
+ return {
2881
+ kind: "ready",
2882
+ ownerParams: {
2784
2883
  para: void 0,
2785
2884
  signer: privateKeyToAccount(owner.privateKey)
2885
+ }
2886
+ };
2887
+ }
2888
+ function getParaSessionOwnerParams(owner) {
2889
+ if (owner.signer) {
2890
+ return {
2891
+ kind: "ready",
2892
+ ownerParams: __spreadValues({
2893
+ para: owner.session,
2894
+ signer: owner.signer
2895
+ }, owner.address ? { address: owner.address } : {})
2786
2896
  };
2787
2897
  }
2788
- if ("signer" in owner) {
2789
- return __spreadValues({
2790
- para: owner.para,
2791
- signer: owner.signer
2792
- }, owner.address ? { address: owner.address } : {});
2898
+ return {
2899
+ kind: "ready",
2900
+ ownerParams: __spreadValues({
2901
+ para: owner.session
2902
+ }, owner.address ? { address: owner.address } : {})
2903
+ };
2904
+ }
2905
+ function getSessionOwnerParams(owner) {
2906
+ switch (owner.adapter) {
2907
+ case "para":
2908
+ return getParaSessionOwnerParams(owner);
2909
+ default:
2910
+ return { kind: "unsupported_adapter", adapter: owner.adapter };
2793
2911
  }
2794
- if ("para" in owner) {
2795
- return __spreadValues({
2796
- para: owner.para
2797
- }, owner.address ? { address: owner.address } : {});
2912
+ }
2913
+ function getOwnerParams(owner) {
2914
+ if (!owner) {
2915
+ return { kind: "missing" };
2916
+ }
2917
+ switch (owner.kind) {
2918
+ case "direct":
2919
+ return getDirectOwnerParams(owner);
2920
+ case "session":
2921
+ return getSessionOwnerParams(owner);
2798
2922
  }
2799
- return null;
2800
2923
  }
2801
2924
  function getMissingOwnerState(plan, provider) {
2802
2925
  return {
@@ -2804,10 +2927,18 @@ function getMissingOwnerState(plan, provider) {
2804
2927
  AA: null,
2805
2928
  isPending: false,
2806
2929
  error: new Error(
2807
- `${provider} AA account creation requires a signer or Para session.`
2930
+ `${provider} AA account creation requires a direct owner or a supported session owner.`
2808
2931
  )
2809
2932
  };
2810
2933
  }
2934
+ function getUnsupportedAdapterState(plan, adapter) {
2935
+ return {
2936
+ plan,
2937
+ AA: null,
2938
+ isPending: false,
2939
+ error: new Error(`Session adapter "${adapter}" is not implemented.`)
2940
+ };
2941
+ }
2811
2942
  async function createAlchemyAAState(options) {
2812
2943
  var _a3, _b;
2813
2944
  const {
@@ -2837,11 +2968,14 @@ async function createAlchemyAAState(options) {
2837
2968
  fallbackToEoa: false
2838
2969
  });
2839
2970
  const ownerParams = getOwnerParams(owner);
2840
- if (!ownerParams) {
2971
+ if (ownerParams.kind === "missing") {
2841
2972
  return getMissingOwnerState(plan, "alchemy");
2842
2973
  }
2974
+ if (ownerParams.kind === "unsupported_adapter") {
2975
+ return getUnsupportedAdapterState(plan, ownerParams.adapter);
2976
+ }
2843
2977
  try {
2844
- const smartAccount = await createAlchemySmartAccount(__spreadProps(__spreadValues({}, ownerParams), {
2978
+ const smartAccount = await createAlchemySmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
2845
2979
  apiKey,
2846
2980
  gasPolicyId,
2847
2981
  chain,
@@ -2896,11 +3030,14 @@ async function createPimlicoAAState(options) {
2896
3030
  fallbackToEoa: false
2897
3031
  });
2898
3032
  const ownerParams = getOwnerParams(owner);
2899
- if (!ownerParams) {
3033
+ if (ownerParams.kind === "missing") {
2900
3034
  return getMissingOwnerState(plan, "pimlico");
2901
3035
  }
3036
+ if (ownerParams.kind === "unsupported_adapter") {
3037
+ return getUnsupportedAdapterState(plan, ownerParams.adapter);
3038
+ }
2902
3039
  try {
2903
- const smartAccount = await createPimlicoSmartAccount(__spreadProps(__spreadValues({}, ownerParams), {
3040
+ const smartAccount = await createPimlicoSmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
2904
3041
  apiKey,
2905
3042
  chain,
2906
3043
  rpcUrl,
@@ -2931,23 +3068,31 @@ async function createPimlicoAAState(options) {
2931
3068
  }
2932
3069
 
2933
3070
  // src/cli/execution.ts
2934
- function resolveAAProvider(config) {
2935
- var _a3;
2936
- const provider = (_a3 = config.aaProvider) != null ? _a3 : resolveDefaultProvider();
2937
- if (!isProviderConfigured(provider)) {
3071
+ function resolveAAProvider(config, options) {
3072
+ const provider = config.aaProvider;
3073
+ if (provider) {
3074
+ if (isProviderConfigured(provider)) {
3075
+ return provider;
3076
+ }
3077
+ if (!options.required) {
3078
+ return null;
3079
+ }
2938
3080
  const envName = provider === "alchemy" ? "ALCHEMY_API_KEY" : "PIMLICO_API_KEY";
2939
3081
  throw new Error(
2940
3082
  `AA provider "${provider}" is selected but ${envName} is not configured.`
2941
3083
  );
2942
3084
  }
2943
- return provider;
2944
- }
2945
- function resolveCliExecutionDecision(params) {
2946
- const { config, chain, callList } = params;
2947
- if (config.execution === "eoa") {
2948
- return { execution: "eoa" };
3085
+ try {
3086
+ return resolveDefaultProvider();
3087
+ } catch (error) {
3088
+ if (!options.required) {
3089
+ return null;
3090
+ }
3091
+ throw error;
2949
3092
  }
2950
- const provider = resolveAAProvider(config);
3093
+ }
3094
+ function getResolvedAAMode(params) {
3095
+ const { provider, config, chain, callList, fallbackToEoa } = params;
2951
3096
  const resolveOpts = {
2952
3097
  calls: callList,
2953
3098
  chainsById: { [chain.id]: chain },
@@ -2961,9 +3106,35 @@ function resolveCliExecutionDecision(params) {
2961
3106
  return {
2962
3107
  execution: "aa",
2963
3108
  provider,
2964
- aaMode: resolved.plan.mode
3109
+ aaMode: resolved.plan.mode,
3110
+ fallbackToEoa
2965
3111
  };
2966
3112
  }
3113
+ function resolveCliExecutionDecision(params) {
3114
+ const { config, chain, callList } = params;
3115
+ if (config.execution === "eoa") {
3116
+ return { execution: "eoa" };
3117
+ }
3118
+ const requireAA = config.execution === "aa";
3119
+ const provider = resolveAAProvider(config, { required: requireAA });
3120
+ if (!provider) {
3121
+ return { execution: "eoa" };
3122
+ }
3123
+ try {
3124
+ return getResolvedAAMode({
3125
+ provider,
3126
+ config,
3127
+ chain,
3128
+ callList,
3129
+ fallbackToEoa: !requireAA
3130
+ });
3131
+ } catch (error) {
3132
+ if (!requireAA) {
3133
+ return { execution: "eoa" };
3134
+ }
3135
+ throw error;
3136
+ }
3137
+ }
2967
3138
  async function createCliProviderState(params) {
2968
3139
  const { decision, chain, privateKey, rpcUrl, callList, sponsored } = params;
2969
3140
  if (decision.execution === "eoa") {
@@ -2972,7 +3143,7 @@ async function createCliProviderState(params) {
2972
3143
  return createAAProviderState({
2973
3144
  provider: decision.provider,
2974
3145
  chain,
2975
- owner: { privateKey },
3146
+ owner: { kind: "direct", privateKey },
2976
3147
  rpcUrl,
2977
3148
  callList,
2978
3149
  mode: decision.aaMode,
@@ -2983,7 +3154,7 @@ function describeExecutionDecision(decision) {
2983
3154
  if (decision.execution === "eoa") {
2984
3155
  return "eoa";
2985
3156
  }
2986
- return `aa (${decision.provider}, ${decision.aaMode})`;
3157
+ return decision.fallbackToEoa ? `aa (${decision.provider}, ${decision.aaMode}; fallback: eoa)` : `aa (${decision.provider}, ${decision.aaMode})`;
2987
3158
  }
2988
3159
 
2989
3160
  // src/cli/commands/wallet.ts
@@ -3067,8 +3238,9 @@ function createSessionFromState(state) {
3067
3238
  publicKey: state.publicKey
3068
3239
  }
3069
3240
  );
3070
- if (state.publicKey) {
3071
- session.resolveWallet(state.publicKey, state.chainId);
3241
+ const userState = buildCliUserState(state.publicKey, state.chainId);
3242
+ if (userState) {
3243
+ session.resolveUserState(userState);
3072
3244
  }
3073
3245
  return session;
3074
3246
  }
@@ -3101,24 +3273,6 @@ function getPreferredRpcUrl(chain, override) {
3101
3273
  var _a3, _b, _c;
3102
3274
  return (_c = (_b = override != null ? override : chain.rpcUrls.default.http[0]) != null ? _b : (_a3 = chain.rpcUrls.public) == null ? void 0 : _a3.http[0]) != null ? _c : "";
3103
3275
  }
3104
- async function promptForEoaFallback() {
3105
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
3106
- return false;
3107
- }
3108
- const rl = createInterface({
3109
- input: process.stdin,
3110
- output: process.stdout
3111
- });
3112
- try {
3113
- const answer = await rl.question(
3114
- "Account abstraction not available, use EOA? [yes/no] "
3115
- );
3116
- const normalized = answer.trim().toLowerCase();
3117
- return normalized === "y" || normalized === "yes";
3118
- } finally {
3119
- rl.close();
3120
- }
3121
- }
3122
3276
  async function executeCliTransaction(params) {
3123
3277
  const { privateKey, currentChainId, chainsById, rpcUrl, providerState, callList } = params;
3124
3278
  const unsupportedWalletMethod = async () => {
@@ -3194,11 +3348,12 @@ async function executeTransactionWithFallback(params) {
3194
3348
  error = retryError;
3195
3349
  }
3196
3350
  }
3197
- const useEoa = await promptForEoaFallback();
3198
- if (!useEoa) {
3351
+ if (!decision.fallbackToEoa) {
3199
3352
  throw error;
3200
3353
  }
3201
3354
  const eoaDecision = { execution: "eoa" };
3355
+ const errorMessage = error instanceof Error ? error.message : String(error);
3356
+ console.log(`AA execution failed: ${errorMessage}`);
3202
3357
  console.log("Retrying with EOA execution...");
3203
3358
  const eoaProviderState = await createCliProviderState({
3204
3359
  decision: eoaDecision,
@@ -3414,16 +3569,19 @@ Usage:
3414
3569
  aomi chat --model <rig>
3415
3570
  Set the session model before sending the message
3416
3571
  aomi chat --verbose Stream agent responses, tool calls, and events live
3417
- aomi models List models available to the current backend
3572
+ aomi app list List available apps
3573
+ aomi app current Show the current app
3574
+ aomi model list List models available to the current backend
3418
3575
  aomi model set <rig> Set the active model for the current session
3419
- aomi sessions List local sessions with metadata tables
3576
+ aomi chain list List supported chains
3577
+ aomi session list List local sessions with metadata
3420
3578
  aomi session resume <id>
3421
3579
  Resume a local session (session-id or session-N)
3422
3580
  aomi session delete <id>
3423
3581
  Delete a local session file (session-id or session-N)
3424
3582
  aomi log Show full conversation history with tool results
3425
3583
  aomi tx List pending and signed transactions
3426
- aomi sign <tx-id> [<tx-id> ...] [--aa | --eoa] [--aa-provider <name>] [--aa-mode <mode>]
3584
+ aomi sign <tx-id> [<tx-id> ...] [--eoa | --aa] [--aa-provider <name>] [--aa-mode <mode>]
3427
3585
  Sign and submit a pending transaction
3428
3586
  aomi status Show current session state
3429
3587
  aomi events List system events
@@ -3440,15 +3598,20 @@ Options:
3440
3598
  --verbose, -v Show tool calls and streaming output (for chat)
3441
3599
 
3442
3600
  Sign options:
3443
- aomi sign <tx-id> --aa
3444
- Require account-abstraction execution (default)
3445
3601
  aomi sign <tx-id> --eoa
3446
3602
  Force plain EOA execution
3603
+ aomi sign <tx-id> --aa
3604
+ Require account-abstraction execution with no EOA fallback
3447
3605
  aomi sign <tx-id> --aa-provider <name>
3448
3606
  AA provider: alchemy | pimlico
3449
3607
  aomi sign <tx-id> --aa-mode <mode>
3450
3608
  AA mode: 4337 | 7702
3451
3609
 
3610
+ Default signing behavior:
3611
+ aomi sign <tx-id>
3612
+ Try AA first, retry unsponsored AA when supported, then
3613
+ fall back to EOA automatically if AA is unavailable
3614
+
3452
3615
  Environment (overridden by flags):
3453
3616
  AOMI_BASE_URL Backend URL
3454
3617
  AOMI_API_KEY API key
@@ -3475,17 +3638,17 @@ async function main(runtime) {
3475
3638
  case "log":
3476
3639
  await logCommand(runtime);
3477
3640
  break;
3478
- case "models":
3479
- await modelsCommand(runtime);
3641
+ case "app":
3642
+ await appCommand(runtime);
3480
3643
  break;
3481
3644
  case "model":
3482
3645
  await modelCommand(runtime);
3483
3646
  break;
3484
- case "sessions":
3485
- await sessionsCommand(runtime);
3647
+ case "chain":
3648
+ chainCommand(runtime);
3486
3649
  break;
3487
3650
  case "session":
3488
- sessionCommand(runtime);
3651
+ await sessionCommand(runtime);
3489
3652
  break;
3490
3653
  case "tx":
3491
3654
  txCommand();