@aomi-labs/client 0.1.1 → 0.1.2
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 +53 -26
- package/dist/cli.js +1186 -427
- package/dist/index.cjs +8 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -8
- package/skills/aomi-transact/SKILL.md +1 -8
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,444 @@ var __spreadValues = (a, b) => {
|
|
|
19
19
|
};
|
|
20
20
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
21
|
|
|
22
|
+
// src/cli/args.ts
|
|
23
|
+
function parseArgs(argv) {
|
|
24
|
+
const raw = argv.slice(2);
|
|
25
|
+
const command = raw[0] && !raw[0].startsWith("--") ? raw[0] : void 0;
|
|
26
|
+
const rest = command ? raw.slice(1) : raw;
|
|
27
|
+
const positional = [];
|
|
28
|
+
const flags = {};
|
|
29
|
+
for (let i = 0; i < rest.length; i++) {
|
|
30
|
+
const arg = rest[i];
|
|
31
|
+
if (arg.startsWith("--") && arg.includes("=")) {
|
|
32
|
+
const [key, ...val] = arg.slice(2).split("=");
|
|
33
|
+
flags[key] = val.join("=");
|
|
34
|
+
} else if (arg.startsWith("--")) {
|
|
35
|
+
const key = arg.slice(2);
|
|
36
|
+
const next = rest[i + 1];
|
|
37
|
+
if (next && !next.startsWith("-")) {
|
|
38
|
+
flags[key] = next;
|
|
39
|
+
i++;
|
|
40
|
+
} else {
|
|
41
|
+
flags[key] = "true";
|
|
42
|
+
}
|
|
43
|
+
} else if (arg.startsWith("-") && arg.length === 2) {
|
|
44
|
+
flags[arg.slice(1)] = "true";
|
|
45
|
+
} else {
|
|
46
|
+
positional.push(arg);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { command, positional, flags };
|
|
50
|
+
}
|
|
51
|
+
function getConfig(parsed) {
|
|
52
|
+
var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
53
|
+
return {
|
|
54
|
+
baseUrl: (_b = (_a3 = parsed.flags["backend-url"]) != null ? _a3 : process.env.AOMI_BASE_URL) != null ? _b : "https://api.aomi.dev",
|
|
55
|
+
apiKey: (_c = parsed.flags["api-key"]) != null ? _c : process.env.AOMI_API_KEY,
|
|
56
|
+
namespace: (_e = (_d = parsed.flags["namespace"]) != null ? _d : process.env.AOMI_NAMESPACE) != null ? _e : "default",
|
|
57
|
+
model: (_f = parsed.flags["model"]) != null ? _f : process.env.AOMI_MODEL,
|
|
58
|
+
publicKey: (_g = parsed.flags["public-key"]) != null ? _g : process.env.AOMI_PUBLIC_KEY,
|
|
59
|
+
privateKey: (_h = parsed.flags["private-key"]) != null ? _h : process.env.PRIVATE_KEY,
|
|
60
|
+
chainRpcUrl: (_i = parsed.flags["rpc-url"]) != null ? _i : process.env.CHAIN_RPC_URL
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function createRuntime(argv) {
|
|
64
|
+
const parsed = parseArgs(argv);
|
|
65
|
+
return {
|
|
66
|
+
parsed,
|
|
67
|
+
config: getConfig(parsed)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/cli/state.ts
|
|
72
|
+
import {
|
|
73
|
+
existsSync,
|
|
74
|
+
mkdirSync,
|
|
75
|
+
readFileSync,
|
|
76
|
+
readdirSync,
|
|
77
|
+
rmSync,
|
|
78
|
+
writeFileSync
|
|
79
|
+
} from "fs";
|
|
80
|
+
import { basename, join } from "path";
|
|
81
|
+
import { homedir, tmpdir } from "os";
|
|
82
|
+
var SESSION_FILE_PREFIX = "session-";
|
|
83
|
+
var SESSION_FILE_SUFFIX = ".json";
|
|
84
|
+
var _a;
|
|
85
|
+
var LEGACY_STATE_FILE = join(
|
|
86
|
+
(_a = process.env.XDG_RUNTIME_DIR) != null ? _a : tmpdir(),
|
|
87
|
+
"aomi-session.json"
|
|
88
|
+
);
|
|
89
|
+
var _a2;
|
|
90
|
+
var STATE_ROOT_DIR = (_a2 = process.env.AOMI_STATE_DIR) != null ? _a2 : join(homedir(), ".aomi");
|
|
91
|
+
var SESSIONS_DIR = join(STATE_ROOT_DIR, "sessions");
|
|
92
|
+
var ACTIVE_SESSION_FILE = join(STATE_ROOT_DIR, "active-session.txt");
|
|
93
|
+
function ensureStorageDirs() {
|
|
94
|
+
mkdirSync(SESSIONS_DIR, { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
function parseSessionFileLocalId(filename) {
|
|
97
|
+
const match = filename.match(/^session-(\d+)\.json$/);
|
|
98
|
+
if (!match) return null;
|
|
99
|
+
const localId = parseInt(match[1], 10);
|
|
100
|
+
return Number.isNaN(localId) ? null : localId;
|
|
101
|
+
}
|
|
102
|
+
function toSessionFilePath(localId) {
|
|
103
|
+
return join(SESSIONS_DIR, `${SESSION_FILE_PREFIX}${localId}${SESSION_FILE_SUFFIX}`);
|
|
104
|
+
}
|
|
105
|
+
function toCliSessionState(stored) {
|
|
106
|
+
return {
|
|
107
|
+
sessionId: stored.sessionId,
|
|
108
|
+
baseUrl: stored.baseUrl,
|
|
109
|
+
namespace: stored.namespace,
|
|
110
|
+
model: stored.model,
|
|
111
|
+
apiKey: stored.apiKey,
|
|
112
|
+
publicKey: stored.publicKey,
|
|
113
|
+
pendingTxs: stored.pendingTxs,
|
|
114
|
+
signedTxs: stored.signedTxs
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function readStoredSession(path) {
|
|
118
|
+
var _a3;
|
|
119
|
+
try {
|
|
120
|
+
const raw = readFileSync(path, "utf-8");
|
|
121
|
+
const parsed = JSON.parse(raw);
|
|
122
|
+
if (typeof parsed.sessionId !== "string" || typeof parsed.baseUrl !== "string") {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const fallbackLocalId = (_a3 = parseSessionFileLocalId(basename(path))) != null ? _a3 : 0;
|
|
126
|
+
return {
|
|
127
|
+
sessionId: parsed.sessionId,
|
|
128
|
+
baseUrl: parsed.baseUrl,
|
|
129
|
+
namespace: parsed.namespace,
|
|
130
|
+
model: parsed.model,
|
|
131
|
+
apiKey: parsed.apiKey,
|
|
132
|
+
publicKey: parsed.publicKey,
|
|
133
|
+
pendingTxs: parsed.pendingTxs,
|
|
134
|
+
signedTxs: parsed.signedTxs,
|
|
135
|
+
localId: typeof parsed.localId === "number" && parsed.localId > 0 ? parsed.localId : fallbackLocalId,
|
|
136
|
+
createdAt: typeof parsed.createdAt === "number" && parsed.createdAt > 0 ? parsed.createdAt : Date.now(),
|
|
137
|
+
updatedAt: typeof parsed.updatedAt === "number" && parsed.updatedAt > 0 ? parsed.updatedAt : Date.now()
|
|
138
|
+
};
|
|
139
|
+
} catch (e) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function readActiveLocalId() {
|
|
144
|
+
try {
|
|
145
|
+
if (!existsSync(ACTIVE_SESSION_FILE)) return null;
|
|
146
|
+
const raw = readFileSync(ACTIVE_SESSION_FILE, "utf-8").trim();
|
|
147
|
+
if (!raw) return null;
|
|
148
|
+
const parsed = parseInt(raw, 10);
|
|
149
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
150
|
+
} catch (e) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function writeActiveLocalId(localId) {
|
|
155
|
+
try {
|
|
156
|
+
if (localId === null) {
|
|
157
|
+
if (existsSync(ACTIVE_SESSION_FILE)) {
|
|
158
|
+
rmSync(ACTIVE_SESSION_FILE);
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
ensureStorageDirs();
|
|
163
|
+
writeFileSync(ACTIVE_SESSION_FILE, String(localId));
|
|
164
|
+
} catch (e) {
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function readAllStoredSessions() {
|
|
168
|
+
try {
|
|
169
|
+
ensureStorageDirs();
|
|
170
|
+
const filenames = readdirSync(SESSIONS_DIR).map((name) => ({ name, localId: parseSessionFileLocalId(name) })).filter(
|
|
171
|
+
(entry) => entry.localId !== null
|
|
172
|
+
).sort((a, b) => a.localId - b.localId);
|
|
173
|
+
const sessions = [];
|
|
174
|
+
for (const entry of filenames) {
|
|
175
|
+
const path = join(SESSIONS_DIR, entry.name);
|
|
176
|
+
const stored = readStoredSession(path);
|
|
177
|
+
if (stored) {
|
|
178
|
+
sessions.push(stored);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return sessions;
|
|
182
|
+
} catch (e) {
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function getNextLocalId(sessions) {
|
|
187
|
+
const maxLocalId = sessions.reduce((max, session) => {
|
|
188
|
+
return session.localId > max ? session.localId : max;
|
|
189
|
+
}, 0);
|
|
190
|
+
return maxLocalId + 1;
|
|
191
|
+
}
|
|
192
|
+
var _migrationDone = false;
|
|
193
|
+
function migrateLegacyStateIfNeeded() {
|
|
194
|
+
if (_migrationDone) return;
|
|
195
|
+
_migrationDone = true;
|
|
196
|
+
if (!existsSync(LEGACY_STATE_FILE)) return;
|
|
197
|
+
const existing = readAllStoredSessions();
|
|
198
|
+
if (existing.length > 0) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const raw = readFileSync(LEGACY_STATE_FILE, "utf-8");
|
|
203
|
+
const legacy = JSON.parse(raw);
|
|
204
|
+
if (!legacy.sessionId || !legacy.baseUrl) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const now = Date.now();
|
|
208
|
+
const migrated = __spreadProps(__spreadValues({}, legacy), {
|
|
209
|
+
localId: 1,
|
|
210
|
+
createdAt: now,
|
|
211
|
+
updatedAt: now
|
|
212
|
+
});
|
|
213
|
+
ensureStorageDirs();
|
|
214
|
+
writeFileSync(toSessionFilePath(1), JSON.stringify(migrated, null, 2));
|
|
215
|
+
writeActiveLocalId(1);
|
|
216
|
+
rmSync(LEGACY_STATE_FILE);
|
|
217
|
+
} catch (e) {
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function resolveStoredSession(selector, sessions) {
|
|
221
|
+
var _a3, _b;
|
|
222
|
+
const trimmed = selector.trim();
|
|
223
|
+
if (!trimmed) return null;
|
|
224
|
+
const localMatch = trimmed.match(/^(?:session-)?(\d+)$/);
|
|
225
|
+
if (localMatch) {
|
|
226
|
+
const localId = parseInt(localMatch[1], 10);
|
|
227
|
+
if (!Number.isNaN(localId)) {
|
|
228
|
+
return (_a3 = sessions.find((session) => session.localId === localId)) != null ? _a3 : null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return (_b = sessions.find((session) => session.sessionId === trimmed)) != null ? _b : null;
|
|
232
|
+
}
|
|
233
|
+
function toStoredSessionRecord(stored) {
|
|
234
|
+
return {
|
|
235
|
+
localId: stored.localId,
|
|
236
|
+
sessionId: stored.sessionId,
|
|
237
|
+
path: toSessionFilePath(stored.localId),
|
|
238
|
+
createdAt: stored.createdAt,
|
|
239
|
+
updatedAt: stored.updatedAt,
|
|
240
|
+
state: toCliSessionState(stored)
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function getActiveStateFilePath() {
|
|
244
|
+
migrateLegacyStateIfNeeded();
|
|
245
|
+
const sessions = readAllStoredSessions();
|
|
246
|
+
const activeLocalId = readActiveLocalId();
|
|
247
|
+
if (activeLocalId === null) return null;
|
|
248
|
+
const active = sessions.find((session) => session.localId === activeLocalId);
|
|
249
|
+
return active ? toSessionFilePath(active.localId) : null;
|
|
250
|
+
}
|
|
251
|
+
function listStoredSessions() {
|
|
252
|
+
migrateLegacyStateIfNeeded();
|
|
253
|
+
return readAllStoredSessions().map(toStoredSessionRecord);
|
|
254
|
+
}
|
|
255
|
+
function setActiveSession(selector) {
|
|
256
|
+
migrateLegacyStateIfNeeded();
|
|
257
|
+
const sessions = readAllStoredSessions();
|
|
258
|
+
const target = resolveStoredSession(selector, sessions);
|
|
259
|
+
if (!target) return null;
|
|
260
|
+
writeActiveLocalId(target.localId);
|
|
261
|
+
return toStoredSessionRecord(target);
|
|
262
|
+
}
|
|
263
|
+
function deleteStoredSession(selector) {
|
|
264
|
+
var _a3, _b;
|
|
265
|
+
migrateLegacyStateIfNeeded();
|
|
266
|
+
const sessions = readAllStoredSessions();
|
|
267
|
+
const target = resolveStoredSession(selector, sessions);
|
|
268
|
+
if (!target) return null;
|
|
269
|
+
const targetPath = toSessionFilePath(target.localId);
|
|
270
|
+
try {
|
|
271
|
+
if (existsSync(targetPath)) {
|
|
272
|
+
rmSync(targetPath);
|
|
273
|
+
}
|
|
274
|
+
} catch (e) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
const activeLocalId = readActiveLocalId();
|
|
278
|
+
if (activeLocalId === target.localId) {
|
|
279
|
+
const remaining = readAllStoredSessions().sort((a, b) => b.updatedAt - a.updatedAt);
|
|
280
|
+
writeActiveLocalId((_b = (_a3 = remaining[0]) == null ? void 0 : _a3.localId) != null ? _b : null);
|
|
281
|
+
}
|
|
282
|
+
return toStoredSessionRecord(target);
|
|
283
|
+
}
|
|
284
|
+
function readState() {
|
|
285
|
+
var _a3;
|
|
286
|
+
migrateLegacyStateIfNeeded();
|
|
287
|
+
const sessions = readAllStoredSessions();
|
|
288
|
+
if (sessions.length === 0) return null;
|
|
289
|
+
const activeLocalId = readActiveLocalId();
|
|
290
|
+
if (activeLocalId === null) {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
const active = (_a3 = sessions.find((session) => session.localId === activeLocalId)) != null ? _a3 : null;
|
|
294
|
+
if (!active) {
|
|
295
|
+
writeActiveLocalId(null);
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
return toCliSessionState(active);
|
|
299
|
+
}
|
|
300
|
+
function writeState(state) {
|
|
301
|
+
var _a3, _b;
|
|
302
|
+
migrateLegacyStateIfNeeded();
|
|
303
|
+
ensureStorageDirs();
|
|
304
|
+
const sessions = readAllStoredSessions();
|
|
305
|
+
const activeLocalId = readActiveLocalId();
|
|
306
|
+
const existingBySessionId = sessions.find(
|
|
307
|
+
(session) => session.sessionId === state.sessionId
|
|
308
|
+
);
|
|
309
|
+
const existingByActive = activeLocalId !== null ? sessions.find((session) => session.localId === activeLocalId) : void 0;
|
|
310
|
+
const existing = existingBySessionId != null ? existingBySessionId : existingByActive;
|
|
311
|
+
const now = Date.now();
|
|
312
|
+
const localId = (_a3 = existing == null ? void 0 : existing.localId) != null ? _a3 : getNextLocalId(sessions);
|
|
313
|
+
const createdAt = (_b = existing == null ? void 0 : existing.createdAt) != null ? _b : now;
|
|
314
|
+
const payload = __spreadProps(__spreadValues({}, state), {
|
|
315
|
+
localId,
|
|
316
|
+
createdAt,
|
|
317
|
+
updatedAt: now
|
|
318
|
+
});
|
|
319
|
+
writeFileSync(toSessionFilePath(localId), JSON.stringify(payload, null, 2));
|
|
320
|
+
writeActiveLocalId(localId);
|
|
321
|
+
}
|
|
322
|
+
function clearState() {
|
|
323
|
+
migrateLegacyStateIfNeeded();
|
|
324
|
+
writeActiveLocalId(null);
|
|
325
|
+
}
|
|
326
|
+
function getNextTxId(state) {
|
|
327
|
+
var _a3, _b;
|
|
328
|
+
const allIds = [...(_a3 = state.pendingTxs) != null ? _a3 : [], ...(_b = state.signedTxs) != null ? _b : []].map((tx) => {
|
|
329
|
+
const match = tx.id.match(/^tx-(\d+)$/);
|
|
330
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
331
|
+
});
|
|
332
|
+
const max = allIds.length > 0 ? Math.max(...allIds) : 0;
|
|
333
|
+
return `tx-${max + 1}`;
|
|
334
|
+
}
|
|
335
|
+
function addPendingTx(state, tx) {
|
|
336
|
+
if (!state.pendingTxs) state.pendingTxs = [];
|
|
337
|
+
const pending = __spreadProps(__spreadValues({}, tx), {
|
|
338
|
+
id: getNextTxId(state)
|
|
339
|
+
});
|
|
340
|
+
state.pendingTxs.push(pending);
|
|
341
|
+
writeState(state);
|
|
342
|
+
return pending;
|
|
343
|
+
}
|
|
344
|
+
function removePendingTx(state, id) {
|
|
345
|
+
if (!state.pendingTxs) return null;
|
|
346
|
+
const idx = state.pendingTxs.findIndex((tx) => tx.id === id);
|
|
347
|
+
if (idx === -1) return null;
|
|
348
|
+
const [removed] = state.pendingTxs.splice(idx, 1);
|
|
349
|
+
writeState(state);
|
|
350
|
+
return removed;
|
|
351
|
+
}
|
|
352
|
+
function addSignedTx(state, tx) {
|
|
353
|
+
if (!state.signedTxs) state.signedTxs = [];
|
|
354
|
+
state.signedTxs.push(tx);
|
|
355
|
+
writeState(state);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// src/cli/output.ts
|
|
359
|
+
var DIM = "\x1B[2m";
|
|
360
|
+
var CYAN = "\x1B[36m";
|
|
361
|
+
var YELLOW = "\x1B[33m";
|
|
362
|
+
var GREEN = "\x1B[32m";
|
|
363
|
+
var RESET = "\x1B[0m";
|
|
364
|
+
function printDataFileLocation() {
|
|
365
|
+
const activeFile = getActiveStateFilePath();
|
|
366
|
+
if (activeFile) {
|
|
367
|
+
console.log(`Data stored at ${activeFile} \u{1F4DD}`);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
console.log(`Data stored under ${STATE_ROOT_DIR} \u{1F4DD}`);
|
|
371
|
+
}
|
|
372
|
+
function printToolUpdate(event) {
|
|
373
|
+
var _a3;
|
|
374
|
+
const name = getToolNameFromEvent(event);
|
|
375
|
+
const status = (_a3 = event.status) != null ? _a3 : "running";
|
|
376
|
+
console.log(`${DIM}\u{1F527} [tool] ${name}: ${status}${RESET}`);
|
|
377
|
+
}
|
|
378
|
+
function printToolComplete(event) {
|
|
379
|
+
const name = getToolNameFromEvent(event);
|
|
380
|
+
const result = getToolResultFromEvent(event);
|
|
381
|
+
const line = formatToolResultLine(name, result);
|
|
382
|
+
console.log(line);
|
|
383
|
+
}
|
|
384
|
+
function printToolResultLine(name, result) {
|
|
385
|
+
console.log(formatToolResultLine(name, result));
|
|
386
|
+
}
|
|
387
|
+
function getToolNameFromEvent(event) {
|
|
388
|
+
var _a3, _b;
|
|
389
|
+
return (_b = (_a3 = event.tool_name) != null ? _a3 : event.name) != null ? _b : "unknown";
|
|
390
|
+
}
|
|
391
|
+
function getToolResultFromEvent(event) {
|
|
392
|
+
var _a3;
|
|
393
|
+
return (_a3 = event.result) != null ? _a3 : event.output;
|
|
394
|
+
}
|
|
395
|
+
function toToolResultKey(name, result) {
|
|
396
|
+
return `${name}
|
|
397
|
+
${result != null ? result : ""}`;
|
|
398
|
+
}
|
|
399
|
+
function getMessageToolResults(messages, startAt = 0) {
|
|
400
|
+
const results = [];
|
|
401
|
+
for (let i = startAt; i < messages.length; i++) {
|
|
402
|
+
const toolResult = messages[i].tool_result;
|
|
403
|
+
if (!toolResult) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
const [name, result] = toolResult;
|
|
407
|
+
if (!name || typeof result !== "string") {
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
results.push({ name, result });
|
|
411
|
+
}
|
|
412
|
+
return results;
|
|
413
|
+
}
|
|
414
|
+
function isAlwaysVisibleTool(name) {
|
|
415
|
+
const normalized = name.toLowerCase();
|
|
416
|
+
if (normalized.includes("encode_and_simulate") || normalized.includes("encode-and-simulate") || normalized.includes("encode_and_view") || normalized.includes("encode-and-view")) {
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
if (normalized.startsWith("simulate ")) {
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
function printNewAgentMessages(messages, lastPrintedCount) {
|
|
425
|
+
const agentMessages = messages.filter(
|
|
426
|
+
(message) => message.sender === "agent" || message.sender === "assistant"
|
|
427
|
+
);
|
|
428
|
+
let handled = lastPrintedCount;
|
|
429
|
+
for (let i = lastPrintedCount; i < agentMessages.length; i++) {
|
|
430
|
+
const message = agentMessages[i];
|
|
431
|
+
if (message.is_streaming) {
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
if (message.content) {
|
|
435
|
+
console.log(`${CYAN}\u{1F916} ${message.content}${RESET}`);
|
|
436
|
+
}
|
|
437
|
+
handled = i + 1;
|
|
438
|
+
}
|
|
439
|
+
return handled;
|
|
440
|
+
}
|
|
441
|
+
function formatLogContent(content) {
|
|
442
|
+
if (!content) return null;
|
|
443
|
+
const trimmed = content.trim();
|
|
444
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
445
|
+
}
|
|
446
|
+
function formatToolResultPreview(result, maxLength = 200) {
|
|
447
|
+
const normalized = result.replace(/\s+/g, " ").trim();
|
|
448
|
+
if (normalized.length <= maxLength) {
|
|
449
|
+
return normalized;
|
|
450
|
+
}
|
|
451
|
+
return `${normalized.slice(0, maxLength)}\u2026`;
|
|
452
|
+
}
|
|
453
|
+
function formatToolResultLine(name, result) {
|
|
454
|
+
if (!result) {
|
|
455
|
+
return `${GREEN}\u2714 [tool] ${name} done${RESET}`;
|
|
456
|
+
}
|
|
457
|
+
return `${GREEN}\u2714 [tool] ${name} \u2192 ${formatToolResultPreview(result, 120)}${RESET}`;
|
|
458
|
+
}
|
|
459
|
+
|
|
22
460
|
// src/sse.ts
|
|
23
461
|
function extractSseData(rawEvent) {
|
|
24
462
|
const dataLines = rawEvent.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart());
|
|
@@ -86,13 +524,13 @@ function createSseSubscriber({
|
|
|
86
524
|
stopped: false,
|
|
87
525
|
listeners: /* @__PURE__ */ new Set([listener]),
|
|
88
526
|
stop: (reason) => {
|
|
89
|
-
var
|
|
527
|
+
var _a3;
|
|
90
528
|
subscription.stopped = true;
|
|
91
529
|
if (subscription.retryTimer) {
|
|
92
530
|
clearTimeout(subscription.retryTimer);
|
|
93
531
|
subscription.retryTimer = null;
|
|
94
532
|
}
|
|
95
|
-
(
|
|
533
|
+
(_a3 = subscription.abortController) == null ? void 0 : _a3.abort();
|
|
96
534
|
subscription.abortController = null;
|
|
97
535
|
logger == null ? void 0 : logger.debug("[aomi][sse] stop", {
|
|
98
536
|
sessionId,
|
|
@@ -115,7 +553,7 @@ function createSseSubscriber({
|
|
|
115
553
|
}, delayMs);
|
|
116
554
|
};
|
|
117
555
|
const open = async () => {
|
|
118
|
-
var
|
|
556
|
+
var _a3;
|
|
119
557
|
if (subscription.stopped) return;
|
|
120
558
|
if (subscription.retryTimer) {
|
|
121
559
|
clearTimeout(subscription.retryTimer);
|
|
@@ -139,19 +577,19 @@ function createSseSubscriber({
|
|
|
139
577
|
}
|
|
140
578
|
subscription.retries = 0;
|
|
141
579
|
await readSseStream(response.body, controller.signal, (data) => {
|
|
142
|
-
var
|
|
143
|
-
let
|
|
580
|
+
var _a4, _b;
|
|
581
|
+
let parsed;
|
|
144
582
|
try {
|
|
145
|
-
|
|
583
|
+
parsed = JSON.parse(data);
|
|
146
584
|
} catch (error) {
|
|
147
585
|
for (const item of subscription.listeners) {
|
|
148
|
-
(
|
|
586
|
+
(_a4 = item.onError) == null ? void 0 : _a4.call(item, error);
|
|
149
587
|
}
|
|
150
588
|
return;
|
|
151
589
|
}
|
|
152
590
|
for (const item of subscription.listeners) {
|
|
153
591
|
try {
|
|
154
|
-
item.onUpdate(
|
|
592
|
+
item.onUpdate(parsed);
|
|
155
593
|
} catch (error) {
|
|
156
594
|
(_b = item.onError) == null ? void 0 : _b.call(item, error);
|
|
157
595
|
}
|
|
@@ -166,7 +604,7 @@ function createSseSubscriber({
|
|
|
166
604
|
} catch (error) {
|
|
167
605
|
if (!controller.signal.aborted && !subscription.stopped) {
|
|
168
606
|
for (const item of subscription.listeners) {
|
|
169
|
-
(
|
|
607
|
+
(_a3 = item.onError) == null ? void 0 : _a3.call(item, error);
|
|
170
608
|
}
|
|
171
609
|
}
|
|
172
610
|
}
|
|
@@ -260,8 +698,8 @@ var AomiClient = class {
|
|
|
260
698
|
* Send a chat message and return updated session state.
|
|
261
699
|
*/
|
|
262
700
|
async sendMessage(sessionId, message, options) {
|
|
263
|
-
var
|
|
264
|
-
const namespace = (
|
|
701
|
+
var _a3, _b;
|
|
702
|
+
const namespace = (_a3 = options == null ? void 0 : options.namespace) != null ? _a3 : "default";
|
|
265
703
|
const apiKey = (_b = options == null ? void 0 : options.apiKey) != null ? _b : this.apiKey;
|
|
266
704
|
const payload = { message, namespace };
|
|
267
705
|
if (options == null ? void 0 : options.publicKey) {
|
|
@@ -439,12 +877,12 @@ var AomiClient = class {
|
|
|
439
877
|
* Get available namespaces.
|
|
440
878
|
*/
|
|
441
879
|
async getNamespaces(sessionId, options) {
|
|
442
|
-
var
|
|
880
|
+
var _a3;
|
|
443
881
|
const url = new URL("/api/control/namespaces", this.baseUrl);
|
|
444
882
|
if (options == null ? void 0 : options.publicKey) {
|
|
445
883
|
url.searchParams.set("public_key", options.publicKey);
|
|
446
884
|
}
|
|
447
|
-
const apiKey = (
|
|
885
|
+
const apiKey = (_a3 = options == null ? void 0 : options.apiKey) != null ? _a3 : this.apiKey;
|
|
448
886
|
const headers = new Headers(withSessionHeader(sessionId));
|
|
449
887
|
if (apiKey) {
|
|
450
888
|
headers.set(API_KEY_HEADER, apiKey);
|
|
@@ -458,10 +896,16 @@ var AomiClient = class {
|
|
|
458
896
|
/**
|
|
459
897
|
* Get available models.
|
|
460
898
|
*/
|
|
461
|
-
async getModels(sessionId) {
|
|
899
|
+
async getModels(sessionId, options) {
|
|
900
|
+
var _a3;
|
|
462
901
|
const url = new URL("/api/control/models", this.baseUrl);
|
|
902
|
+
const apiKey = (_a3 = options == null ? void 0 : options.apiKey) != null ? _a3 : this.apiKey;
|
|
903
|
+
const headers = new Headers(withSessionHeader(sessionId));
|
|
904
|
+
if (apiKey) {
|
|
905
|
+
headers.set(API_KEY_HEADER, apiKey);
|
|
906
|
+
}
|
|
463
907
|
const response = await fetch(url.toString(), {
|
|
464
|
-
headers
|
|
908
|
+
headers
|
|
465
909
|
});
|
|
466
910
|
if (!response.ok) {
|
|
467
911
|
throw new Error(`Failed to get models: HTTP ${response.status}`);
|
|
@@ -472,8 +916,8 @@ var AomiClient = class {
|
|
|
472
916
|
* Set the model for a session.
|
|
473
917
|
*/
|
|
474
918
|
async setModel(sessionId, rig, options) {
|
|
475
|
-
var
|
|
476
|
-
const apiKey = (
|
|
919
|
+
var _a3;
|
|
920
|
+
const apiKey = (_a3 = options == null ? void 0 : options.apiKey) != null ? _a3 : this.apiKey;
|
|
477
921
|
const payload = { rig };
|
|
478
922
|
if (options == null ? void 0 : options.namespace) {
|
|
479
923
|
payload.namespace = options.namespace;
|
|
@@ -570,11 +1014,11 @@ function isAsyncCallback(event) {
|
|
|
570
1014
|
|
|
571
1015
|
// src/event-unwrap.ts
|
|
572
1016
|
function unwrapSystemEvent(event) {
|
|
573
|
-
var
|
|
1017
|
+
var _a3;
|
|
574
1018
|
if (isInlineCall(event)) {
|
|
575
1019
|
return {
|
|
576
1020
|
type: event.InlineCall.type,
|
|
577
|
-
payload: (
|
|
1021
|
+
payload: (_a3 = event.InlineCall.payload) != null ? _a3 : event.InlineCall
|
|
578
1022
|
};
|
|
579
1023
|
}
|
|
580
1024
|
if (isSystemNotice(event)) {
|
|
@@ -605,10 +1049,10 @@ function asRecord(value) {
|
|
|
605
1049
|
return value;
|
|
606
1050
|
}
|
|
607
1051
|
function getToolArgs(payload) {
|
|
608
|
-
var
|
|
1052
|
+
var _a3;
|
|
609
1053
|
const root = asRecord(payload);
|
|
610
1054
|
const nestedArgs = asRecord(root == null ? void 0 : root.args);
|
|
611
|
-
return (
|
|
1055
|
+
return (_a3 = nestedArgs != null ? nestedArgs : root) != null ? _a3 : {};
|
|
612
1056
|
}
|
|
613
1057
|
function parseChainId(value) {
|
|
614
1058
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
@@ -619,11 +1063,11 @@ function parseChainId(value) {
|
|
|
619
1063
|
const parsedHex = Number.parseInt(trimmed.slice(2), 16);
|
|
620
1064
|
return Number.isFinite(parsedHex) ? parsedHex : void 0;
|
|
621
1065
|
}
|
|
622
|
-
const
|
|
623
|
-
return Number.isFinite(
|
|
1066
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
1067
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
624
1068
|
}
|
|
625
1069
|
function normalizeTxPayload(payload) {
|
|
626
|
-
var
|
|
1070
|
+
var _a3, _b, _c;
|
|
627
1071
|
const root = asRecord(payload);
|
|
628
1072
|
const args = getToolArgs(payload);
|
|
629
1073
|
const ctx = asRecord(root == null ? void 0 : root.ctx);
|
|
@@ -632,19 +1076,19 @@ function normalizeTxPayload(payload) {
|
|
|
632
1076
|
const valueRaw = args.value;
|
|
633
1077
|
const value = typeof valueRaw === "string" ? valueRaw : typeof valueRaw === "number" && Number.isFinite(valueRaw) ? String(Math.trunc(valueRaw)) : void 0;
|
|
634
1078
|
const data = typeof args.data === "string" ? args.data : void 0;
|
|
635
|
-
const chainId = (_c = (_b = (
|
|
1079
|
+
const chainId = (_c = (_b = (_a3 = parseChainId(args.chainId)) != null ? _a3 : parseChainId(args.chain_id)) != null ? _b : parseChainId(ctx == null ? void 0 : ctx.user_chain_id)) != null ? _c : parseChainId(ctx == null ? void 0 : ctx.userChainId);
|
|
636
1080
|
return { to, value, data, chainId };
|
|
637
1081
|
}
|
|
638
1082
|
function normalizeEip712Payload(payload) {
|
|
639
|
-
var
|
|
1083
|
+
var _a3;
|
|
640
1084
|
const args = getToolArgs(payload);
|
|
641
|
-
const typedDataRaw = (
|
|
1085
|
+
const typedDataRaw = (_a3 = args.typed_data) != null ? _a3 : args.typedData;
|
|
642
1086
|
let typedData;
|
|
643
1087
|
if (typeof typedDataRaw === "string") {
|
|
644
1088
|
try {
|
|
645
|
-
const
|
|
646
|
-
if (
|
|
647
|
-
typedData =
|
|
1089
|
+
const parsed = JSON.parse(typedDataRaw);
|
|
1090
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
1091
|
+
typedData = parsed;
|
|
648
1092
|
}
|
|
649
1093
|
} catch (e) {
|
|
650
1094
|
typedData = void 0;
|
|
@@ -659,7 +1103,7 @@ function normalizeEip712Payload(payload) {
|
|
|
659
1103
|
// src/session.ts
|
|
660
1104
|
var Session = class extends TypedEventEmitter {
|
|
661
1105
|
constructor(clientOrOptions, sessionOptions) {
|
|
662
|
-
var
|
|
1106
|
+
var _a3, _b, _c;
|
|
663
1107
|
super();
|
|
664
1108
|
// Internal state
|
|
665
1109
|
this.pollTimer = null;
|
|
@@ -672,7 +1116,7 @@ var Session = class extends TypedEventEmitter {
|
|
|
672
1116
|
// For send() blocking behavior
|
|
673
1117
|
this.pendingResolve = null;
|
|
674
1118
|
this.client = clientOrOptions instanceof AomiClient ? clientOrOptions : new AomiClient(clientOrOptions);
|
|
675
|
-
this.sessionId = (
|
|
1119
|
+
this.sessionId = (_a3 = sessionOptions == null ? void 0 : sessionOptions.sessionId) != null ? _a3 : crypto.randomUUID();
|
|
676
1120
|
this.namespace = (_b = sessionOptions == null ? void 0 : sessionOptions.namespace) != null ? _b : "default";
|
|
677
1121
|
this.publicKey = sessionOptions == null ? void 0 : sessionOptions.publicKey;
|
|
678
1122
|
this.apiKey = sessionOptions == null ? void 0 : sessionOptions.apiKey;
|
|
@@ -743,14 +1187,14 @@ var Session = class extends TypedEventEmitter {
|
|
|
743
1187
|
* Sends the result to the backend and resumes polling.
|
|
744
1188
|
*/
|
|
745
1189
|
async resolve(requestId, result) {
|
|
746
|
-
var
|
|
1190
|
+
var _a3;
|
|
747
1191
|
const req = this.removeWalletRequest(requestId);
|
|
748
1192
|
if (!req) {
|
|
749
1193
|
throw new Error(`No pending wallet request with id "${requestId}"`);
|
|
750
1194
|
}
|
|
751
1195
|
if (req.kind === "transaction") {
|
|
752
1196
|
await this.sendSystemEvent("wallet:tx_complete", {
|
|
753
|
-
txHash: (
|
|
1197
|
+
txHash: (_a3 = result.txHash) != null ? _a3 : "",
|
|
754
1198
|
status: "success",
|
|
755
1199
|
amount: result.amount
|
|
756
1200
|
});
|
|
@@ -811,11 +1255,11 @@ var Session = class extends TypedEventEmitter {
|
|
|
811
1255
|
* The session cannot be used after closing.
|
|
812
1256
|
*/
|
|
813
1257
|
close() {
|
|
814
|
-
var
|
|
1258
|
+
var _a3;
|
|
815
1259
|
if (this.closed) return;
|
|
816
1260
|
this.closed = true;
|
|
817
1261
|
this.stopPolling();
|
|
818
|
-
(
|
|
1262
|
+
(_a3 = this.unsubscribeSSE) == null ? void 0 : _a3.call(this);
|
|
819
1263
|
this.unsubscribeSSE = null;
|
|
820
1264
|
this.resolvePending();
|
|
821
1265
|
this.removeAllListeners();
|
|
@@ -843,23 +1287,23 @@ var Session = class extends TypedEventEmitter {
|
|
|
843
1287
|
// Internal — Polling (ported from PollingController)
|
|
844
1288
|
// ===========================================================================
|
|
845
1289
|
startPolling() {
|
|
846
|
-
var
|
|
1290
|
+
var _a3;
|
|
847
1291
|
if (this.pollTimer || this.closed) return;
|
|
848
|
-
(
|
|
1292
|
+
(_a3 = this.logger) == null ? void 0 : _a3.debug("[session] polling started", this.sessionId);
|
|
849
1293
|
this.pollTimer = setInterval(() => {
|
|
850
1294
|
void this.pollTick();
|
|
851
1295
|
}, this.pollIntervalMs);
|
|
852
1296
|
}
|
|
853
1297
|
stopPolling() {
|
|
854
|
-
var
|
|
1298
|
+
var _a3;
|
|
855
1299
|
if (this.pollTimer) {
|
|
856
1300
|
clearInterval(this.pollTimer);
|
|
857
1301
|
this.pollTimer = null;
|
|
858
|
-
(
|
|
1302
|
+
(_a3 = this.logger) == null ? void 0 : _a3.debug("[session] polling stopped", this.sessionId);
|
|
859
1303
|
}
|
|
860
1304
|
}
|
|
861
1305
|
async pollTick() {
|
|
862
|
-
var
|
|
1306
|
+
var _a3;
|
|
863
1307
|
if (!this.pollTimer) return;
|
|
864
1308
|
try {
|
|
865
1309
|
const state = await this.client.fetchState(
|
|
@@ -875,7 +1319,7 @@ var Session = class extends TypedEventEmitter {
|
|
|
875
1319
|
this.resolvePending();
|
|
876
1320
|
}
|
|
877
1321
|
} catch (error) {
|
|
878
|
-
(
|
|
1322
|
+
(_a3 = this.logger) == null ? void 0 : _a3.debug("[session] poll error", error);
|
|
879
1323
|
this.emit("error", { error });
|
|
880
1324
|
}
|
|
881
1325
|
}
|
|
@@ -883,7 +1327,7 @@ var Session = class extends TypedEventEmitter {
|
|
|
883
1327
|
// Internal — State Application
|
|
884
1328
|
// ===========================================================================
|
|
885
1329
|
applyState(state) {
|
|
886
|
-
var
|
|
1330
|
+
var _a3;
|
|
887
1331
|
if (state.messages) {
|
|
888
1332
|
this._messages = state.messages;
|
|
889
1333
|
this.emit("messages", this._messages);
|
|
@@ -891,12 +1335,12 @@ var Session = class extends TypedEventEmitter {
|
|
|
891
1335
|
if (state.title) {
|
|
892
1336
|
this._title = state.title;
|
|
893
1337
|
}
|
|
894
|
-
if ((
|
|
1338
|
+
if ((_a3 = state.system_events) == null ? void 0 : _a3.length) {
|
|
895
1339
|
this.dispatchSystemEvents(state.system_events);
|
|
896
1340
|
}
|
|
897
1341
|
}
|
|
898
1342
|
dispatchSystemEvents(events) {
|
|
899
|
-
var
|
|
1343
|
+
var _a3;
|
|
900
1344
|
for (const event of events) {
|
|
901
1345
|
const unwrapped = unwrapSystemEvent(event);
|
|
902
1346
|
if (!unwrapped) continue;
|
|
@@ -907,7 +1351,7 @@ var Session = class extends TypedEventEmitter {
|
|
|
907
1351
|
this.emit("wallet_tx_request", req);
|
|
908
1352
|
}
|
|
909
1353
|
} else if (unwrapped.type === "wallet_eip712_request") {
|
|
910
|
-
const payload = normalizeEip712Payload((
|
|
1354
|
+
const payload = normalizeEip712Payload((_a3 = unwrapped.payload) != null ? _a3 : {});
|
|
911
1355
|
const req = this.enqueueWalletRequest("eip712_sign", payload);
|
|
912
1356
|
this.emit("wallet_eip712_request", req);
|
|
913
1357
|
} else if (unwrapped.type === "system_notice" || unwrapped.type === "system_error" || unwrapped.type === "async_callback") {
|
|
@@ -970,69 +1414,78 @@ var Session = class extends TypedEventEmitter {
|
|
|
970
1414
|
}
|
|
971
1415
|
};
|
|
972
1416
|
|
|
973
|
-
// src/cli
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
if (
|
|
997
|
-
|
|
1417
|
+
// src/cli/context.ts
|
|
1418
|
+
function getOrCreateSession(runtime) {
|
|
1419
|
+
const { config } = runtime;
|
|
1420
|
+
let state = readState();
|
|
1421
|
+
if (!state) {
|
|
1422
|
+
state = {
|
|
1423
|
+
sessionId: crypto.randomUUID(),
|
|
1424
|
+
baseUrl: config.baseUrl,
|
|
1425
|
+
namespace: config.namespace,
|
|
1426
|
+
apiKey: config.apiKey,
|
|
1427
|
+
publicKey: config.publicKey
|
|
1428
|
+
};
|
|
1429
|
+
writeState(state);
|
|
1430
|
+
} else {
|
|
1431
|
+
let changed = false;
|
|
1432
|
+
if (config.baseUrl !== state.baseUrl) {
|
|
1433
|
+
state.baseUrl = config.baseUrl;
|
|
1434
|
+
changed = true;
|
|
1435
|
+
}
|
|
1436
|
+
if (config.namespace !== state.namespace) {
|
|
1437
|
+
state.namespace = config.namespace;
|
|
1438
|
+
changed = true;
|
|
1439
|
+
}
|
|
1440
|
+
if (config.apiKey !== void 0 && config.apiKey !== state.apiKey) {
|
|
1441
|
+
state.apiKey = config.apiKey;
|
|
1442
|
+
changed = true;
|
|
1443
|
+
}
|
|
1444
|
+
if (config.publicKey !== void 0 && config.publicKey !== state.publicKey) {
|
|
1445
|
+
state.publicKey = config.publicKey;
|
|
1446
|
+
changed = true;
|
|
1447
|
+
}
|
|
1448
|
+
if (changed) writeState(state);
|
|
998
1449
|
}
|
|
1450
|
+
const session = new Session(
|
|
1451
|
+
{ baseUrl: state.baseUrl, apiKey: state.apiKey },
|
|
1452
|
+
{
|
|
1453
|
+
sessionId: state.sessionId,
|
|
1454
|
+
namespace: state.namespace,
|
|
1455
|
+
apiKey: state.apiKey,
|
|
1456
|
+
publicKey: state.publicKey,
|
|
1457
|
+
userState: state.publicKey ? {
|
|
1458
|
+
address: state.publicKey,
|
|
1459
|
+
chainId: 1,
|
|
1460
|
+
isConnected: true
|
|
1461
|
+
} : void 0
|
|
1462
|
+
}
|
|
1463
|
+
);
|
|
1464
|
+
return { session, state };
|
|
999
1465
|
}
|
|
1000
|
-
function
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
...(_b = state.signedTxs) != null ? _b : []
|
|
1005
|
-
].map((t) => {
|
|
1006
|
-
const m = t.id.match(/^tx-(\d+)$/);
|
|
1007
|
-
return m ? parseInt(m[1], 10) : 0;
|
|
1466
|
+
function createControlClient(runtime) {
|
|
1467
|
+
return new AomiClient({
|
|
1468
|
+
baseUrl: runtime.config.baseUrl,
|
|
1469
|
+
apiKey: runtime.config.apiKey
|
|
1008
1470
|
});
|
|
1009
|
-
const max = allIds.length > 0 ? Math.max(...allIds) : 0;
|
|
1010
|
-
return `tx-${max + 1}`;
|
|
1011
1471
|
}
|
|
1012
|
-
function
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1472
|
+
async function applyModelSelection(session, state, model) {
|
|
1473
|
+
await session.client.setModel(state.sessionId, model, {
|
|
1474
|
+
namespace: state.namespace,
|
|
1475
|
+
apiKey: state.apiKey
|
|
1016
1476
|
});
|
|
1017
|
-
state.
|
|
1477
|
+
state.model = model;
|
|
1018
1478
|
writeState(state);
|
|
1019
|
-
return pending;
|
|
1020
1479
|
}
|
|
1021
|
-
function
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
return removed;
|
|
1028
|
-
}
|
|
1029
|
-
function addSignedTx(state, tx) {
|
|
1030
|
-
if (!state.signedTxs) state.signedTxs = [];
|
|
1031
|
-
state.signedTxs.push(tx);
|
|
1032
|
-
writeState(state);
|
|
1480
|
+
async function applyRequestedModelIfPresent(runtime, session, state) {
|
|
1481
|
+
const requestedModel = runtime.config.model;
|
|
1482
|
+
if (!requestedModel || requestedModel === state.model) {
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
await applyModelSelection(session, state, requestedModel);
|
|
1033
1486
|
}
|
|
1034
1487
|
|
|
1035
|
-
// src/cli.ts
|
|
1488
|
+
// src/cli/errors.ts
|
|
1036
1489
|
var CliExit = class extends Error {
|
|
1037
1490
|
constructor(code) {
|
|
1038
1491
|
super();
|
|
@@ -1040,217 +1493,108 @@ var CliExit = class extends Error {
|
|
|
1040
1493
|
}
|
|
1041
1494
|
};
|
|
1042
1495
|
function fatal(message) {
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
for (let i = 0; i < rest.length; i++) {
|
|
1056
|
-
const arg = rest[i];
|
|
1057
|
-
if (arg.startsWith("--") && arg.includes("=")) {
|
|
1058
|
-
const [key, ...val] = arg.slice(2).split("=");
|
|
1059
|
-
flags[key] = val.join("=");
|
|
1060
|
-
} else if (arg.startsWith("--")) {
|
|
1061
|
-
const key = arg.slice(2);
|
|
1062
|
-
const next = rest[i + 1];
|
|
1063
|
-
if (next && !next.startsWith("-")) {
|
|
1064
|
-
flags[key] = next;
|
|
1065
|
-
i++;
|
|
1066
|
-
} else {
|
|
1067
|
-
flags[key] = "true";
|
|
1068
|
-
}
|
|
1069
|
-
} else if (arg.startsWith("-") && arg.length === 2) {
|
|
1070
|
-
flags[arg.slice(1)] = "true";
|
|
1071
|
-
} else {
|
|
1072
|
-
positional.push(arg);
|
|
1073
|
-
}
|
|
1496
|
+
const RED = "\x1B[31m";
|
|
1497
|
+
const DIM3 = "\x1B[2m";
|
|
1498
|
+
const RESET3 = "\x1B[0m";
|
|
1499
|
+
const lines = message.split("\n");
|
|
1500
|
+
const [headline, ...details] = lines;
|
|
1501
|
+
console.error(`${RED}\u274C ${headline}${RESET3}`);
|
|
1502
|
+
for (const detail of details) {
|
|
1503
|
+
if (!detail.trim()) {
|
|
1504
|
+
console.error("");
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1507
|
+
console.error(`${DIM3}${detail}${RESET3}`);
|
|
1074
1508
|
}
|
|
1075
|
-
|
|
1076
|
-
}
|
|
1077
|
-
var parsed = parseArgs(process.argv);
|
|
1078
|
-
function getConfig() {
|
|
1079
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
1080
|
-
return {
|
|
1081
|
-
baseUrl: (_b = (_a2 = parsed.flags["backend-url"]) != null ? _a2 : process.env.AOMI_BASE_URL) != null ? _b : "https://api.aomi.dev",
|
|
1082
|
-
apiKey: (_c = parsed.flags["api-key"]) != null ? _c : process.env.AOMI_API_KEY,
|
|
1083
|
-
namespace: (_e = (_d = parsed.flags["namespace"]) != null ? _d : process.env.AOMI_NAMESPACE) != null ? _e : "default",
|
|
1084
|
-
publicKey: (_f = parsed.flags["public-key"]) != null ? _f : process.env.AOMI_PUBLIC_KEY,
|
|
1085
|
-
privateKey: (_g = parsed.flags["private-key"]) != null ? _g : process.env.PRIVATE_KEY,
|
|
1086
|
-
chainRpcUrl: (_h = parsed.flags["rpc-url"]) != null ? _h : process.env.CHAIN_RPC_URL
|
|
1087
|
-
};
|
|
1088
|
-
}
|
|
1089
|
-
function getOrCreateSession() {
|
|
1090
|
-
const config = getConfig();
|
|
1091
|
-
let state = readState();
|
|
1092
|
-
if (!state) {
|
|
1093
|
-
state = {
|
|
1094
|
-
sessionId: crypto.randomUUID(),
|
|
1095
|
-
baseUrl: config.baseUrl,
|
|
1096
|
-
namespace: config.namespace,
|
|
1097
|
-
apiKey: config.apiKey,
|
|
1098
|
-
publicKey: config.publicKey
|
|
1099
|
-
};
|
|
1100
|
-
writeState(state);
|
|
1101
|
-
} else {
|
|
1102
|
-
let changed = false;
|
|
1103
|
-
if (config.baseUrl && config.baseUrl !== state.baseUrl) {
|
|
1104
|
-
state.baseUrl = config.baseUrl;
|
|
1105
|
-
changed = true;
|
|
1106
|
-
}
|
|
1107
|
-
if (config.namespace && config.namespace !== state.namespace) {
|
|
1108
|
-
state.namespace = config.namespace;
|
|
1109
|
-
changed = true;
|
|
1110
|
-
}
|
|
1111
|
-
if (config.apiKey !== void 0 && config.apiKey !== state.apiKey) {
|
|
1112
|
-
state.apiKey = config.apiKey;
|
|
1113
|
-
changed = true;
|
|
1114
|
-
}
|
|
1115
|
-
if (config.publicKey !== void 0 && config.publicKey !== state.publicKey) {
|
|
1116
|
-
state.publicKey = config.publicKey;
|
|
1117
|
-
changed = true;
|
|
1118
|
-
}
|
|
1119
|
-
if (changed) writeState(state);
|
|
1120
|
-
}
|
|
1121
|
-
const session = new Session(
|
|
1122
|
-
{ baseUrl: state.baseUrl, apiKey: state.apiKey },
|
|
1123
|
-
{
|
|
1124
|
-
sessionId: state.sessionId,
|
|
1125
|
-
namespace: state.namespace,
|
|
1126
|
-
apiKey: state.apiKey,
|
|
1127
|
-
publicKey: state.publicKey,
|
|
1128
|
-
userState: state.publicKey ? {
|
|
1129
|
-
address: state.publicKey,
|
|
1130
|
-
chainId: 1,
|
|
1131
|
-
isConnected: true
|
|
1132
|
-
} : void 0
|
|
1133
|
-
}
|
|
1134
|
-
);
|
|
1135
|
-
return { session, state };
|
|
1509
|
+
throw new CliExit(1);
|
|
1136
1510
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1511
|
+
|
|
1512
|
+
// src/cli/transactions.ts
|
|
1513
|
+
function walletRequestToPendingTx(request) {
|
|
1514
|
+
if (request.kind === "transaction") {
|
|
1515
|
+
const payload2 = request.payload;
|
|
1140
1516
|
return {
|
|
1141
1517
|
kind: "transaction",
|
|
1142
|
-
to:
|
|
1143
|
-
value:
|
|
1144
|
-
data:
|
|
1145
|
-
chainId:
|
|
1146
|
-
timestamp:
|
|
1147
|
-
payload:
|
|
1518
|
+
to: payload2.to,
|
|
1519
|
+
value: payload2.value,
|
|
1520
|
+
data: payload2.data,
|
|
1521
|
+
chainId: payload2.chainId,
|
|
1522
|
+
timestamp: request.timestamp,
|
|
1523
|
+
payload: request.payload
|
|
1148
1524
|
};
|
|
1149
1525
|
}
|
|
1150
|
-
const
|
|
1526
|
+
const payload = request.payload;
|
|
1151
1527
|
return {
|
|
1152
1528
|
kind: "eip712_sign",
|
|
1153
|
-
description:
|
|
1154
|
-
timestamp:
|
|
1155
|
-
payload:
|
|
1529
|
+
description: payload.description,
|
|
1530
|
+
timestamp: request.timestamp,
|
|
1531
|
+
payload: request.payload
|
|
1156
1532
|
};
|
|
1157
1533
|
}
|
|
1158
1534
|
function formatTxLine(tx, prefix) {
|
|
1159
|
-
var
|
|
1535
|
+
var _a3;
|
|
1160
1536
|
const parts = [`${prefix} ${tx.id}`];
|
|
1161
1537
|
if (tx.kind === "transaction") {
|
|
1162
|
-
parts.push(`to: ${(
|
|
1538
|
+
parts.push(`to: ${(_a3 = tx.to) != null ? _a3 : "?"}`);
|
|
1163
1539
|
if (tx.value) parts.push(`value: ${tx.value}`);
|
|
1164
1540
|
if (tx.chainId) parts.push(`chain: ${tx.chainId}`);
|
|
1165
1541
|
if (tx.data) parts.push(`data: ${tx.data.slice(0, 20)}...`);
|
|
1166
1542
|
} else {
|
|
1167
|
-
parts.push(
|
|
1543
|
+
parts.push("eip712");
|
|
1168
1544
|
if (tx.description) parts.push(tx.description);
|
|
1169
1545
|
}
|
|
1170
1546
|
parts.push(`(${new Date(tx.timestamp).toLocaleTimeString()})`);
|
|
1171
1547
|
return parts.join(" ");
|
|
1172
1548
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
var RESET = "\x1B[0m";
|
|
1178
|
-
function printToolUpdate(event) {
|
|
1179
|
-
var _a2, _b, _c;
|
|
1180
|
-
const name = (_b = (_a2 = event.tool_name) != null ? _a2 : event.name) != null ? _b : "unknown";
|
|
1181
|
-
const status = (_c = event.status) != null ? _c : "running";
|
|
1182
|
-
console.log(`${DIM}\u{1F527} [tool] ${name}: ${status}${RESET}`);
|
|
1183
|
-
}
|
|
1184
|
-
function printToolComplete(event) {
|
|
1185
|
-
var _a2, _b, _c;
|
|
1186
|
-
const name = (_b = (_a2 = event.tool_name) != null ? _a2 : event.name) != null ? _b : "unknown";
|
|
1187
|
-
const result = (_c = event.result) != null ? _c : event.output;
|
|
1188
|
-
const line = result ? `${GREEN}\u2714 [tool] ${name} \u2192 ${result.slice(0, 120)}${result.length > 120 ? "\u2026" : ""}${RESET}` : `${GREEN}\u2714 [tool] ${name} done${RESET}`;
|
|
1189
|
-
console.log(line);
|
|
1190
|
-
}
|
|
1191
|
-
function printNewAgentMessages(messages, lastPrintedCount) {
|
|
1192
|
-
const agentMessages = messages.filter(
|
|
1193
|
-
(m) => m.sender === "agent" || m.sender === "assistant"
|
|
1194
|
-
);
|
|
1195
|
-
let handled = lastPrintedCount;
|
|
1196
|
-
for (let i = lastPrintedCount; i < agentMessages.length; i++) {
|
|
1197
|
-
const msg = agentMessages[i];
|
|
1198
|
-
if (msg.is_streaming) {
|
|
1199
|
-
break;
|
|
1200
|
-
}
|
|
1201
|
-
if (msg.content) {
|
|
1202
|
-
console.log(`${CYAN}\u{1F916} ${msg.content}${RESET}`);
|
|
1203
|
-
}
|
|
1204
|
-
handled = i + 1;
|
|
1205
|
-
}
|
|
1206
|
-
return handled;
|
|
1207
|
-
}
|
|
1208
|
-
async function chatCommand() {
|
|
1209
|
-
const message = parsed.positional.join(" ");
|
|
1549
|
+
|
|
1550
|
+
// src/cli/commands/chat.ts
|
|
1551
|
+
async function chatCommand(runtime) {
|
|
1552
|
+
const message = runtime.parsed.positional.join(" ");
|
|
1210
1553
|
if (!message) {
|
|
1211
1554
|
fatal("Usage: aomi chat <message>");
|
|
1212
1555
|
}
|
|
1213
|
-
const verbose = parsed.flags["verbose"] === "true" || parsed.flags["v"] === "true";
|
|
1214
|
-
const { session, state } = getOrCreateSession();
|
|
1215
|
-
if (state.publicKey) {
|
|
1216
|
-
await session.client.sendSystemMessage(
|
|
1217
|
-
session.sessionId,
|
|
1218
|
-
JSON.stringify({
|
|
1219
|
-
type: "wallet:state_changed",
|
|
1220
|
-
payload: {
|
|
1221
|
-
address: state.publicKey,
|
|
1222
|
-
chainId: 1,
|
|
1223
|
-
isConnected: true
|
|
1224
|
-
}
|
|
1225
|
-
})
|
|
1226
|
-
);
|
|
1227
|
-
}
|
|
1228
|
-
const capturedRequests = [];
|
|
1229
|
-
let printedAgentCount = 0;
|
|
1230
|
-
session.on("wallet_tx_request", (req) => capturedRequests.push(req));
|
|
1231
|
-
session.on("wallet_eip712_request", (req) => capturedRequests.push(req));
|
|
1556
|
+
const verbose = runtime.parsed.flags["verbose"] === "true" || runtime.parsed.flags["v"] === "true";
|
|
1557
|
+
const { session, state } = getOrCreateSession(runtime);
|
|
1232
1558
|
try {
|
|
1233
|
-
await session
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1559
|
+
await applyRequestedModelIfPresent(runtime, session, state);
|
|
1560
|
+
if (state.publicKey) {
|
|
1561
|
+
await session.client.sendSystemMessage(
|
|
1562
|
+
session.sessionId,
|
|
1563
|
+
JSON.stringify({
|
|
1564
|
+
type: "wallet:state_changed",
|
|
1565
|
+
payload: {
|
|
1566
|
+
address: state.publicKey,
|
|
1567
|
+
chainId: 1,
|
|
1568
|
+
isConnected: true
|
|
1569
|
+
}
|
|
1570
|
+
})
|
|
1571
|
+
);
|
|
1241
1572
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
)
|
|
1573
|
+
const capturedRequests = [];
|
|
1574
|
+
let printedAgentCount = 0;
|
|
1575
|
+
const seenToolResults = /* @__PURE__ */ new Set();
|
|
1576
|
+
session.on("wallet_tx_request", (request) => capturedRequests.push(request));
|
|
1577
|
+
session.on(
|
|
1578
|
+
"wallet_eip712_request",
|
|
1579
|
+
(request) => capturedRequests.push(request)
|
|
1580
|
+
);
|
|
1581
|
+
session.on("tool_complete", (event) => {
|
|
1582
|
+
const name = getToolNameFromEvent(event);
|
|
1583
|
+
const result = getToolResultFromEvent(event);
|
|
1584
|
+
const key = toToolResultKey(name, result);
|
|
1585
|
+
seenToolResults.add(key);
|
|
1586
|
+
if (verbose || isAlwaysVisibleTool(name)) {
|
|
1587
|
+
printToolComplete(event);
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1590
|
+
session.on("tool_update", (event) => {
|
|
1591
|
+
if (verbose) {
|
|
1592
|
+
printToolUpdate(event);
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1245
1595
|
if (verbose) {
|
|
1246
|
-
|
|
1596
|
+
session.on("processing_start", () => {
|
|
1247
1597
|
console.log(`${DIM}\u23F3 Processing\u2026${RESET}`);
|
|
1248
|
-
}
|
|
1249
|
-
printedAgentCount = printNewAgentMessages(allMsgs, printedAgentCount);
|
|
1250
|
-
session.on("tool_update", (event) => printToolUpdate(event));
|
|
1251
|
-
session.on("tool_complete", (event) => printToolComplete(event));
|
|
1252
|
-
session.on("messages", (msgs) => {
|
|
1253
|
-
printedAgentCount = printNewAgentMessages(msgs, printedAgentCount);
|
|
1254
1598
|
});
|
|
1255
1599
|
session.on("system_notice", ({ message: msg }) => {
|
|
1256
1600
|
console.log(`${YELLOW}\u{1F4E2} ${msg}${RESET}`);
|
|
@@ -1259,6 +1603,27 @@ async function chatCommand() {
|
|
|
1259
1603
|
console.log(`\x1B[31m\u274C ${msg}${RESET}`);
|
|
1260
1604
|
});
|
|
1261
1605
|
}
|
|
1606
|
+
await session.sendAsync(message);
|
|
1607
|
+
const allMessages = session.getMessages();
|
|
1608
|
+
let seedIdx = allMessages.length;
|
|
1609
|
+
for (let i = allMessages.length - 1; i >= 0; i--) {
|
|
1610
|
+
if (allMessages[i].sender === "user") {
|
|
1611
|
+
seedIdx = i;
|
|
1612
|
+
break;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
printedAgentCount = allMessages.slice(0, seedIdx).filter(
|
|
1616
|
+
(entry) => entry.sender === "agent" || entry.sender === "assistant"
|
|
1617
|
+
).length;
|
|
1618
|
+
if (verbose) {
|
|
1619
|
+
printedAgentCount = printNewAgentMessages(
|
|
1620
|
+
allMessages,
|
|
1621
|
+
printedAgentCount
|
|
1622
|
+
);
|
|
1623
|
+
session.on("messages", (messages) => {
|
|
1624
|
+
printedAgentCount = printNewAgentMessages(messages, printedAgentCount);
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1262
1627
|
if (session.getIsProcessing()) {
|
|
1263
1628
|
await new Promise((resolve) => {
|
|
1264
1629
|
const checkWallet = () => {
|
|
@@ -1269,27 +1634,54 @@ async function chatCommand() {
|
|
|
1269
1634
|
session.on("processing_end", () => resolve());
|
|
1270
1635
|
});
|
|
1271
1636
|
}
|
|
1637
|
+
const messageToolResults = getMessageToolResults(
|
|
1638
|
+
session.getMessages(),
|
|
1639
|
+
seedIdx + 1
|
|
1640
|
+
);
|
|
1272
1641
|
if (verbose) {
|
|
1273
|
-
|
|
1642
|
+
for (const tool of messageToolResults) {
|
|
1643
|
+
const key = toToolResultKey(tool.name, tool.result);
|
|
1644
|
+
if (seenToolResults.has(key)) {
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
printToolResultLine(tool.name, tool.result);
|
|
1648
|
+
}
|
|
1649
|
+
} else {
|
|
1650
|
+
for (const tool of messageToolResults) {
|
|
1651
|
+
const key = toToolResultKey(tool.name, tool.result);
|
|
1652
|
+
if (seenToolResults.has(key)) {
|
|
1653
|
+
continue;
|
|
1654
|
+
}
|
|
1655
|
+
if (isAlwaysVisibleTool(tool.name)) {
|
|
1656
|
+
printToolResultLine(tool.name, tool.result);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
if (verbose) {
|
|
1661
|
+
printedAgentCount = printNewAgentMessages(
|
|
1662
|
+
session.getMessages(),
|
|
1663
|
+
printedAgentCount
|
|
1664
|
+
);
|
|
1274
1665
|
console.log(`${DIM}\u2705 Done${RESET}`);
|
|
1275
1666
|
}
|
|
1276
|
-
for (const
|
|
1277
|
-
const pending = addPendingTx(state, walletRequestToPendingTx(
|
|
1667
|
+
for (const request of capturedRequests) {
|
|
1668
|
+
const pending = addPendingTx(state, walletRequestToPendingTx(request));
|
|
1278
1669
|
console.log(`\u26A1 Wallet request queued: ${pending.id}`);
|
|
1279
|
-
if (
|
|
1280
|
-
const
|
|
1281
|
-
console.log(` to: ${
|
|
1282
|
-
if (
|
|
1283
|
-
if (
|
|
1670
|
+
if (request.kind === "transaction") {
|
|
1671
|
+
const payload = request.payload;
|
|
1672
|
+
console.log(` to: ${payload.to}`);
|
|
1673
|
+
if (payload.value) console.log(` value: ${payload.value}`);
|
|
1674
|
+
if (payload.chainId) console.log(` chain: ${payload.chainId}`);
|
|
1284
1675
|
} else {
|
|
1285
|
-
const
|
|
1286
|
-
if (
|
|
1676
|
+
const payload = request.payload;
|
|
1677
|
+
if (payload.description) {
|
|
1678
|
+
console.log(` desc: ${payload.description}`);
|
|
1679
|
+
}
|
|
1287
1680
|
}
|
|
1288
1681
|
}
|
|
1289
1682
|
if (!verbose) {
|
|
1290
|
-
const
|
|
1291
|
-
|
|
1292
|
-
(m) => m.sender === "agent" || m.sender === "assistant"
|
|
1683
|
+
const agentMessages = session.getMessages().filter(
|
|
1684
|
+
(entry) => entry.sender === "agent" || entry.sender === "assistant"
|
|
1293
1685
|
);
|
|
1294
1686
|
const last = agentMessages[agentMessages.length - 1];
|
|
1295
1687
|
if (last == null ? void 0 : last.content) {
|
|
@@ -1299,22 +1691,24 @@ async function chatCommand() {
|
|
|
1299
1691
|
}
|
|
1300
1692
|
}
|
|
1301
1693
|
if (capturedRequests.length > 0) {
|
|
1302
|
-
console.log(
|
|
1303
|
-
|
|
1694
|
+
console.log(
|
|
1695
|
+
"\nRun `aomi tx` to see pending transactions, `aomi sign <id>` to sign."
|
|
1696
|
+
);
|
|
1304
1697
|
}
|
|
1305
1698
|
} finally {
|
|
1306
1699
|
session.close();
|
|
1307
1700
|
}
|
|
1308
1701
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1702
|
+
|
|
1703
|
+
// src/cli/commands/control.ts
|
|
1704
|
+
async function statusCommand(runtime) {
|
|
1705
|
+
var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1706
|
+
if (!readState()) {
|
|
1313
1707
|
console.log("No active session");
|
|
1314
1708
|
printDataFileLocation();
|
|
1315
1709
|
return;
|
|
1316
1710
|
}
|
|
1317
|
-
const { session } = getOrCreateSession();
|
|
1711
|
+
const { session, state } = getOrCreateSession(runtime);
|
|
1318
1712
|
try {
|
|
1319
1713
|
const apiState = await session.client.fetchState(state.sessionId);
|
|
1320
1714
|
console.log(
|
|
@@ -1323,11 +1717,12 @@ async function statusCommand() {
|
|
|
1323
1717
|
sessionId: state.sessionId,
|
|
1324
1718
|
baseUrl: state.baseUrl,
|
|
1325
1719
|
namespace: state.namespace,
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1720
|
+
model: (_a3 = state.model) != null ? _a3 : null,
|
|
1721
|
+
isProcessing: (_b = apiState.is_processing) != null ? _b : false,
|
|
1722
|
+
messageCount: (_d = (_c = apiState.messages) == null ? void 0 : _c.length) != null ? _d : 0,
|
|
1723
|
+
title: (_e = apiState.title) != null ? _e : null,
|
|
1724
|
+
pendingTxs: (_g = (_f = state.pendingTxs) == null ? void 0 : _f.length) != null ? _g : 0,
|
|
1725
|
+
signedTxs: (_i = (_h = state.signedTxs) == null ? void 0 : _h.length) != null ? _i : 0
|
|
1331
1726
|
},
|
|
1332
1727
|
null,
|
|
1333
1728
|
2
|
|
@@ -1338,13 +1733,12 @@ async function statusCommand() {
|
|
|
1338
1733
|
session.close();
|
|
1339
1734
|
}
|
|
1340
1735
|
}
|
|
1341
|
-
async function eventsCommand() {
|
|
1342
|
-
|
|
1343
|
-
if (!state) {
|
|
1736
|
+
async function eventsCommand(runtime) {
|
|
1737
|
+
if (!readState()) {
|
|
1344
1738
|
console.log("No active session");
|
|
1345
1739
|
return;
|
|
1346
1740
|
}
|
|
1347
|
-
const { session } = getOrCreateSession();
|
|
1741
|
+
const { session, state } = getOrCreateSession(runtime);
|
|
1348
1742
|
try {
|
|
1349
1743
|
const events = await session.client.getSystemEvents(state.sessionId);
|
|
1350
1744
|
console.log(JSON.stringify(events, null, 2));
|
|
@@ -1352,15 +1746,372 @@ async function eventsCommand() {
|
|
|
1352
1746
|
session.close();
|
|
1353
1747
|
}
|
|
1354
1748
|
}
|
|
1749
|
+
async function modelsCommand(runtime) {
|
|
1750
|
+
var _a3, _b;
|
|
1751
|
+
const client = createControlClient(runtime);
|
|
1752
|
+
const state = readState();
|
|
1753
|
+
const sessionId = (_a3 = state == null ? void 0 : state.sessionId) != null ? _a3 : crypto.randomUUID();
|
|
1754
|
+
const models = await client.getModels(sessionId, {
|
|
1755
|
+
apiKey: (_b = runtime.config.apiKey) != null ? _b : state == null ? void 0 : state.apiKey
|
|
1756
|
+
});
|
|
1757
|
+
if (models.length === 0) {
|
|
1758
|
+
console.log("No models available.");
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
for (const model of models) {
|
|
1762
|
+
const marker = (state == null ? void 0 : state.model) === model ? " (current)" : "";
|
|
1763
|
+
console.log(`${model}${marker}`);
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
async function modelCommand(runtime) {
|
|
1767
|
+
var _a3;
|
|
1768
|
+
const subcommand = runtime.parsed.positional[0];
|
|
1769
|
+
if (!subcommand || subcommand === "current") {
|
|
1770
|
+
const state2 = readState();
|
|
1771
|
+
if (!state2) {
|
|
1772
|
+
console.log("No active session");
|
|
1773
|
+
printDataFileLocation();
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
console.log((_a3 = state2.model) != null ? _a3 : "(default backend model)");
|
|
1777
|
+
printDataFileLocation();
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
if (subcommand !== "set") {
|
|
1781
|
+
fatal("Usage: aomi model set <rig>\n aomi model current");
|
|
1782
|
+
}
|
|
1783
|
+
const model = runtime.parsed.positional.slice(1).join(" ").trim();
|
|
1784
|
+
if (!model) {
|
|
1785
|
+
fatal("Usage: aomi model set <rig>");
|
|
1786
|
+
}
|
|
1787
|
+
const { session, state } = getOrCreateSession(runtime);
|
|
1788
|
+
try {
|
|
1789
|
+
await applyModelSelection(session, state, model);
|
|
1790
|
+
console.log(`Model set to ${model}`);
|
|
1791
|
+
printDataFileLocation();
|
|
1792
|
+
} finally {
|
|
1793
|
+
session.close();
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
// src/cli/tables.ts
|
|
1798
|
+
var MAX_TABLE_VALUE_WIDTH = 72;
|
|
1799
|
+
var MAX_TX_JSON_WIDTH = 96;
|
|
1800
|
+
var MAX_TX_ROWS = 8;
|
|
1801
|
+
function truncateCell(value, maxWidth) {
|
|
1802
|
+
if (value.length <= maxWidth) return value;
|
|
1803
|
+
return `${value.slice(0, maxWidth - 1)}\u2026`;
|
|
1804
|
+
}
|
|
1805
|
+
function padRight(value, width) {
|
|
1806
|
+
return value.padEnd(width, " ");
|
|
1807
|
+
}
|
|
1808
|
+
function estimateTokenCount(messages) {
|
|
1809
|
+
var _a3;
|
|
1810
|
+
let totalChars = 0;
|
|
1811
|
+
for (const message of messages) {
|
|
1812
|
+
const content = formatLogContent(message.content);
|
|
1813
|
+
if (content) {
|
|
1814
|
+
totalChars += content.length + 1;
|
|
1815
|
+
}
|
|
1816
|
+
if ((_a3 = message.tool_result) == null ? void 0 : _a3[1]) {
|
|
1817
|
+
totalChars += message.tool_result[1].length;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
return Math.round(totalChars / 4);
|
|
1821
|
+
}
|
|
1822
|
+
function toPendingTxMetadata(tx) {
|
|
1823
|
+
var _a3, _b, _c, _d;
|
|
1824
|
+
return {
|
|
1825
|
+
id: tx.id,
|
|
1826
|
+
kind: tx.kind,
|
|
1827
|
+
to: (_a3 = tx.to) != null ? _a3 : null,
|
|
1828
|
+
value: (_b = tx.value) != null ? _b : null,
|
|
1829
|
+
chainId: (_c = tx.chainId) != null ? _c : null,
|
|
1830
|
+
description: (_d = tx.description) != null ? _d : null,
|
|
1831
|
+
timestamp: new Date(tx.timestamp).toISOString()
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
function toSignedTxMetadata(tx) {
|
|
1835
|
+
var _a3, _b, _c, _d, _e, _f, _g;
|
|
1836
|
+
return {
|
|
1837
|
+
id: tx.id,
|
|
1838
|
+
kind: tx.kind,
|
|
1839
|
+
txHash: (_a3 = tx.txHash) != null ? _a3 : null,
|
|
1840
|
+
signature: (_b = tx.signature) != null ? _b : null,
|
|
1841
|
+
from: (_c = tx.from) != null ? _c : null,
|
|
1842
|
+
to: (_d = tx.to) != null ? _d : null,
|
|
1843
|
+
value: (_e = tx.value) != null ? _e : null,
|
|
1844
|
+
chainId: (_f = tx.chainId) != null ? _f : null,
|
|
1845
|
+
description: (_g = tx.description) != null ? _g : null,
|
|
1846
|
+
timestamp: new Date(tx.timestamp).toISOString()
|
|
1847
|
+
};
|
|
1848
|
+
}
|
|
1849
|
+
function printKeyValueTable(rows, color = CYAN) {
|
|
1850
|
+
const labels = rows.map(([label]) => label);
|
|
1851
|
+
const values = rows.map(
|
|
1852
|
+
([, value]) => truncateCell(value, MAX_TABLE_VALUE_WIDTH)
|
|
1853
|
+
);
|
|
1854
|
+
const keyWidth = Math.max("field".length, ...labels.map((label) => label.length));
|
|
1855
|
+
const valueWidth = Math.max("value".length, ...values.map((value) => value.length));
|
|
1856
|
+
const border = `+${"-".repeat(keyWidth + 2)}+${"-".repeat(valueWidth + 2)}+`;
|
|
1857
|
+
console.log(`${color}${border}${RESET}`);
|
|
1858
|
+
console.log(
|
|
1859
|
+
`${color}| ${padRight("field", keyWidth)} | ${padRight("value", valueWidth)} |${RESET}`
|
|
1860
|
+
);
|
|
1861
|
+
console.log(`${color}${border}${RESET}`);
|
|
1862
|
+
for (let i = 0; i < rows.length; i++) {
|
|
1863
|
+
console.log(
|
|
1864
|
+
`${color}| ${padRight(labels[i], keyWidth)} | ${padRight(values[i], valueWidth)} |${RESET}`
|
|
1865
|
+
);
|
|
1866
|
+
console.log(`${color}${border}${RESET}`);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
function printTransactionTable(pendingTxs, signedTxs, color = GREEN) {
|
|
1870
|
+
const rows = [
|
|
1871
|
+
...pendingTxs.map((tx) => ({
|
|
1872
|
+
status: "pending",
|
|
1873
|
+
metadata: toPendingTxMetadata(tx)
|
|
1874
|
+
})),
|
|
1875
|
+
...signedTxs.map((tx) => ({
|
|
1876
|
+
status: "signed",
|
|
1877
|
+
metadata: toSignedTxMetadata(tx)
|
|
1878
|
+
}))
|
|
1879
|
+
];
|
|
1880
|
+
if (rows.length === 0) {
|
|
1881
|
+
console.log(`${YELLOW}No transactions in local CLI state.${RESET}`);
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
const visibleRows = rows.slice(0, MAX_TX_ROWS);
|
|
1885
|
+
const statusWidth = Math.max(
|
|
1886
|
+
"status".length,
|
|
1887
|
+
...visibleRows.map((row) => row.status.length)
|
|
1888
|
+
);
|
|
1889
|
+
const jsonCells = visibleRows.map(
|
|
1890
|
+
(row) => truncateCell(JSON.stringify(row.metadata), MAX_TX_JSON_WIDTH)
|
|
1891
|
+
);
|
|
1892
|
+
const jsonWidth = Math.max("metadata_json".length, ...jsonCells.map((v) => v.length));
|
|
1893
|
+
const border = `+${"-".repeat(statusWidth + 2)}+${"-".repeat(jsonWidth + 2)}+`;
|
|
1894
|
+
console.log(`${color}${border}${RESET}`);
|
|
1895
|
+
console.log(
|
|
1896
|
+
`${color}| ${padRight("status", statusWidth)} | ${padRight("metadata_json", jsonWidth)} |${RESET}`
|
|
1897
|
+
);
|
|
1898
|
+
console.log(`${color}${border}${RESET}`);
|
|
1899
|
+
for (let i = 0; i < visibleRows.length; i++) {
|
|
1900
|
+
console.log(
|
|
1901
|
+
`${color}| ${padRight(visibleRows[i].status, statusWidth)} | ${padRight(jsonCells[i], jsonWidth)} |${RESET}`
|
|
1902
|
+
);
|
|
1903
|
+
console.log(`${color}${border}${RESET}`);
|
|
1904
|
+
}
|
|
1905
|
+
if (rows.length > MAX_TX_ROWS) {
|
|
1906
|
+
const omitted = rows.length - MAX_TX_ROWS;
|
|
1907
|
+
console.log(`${DIM}${omitted} transaction rows omitted${RESET}`);
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
// src/cli/commands/history.ts
|
|
1912
|
+
async function logCommand(runtime) {
|
|
1913
|
+
var _a3, _b, _c, _d, _e;
|
|
1914
|
+
if (!readState()) {
|
|
1915
|
+
console.log("No active session");
|
|
1916
|
+
printDataFileLocation();
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
const { session, state } = getOrCreateSession(runtime);
|
|
1920
|
+
try {
|
|
1921
|
+
const apiState = await session.client.fetchState(state.sessionId);
|
|
1922
|
+
const messages = (_a3 = apiState.messages) != null ? _a3 : [];
|
|
1923
|
+
const pendingTxs = (_b = state.pendingTxs) != null ? _b : [];
|
|
1924
|
+
const signedTxs = (_c = state.signedTxs) != null ? _c : [];
|
|
1925
|
+
const toolCalls = messages.filter((msg) => Boolean(msg.tool_result)).length;
|
|
1926
|
+
const tokenCountEstimate = estimateTokenCount(messages);
|
|
1927
|
+
const topic = (_d = apiState.title) != null ? _d : "Untitled Session";
|
|
1928
|
+
if (messages.length === 0) {
|
|
1929
|
+
console.log("No messages in this session.");
|
|
1930
|
+
printDataFileLocation();
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
console.log(`------ Session id: ${state.sessionId} ------`);
|
|
1934
|
+
printKeyValueTable([
|
|
1935
|
+
["topic", topic],
|
|
1936
|
+
["msg count", String(messages.length)],
|
|
1937
|
+
["token count", `${tokenCountEstimate} (estimated)`],
|
|
1938
|
+
["tool calls", String(toolCalls)],
|
|
1939
|
+
[
|
|
1940
|
+
"transactions",
|
|
1941
|
+
`${pendingTxs.length + signedTxs.length} (${pendingTxs.length} pending, ${signedTxs.length} signed)`
|
|
1942
|
+
]
|
|
1943
|
+
]);
|
|
1944
|
+
console.log("Transactions metadata (JSON):");
|
|
1945
|
+
printTransactionTable(pendingTxs, signedTxs);
|
|
1946
|
+
console.log("-------------------- Messages --------------------");
|
|
1947
|
+
for (const msg of messages) {
|
|
1948
|
+
const content = formatLogContent(msg.content);
|
|
1949
|
+
let time = "";
|
|
1950
|
+
if (msg.timestamp) {
|
|
1951
|
+
const raw = msg.timestamp;
|
|
1952
|
+
const numeric = /^\d+$/.test(raw) ? parseInt(raw, 10) : NaN;
|
|
1953
|
+
const date = !Number.isNaN(numeric) ? new Date(numeric < 1e12 ? numeric * 1e3 : numeric) : new Date(raw);
|
|
1954
|
+
time = Number.isNaN(date.getTime()) ? "" : `${DIM}${date.toLocaleTimeString()}${RESET} `;
|
|
1955
|
+
}
|
|
1956
|
+
const sender = (_e = msg.sender) != null ? _e : "unknown";
|
|
1957
|
+
if (sender === "user") {
|
|
1958
|
+
if (content) {
|
|
1959
|
+
console.log(`${time}${CYAN}\u{1F464} You:${RESET} ${content}`);
|
|
1960
|
+
}
|
|
1961
|
+
} else if (sender === "agent" || sender === "assistant") {
|
|
1962
|
+
if (msg.tool_result) {
|
|
1963
|
+
const [toolName, result] = msg.tool_result;
|
|
1964
|
+
console.log(
|
|
1965
|
+
`${time}${GREEN}\u{1F527} [${toolName}]${RESET} ${formatToolResultPreview(result)}`
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
if (content) {
|
|
1969
|
+
console.log(`${time}${CYAN}\u{1F916} Agent:${RESET} ${content}`);
|
|
1970
|
+
}
|
|
1971
|
+
} else if (sender === "system") {
|
|
1972
|
+
if (content && !content.startsWith("Response of system endpoint:")) {
|
|
1973
|
+
console.log(`${time}${YELLOW}\u2699\uFE0F System:${RESET} ${content}`);
|
|
1974
|
+
}
|
|
1975
|
+
} else {
|
|
1976
|
+
if (content) {
|
|
1977
|
+
console.log(`${time}${DIM}[${sender}]${RESET} ${content}`);
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
console.log(`
|
|
1982
|
+
${DIM}\u2014 ${messages.length} messages \u2014${RESET}`);
|
|
1983
|
+
printDataFileLocation();
|
|
1984
|
+
} finally {
|
|
1985
|
+
session.close();
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
function closeCommand(runtime) {
|
|
1989
|
+
if (readState()) {
|
|
1990
|
+
const { session } = getOrCreateSession(runtime);
|
|
1991
|
+
session.close();
|
|
1992
|
+
}
|
|
1993
|
+
clearState();
|
|
1994
|
+
console.log("Session closed");
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
// src/cli/commands/sessions.ts
|
|
1998
|
+
async function fetchRemoteSessionStats(record) {
|
|
1999
|
+
var _a3, _b;
|
|
2000
|
+
const client = new AomiClient({
|
|
2001
|
+
baseUrl: record.state.baseUrl,
|
|
2002
|
+
apiKey: record.state.apiKey
|
|
2003
|
+
});
|
|
2004
|
+
try {
|
|
2005
|
+
const apiState = await client.fetchState(record.sessionId);
|
|
2006
|
+
const messages = (_a3 = apiState.messages) != null ? _a3 : [];
|
|
2007
|
+
return {
|
|
2008
|
+
topic: (_b = apiState.title) != null ? _b : "Untitled Session",
|
|
2009
|
+
messageCount: messages.length,
|
|
2010
|
+
tokenCountEstimate: estimateTokenCount(messages),
|
|
2011
|
+
toolCalls: messages.filter((msg) => Boolean(msg.tool_result)).length
|
|
2012
|
+
};
|
|
2013
|
+
} catch (e) {
|
|
2014
|
+
return null;
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
function printSessionSummary(record, stats, isActive) {
|
|
2018
|
+
var _a3, _b, _c;
|
|
2019
|
+
const pendingTxs = (_a3 = record.state.pendingTxs) != null ? _a3 : [];
|
|
2020
|
+
const signedTxs = (_b = record.state.signedTxs) != null ? _b : [];
|
|
2021
|
+
const header = isActive ? `\u{1F9F5} Session id: ${record.sessionId} (session-${record.localId}, active)` : `\u{1F9F5} Session id: ${record.sessionId} (session-${record.localId})`;
|
|
2022
|
+
console.log(`${YELLOW}------ ${header} ------${RESET}`);
|
|
2023
|
+
printKeyValueTable([
|
|
2024
|
+
["\u{1F9E0} topic", (_c = stats == null ? void 0 : stats.topic) != null ? _c : "Unavailable (fetch failed)"],
|
|
2025
|
+
["\u{1F4AC} msg count", stats ? String(stats.messageCount) : "n/a"],
|
|
2026
|
+
[
|
|
2027
|
+
"\u{1F9EE} token count",
|
|
2028
|
+
stats ? `${stats.tokenCountEstimate} (estimated)` : "n/a"
|
|
2029
|
+
],
|
|
2030
|
+
["\u{1F6E0} tool calls", stats ? String(stats.toolCalls) : "n/a"],
|
|
2031
|
+
[
|
|
2032
|
+
"\u{1F4B8} transactions",
|
|
2033
|
+
`${pendingTxs.length + signedTxs.length} (${pendingTxs.length} pending, ${signedTxs.length} signed)`
|
|
2034
|
+
]
|
|
2035
|
+
]);
|
|
2036
|
+
console.log();
|
|
2037
|
+
console.log(`${YELLOW}\u{1F4BE} Transactions metadata (JSON):${RESET}`);
|
|
2038
|
+
printTransactionTable(pendingTxs, signedTxs);
|
|
2039
|
+
}
|
|
2040
|
+
async function sessionsCommand(_runtime) {
|
|
2041
|
+
var _a3;
|
|
2042
|
+
const sessions = listStoredSessions().sort((a, b) => b.updatedAt - a.updatedAt);
|
|
2043
|
+
if (sessions.length === 0) {
|
|
2044
|
+
console.log("No local sessions.");
|
|
2045
|
+
printDataFileLocation();
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
const activeSessionId = (_a3 = readState()) == null ? void 0 : _a3.sessionId;
|
|
2049
|
+
const statsResults = await Promise.all(
|
|
2050
|
+
sessions.map((record) => fetchRemoteSessionStats(record))
|
|
2051
|
+
);
|
|
2052
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
2053
|
+
printSessionSummary(
|
|
2054
|
+
sessions[i],
|
|
2055
|
+
statsResults[i],
|
|
2056
|
+
sessions[i].sessionId === activeSessionId
|
|
2057
|
+
);
|
|
2058
|
+
if (i < sessions.length - 1) {
|
|
2059
|
+
console.log();
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
printDataFileLocation();
|
|
2063
|
+
}
|
|
2064
|
+
function sessionCommand(runtime) {
|
|
2065
|
+
const subcommand = runtime.parsed.positional[0];
|
|
2066
|
+
const selector = runtime.parsed.positional[1];
|
|
2067
|
+
if (subcommand === "resume") {
|
|
2068
|
+
if (!selector) {
|
|
2069
|
+
fatal("Usage: aomi session resume <session-id|session-N|N>");
|
|
2070
|
+
}
|
|
2071
|
+
const resumed = setActiveSession(selector);
|
|
2072
|
+
if (!resumed) {
|
|
2073
|
+
fatal(`No local session found for selector "${selector}".`);
|
|
2074
|
+
}
|
|
2075
|
+
console.log(`Active session set to ${resumed.sessionId} (session-${resumed.localId}).`);
|
|
2076
|
+
printDataFileLocation();
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
if (subcommand === "delete") {
|
|
2080
|
+
if (!selector) {
|
|
2081
|
+
fatal("Usage: aomi session delete <session-id|session-N|N>");
|
|
2082
|
+
}
|
|
2083
|
+
const deleted = deleteStoredSession(selector);
|
|
2084
|
+
if (!deleted) {
|
|
2085
|
+
fatal(`No local session found for selector "${selector}".`);
|
|
2086
|
+
}
|
|
2087
|
+
console.log(`Deleted local session ${deleted.sessionId} (session-${deleted.localId}).`);
|
|
2088
|
+
const active = readState();
|
|
2089
|
+
if (active) {
|
|
2090
|
+
console.log(`Active session: ${active.sessionId}`);
|
|
2091
|
+
} else {
|
|
2092
|
+
console.log("No active session");
|
|
2093
|
+
}
|
|
2094
|
+
printDataFileLocation();
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
2097
|
+
fatal(
|
|
2098
|
+
"Usage: aomi session resume <session-id|session-N|N>\n aomi session delete <session-id|session-N|N>"
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
// src/cli/commands/wallet.ts
|
|
2103
|
+
import { createWalletClient, http } from "viem";
|
|
2104
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
2105
|
+
import * as viemChains from "viem/chains";
|
|
1355
2106
|
function txCommand() {
|
|
1356
|
-
var
|
|
2107
|
+
var _a3, _b, _c;
|
|
1357
2108
|
const state = readState();
|
|
1358
2109
|
if (!state) {
|
|
1359
2110
|
console.log("No active session");
|
|
1360
2111
|
printDataFileLocation();
|
|
1361
2112
|
return;
|
|
1362
2113
|
}
|
|
1363
|
-
const pending = (
|
|
2114
|
+
const pending = (_a3 = state.pendingTxs) != null ? _a3 : [];
|
|
1364
2115
|
const signed = (_b = state.signedTxs) != null ? _b : [];
|
|
1365
2116
|
if (pending.length === 0 && signed.length === 0) {
|
|
1366
2117
|
console.log("No transactions.");
|
|
@@ -1392,48 +2143,62 @@ function txCommand() {
|
|
|
1392
2143
|
}
|
|
1393
2144
|
printDataFileLocation();
|
|
1394
2145
|
}
|
|
1395
|
-
|
|
1396
|
-
var
|
|
1397
|
-
const
|
|
2146
|
+
function requirePendingTx(state, txId) {
|
|
2147
|
+
var _a3;
|
|
2148
|
+
const pendingTx = ((_a3 = state.pendingTxs) != null ? _a3 : []).find((tx) => tx.id === txId);
|
|
2149
|
+
if (!pendingTx) {
|
|
2150
|
+
fatal(
|
|
2151
|
+
`No pending transaction with id "${txId}".
|
|
2152
|
+
Run \`aomi tx\` to see available IDs.`
|
|
2153
|
+
);
|
|
2154
|
+
}
|
|
2155
|
+
return pendingTx;
|
|
2156
|
+
}
|
|
2157
|
+
async function signCommand(runtime) {
|
|
2158
|
+
var _a3, _b, _c;
|
|
2159
|
+
const txId = runtime.parsed.positional[0];
|
|
1398
2160
|
if (!txId) {
|
|
1399
|
-
fatal(
|
|
2161
|
+
fatal(
|
|
2162
|
+
"Usage: aomi sign <tx-id>\nRun `aomi tx` to see pending transaction IDs."
|
|
2163
|
+
);
|
|
1400
2164
|
}
|
|
1401
|
-
const
|
|
1402
|
-
const privateKey = config.privateKey;
|
|
2165
|
+
const privateKey = runtime.config.privateKey;
|
|
1403
2166
|
if (!privateKey) {
|
|
1404
|
-
fatal(
|
|
2167
|
+
fatal(
|
|
2168
|
+
[
|
|
2169
|
+
"Private key required for `aomi sign`.",
|
|
2170
|
+
"Pass one of:",
|
|
2171
|
+
" --private-key <hex-key>",
|
|
2172
|
+
" PRIVATE_KEY=<hex-key> aomi sign <tx-id>"
|
|
2173
|
+
].join("\n")
|
|
2174
|
+
);
|
|
1405
2175
|
}
|
|
1406
2176
|
const state = readState();
|
|
1407
2177
|
if (!state) {
|
|
1408
2178
|
fatal("No active session. Run `aomi chat` first.");
|
|
1409
2179
|
}
|
|
1410
|
-
const pendingTx = (
|
|
1411
|
-
|
|
1412
|
-
fatal(`No pending transaction with id "${txId}".
|
|
1413
|
-
Run \`aomi tx\` to see available IDs.`);
|
|
1414
|
-
}
|
|
1415
|
-
const { session } = getOrCreateSession();
|
|
2180
|
+
const pendingTx = requirePendingTx(state, txId);
|
|
2181
|
+
const { session } = getOrCreateSession(runtime);
|
|
1416
2182
|
try {
|
|
1417
|
-
let viem;
|
|
1418
|
-
let viemAccounts;
|
|
1419
|
-
let viemChains;
|
|
1420
|
-
try {
|
|
1421
|
-
viem = await import("viem");
|
|
1422
|
-
viemAccounts = await import("viem/accounts");
|
|
1423
|
-
viemChains = await import("viem/chains");
|
|
1424
|
-
} catch (e) {
|
|
1425
|
-
fatal(
|
|
1426
|
-
"viem is required for `aomi sign`. Install it:\n npm install viem\n # or: pnpm add viem"
|
|
1427
|
-
);
|
|
1428
|
-
}
|
|
1429
|
-
const { createWalletClient, http } = viem;
|
|
1430
|
-
const { privateKeyToAccount } = viemAccounts;
|
|
1431
2183
|
const account = privateKeyToAccount(privateKey);
|
|
1432
|
-
const rpcUrl = config.chainRpcUrl;
|
|
1433
|
-
const targetChainId = (
|
|
1434
|
-
const chain = (
|
|
1435
|
-
(
|
|
1436
|
-
)) != null ?
|
|
2184
|
+
const rpcUrl = runtime.config.chainRpcUrl;
|
|
2185
|
+
const targetChainId = (_a3 = pendingTx.chainId) != null ? _a3 : 1;
|
|
2186
|
+
const chain = (_b = Object.values(viemChains).find(
|
|
2187
|
+
(candidate) => typeof candidate === "object" && candidate !== null && "id" in candidate && candidate.id === targetChainId
|
|
2188
|
+
)) != null ? _b : {
|
|
2189
|
+
id: targetChainId,
|
|
2190
|
+
name: `Chain ${targetChainId}`,
|
|
2191
|
+
nativeCurrency: {
|
|
2192
|
+
name: "ETH",
|
|
2193
|
+
symbol: "ETH",
|
|
2194
|
+
decimals: 18
|
|
2195
|
+
},
|
|
2196
|
+
rpcUrls: {
|
|
2197
|
+
default: {
|
|
2198
|
+
http: [rpcUrl != null ? rpcUrl : ""]
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
};
|
|
1437
2202
|
const walletClient = createWalletClient({
|
|
1438
2203
|
account,
|
|
1439
2204
|
chain,
|
|
@@ -1446,12 +2211,14 @@ Run \`aomi tx\` to see available IDs.`);
|
|
|
1446
2211
|
console.log(`To: ${pendingTx.to}`);
|
|
1447
2212
|
if (pendingTx.value) console.log(`Value: ${pendingTx.value}`);
|
|
1448
2213
|
if (pendingTx.chainId) console.log(`Chain: ${pendingTx.chainId}`);
|
|
1449
|
-
if (pendingTx.data)
|
|
2214
|
+
if (pendingTx.data) {
|
|
2215
|
+
console.log(`Data: ${pendingTx.data.slice(0, 40)}...`);
|
|
2216
|
+
}
|
|
1450
2217
|
console.log();
|
|
1451
2218
|
const hash = await walletClient.sendTransaction({
|
|
1452
2219
|
to: pendingTx.to,
|
|
1453
2220
|
value: pendingTx.value ? BigInt(pendingTx.value) : /* @__PURE__ */ BigInt("0"),
|
|
1454
|
-
data: (
|
|
2221
|
+
data: (_c = pendingTx.data) != null ? _c : void 0
|
|
1455
2222
|
});
|
|
1456
2223
|
console.log(`\u2705 Sent! Hash: ${hash}`);
|
|
1457
2224
|
removePendingTx(state, txId);
|
|
@@ -1478,8 +2245,12 @@ Run \`aomi tx\` to see available IDs.`);
|
|
|
1478
2245
|
if (!typedData) {
|
|
1479
2246
|
fatal("EIP-712 request is missing typed_data payload.");
|
|
1480
2247
|
}
|
|
1481
|
-
if (pendingTx.description)
|
|
1482
|
-
|
|
2248
|
+
if (pendingTx.description) {
|
|
2249
|
+
console.log(`Desc: ${pendingTx.description}`);
|
|
2250
|
+
}
|
|
2251
|
+
if (typedData.primaryType) {
|
|
2252
|
+
console.log(`Type: ${typedData.primaryType}`);
|
|
2253
|
+
}
|
|
1483
2254
|
console.log();
|
|
1484
2255
|
const { domain, types, primaryType, message } = typedData;
|
|
1485
2256
|
const sigTypes = __spreadValues({}, types);
|
|
@@ -1522,73 +2293,24 @@ Run \`aomi tx\` to see available IDs.`);
|
|
|
1522
2293
|
session.close();
|
|
1523
2294
|
}
|
|
1524
2295
|
}
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
const state = readState();
|
|
1528
|
-
if (!state) {
|
|
1529
|
-
console.log("No active session");
|
|
1530
|
-
printDataFileLocation();
|
|
1531
|
-
return;
|
|
1532
|
-
}
|
|
1533
|
-
const { session } = getOrCreateSession();
|
|
1534
|
-
try {
|
|
1535
|
-
const apiState = await session.client.fetchState(state.sessionId);
|
|
1536
|
-
const messages = (_a2 = apiState.messages) != null ? _a2 : [];
|
|
1537
|
-
if (messages.length === 0) {
|
|
1538
|
-
console.log("No messages in this session.");
|
|
1539
|
-
printDataFileLocation();
|
|
1540
|
-
return;
|
|
1541
|
-
}
|
|
1542
|
-
for (const msg of messages) {
|
|
1543
|
-
let time = "";
|
|
1544
|
-
if (msg.timestamp) {
|
|
1545
|
-
const raw = msg.timestamp;
|
|
1546
|
-
const n = /^\d+$/.test(raw) ? parseInt(raw, 10) : NaN;
|
|
1547
|
-
const date = !isNaN(n) ? new Date(n < 1e12 ? n * 1e3 : n) : new Date(raw);
|
|
1548
|
-
time = isNaN(date.getTime()) ? "" : `${DIM}${date.toLocaleTimeString()}${RESET} `;
|
|
1549
|
-
}
|
|
1550
|
-
const sender = (_b = msg.sender) != null ? _b : "unknown";
|
|
1551
|
-
if (sender === "user") {
|
|
1552
|
-
console.log(`${time}${CYAN}\u{1F464} You:${RESET} ${(_c = msg.content) != null ? _c : ""}`);
|
|
1553
|
-
} else if (sender === "agent" || sender === "assistant") {
|
|
1554
|
-
if (msg.tool_result) {
|
|
1555
|
-
const [toolName, result] = msg.tool_result;
|
|
1556
|
-
console.log(
|
|
1557
|
-
`${time}${GREEN}\u{1F527} [${toolName}]${RESET} ${result.slice(0, 200)}${result.length > 200 ? "\u2026" : ""}`
|
|
1558
|
-
);
|
|
1559
|
-
}
|
|
1560
|
-
if (msg.content) {
|
|
1561
|
-
console.log(`${time}${CYAN}\u{1F916} Agent:${RESET} ${msg.content}`);
|
|
1562
|
-
}
|
|
1563
|
-
} else if (sender === "system") {
|
|
1564
|
-
console.log(`${time}${YELLOW}\u2699\uFE0F System:${RESET} ${(_d = msg.content) != null ? _d : ""}`);
|
|
1565
|
-
} else {
|
|
1566
|
-
console.log(`${time}${DIM}[${sender}]${RESET} ${(_e = msg.content) != null ? _e : ""}`);
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
console.log(`
|
|
1570
|
-
${DIM}\u2014 ${messages.length} messages \u2014${RESET}`);
|
|
1571
|
-
printDataFileLocation();
|
|
1572
|
-
} finally {
|
|
1573
|
-
session.close();
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
|
-
function closeCommand() {
|
|
1577
|
-
const state = readState();
|
|
1578
|
-
if (state) {
|
|
1579
|
-
const { session } = getOrCreateSession();
|
|
1580
|
-
session.close();
|
|
1581
|
-
}
|
|
1582
|
-
clearState();
|
|
1583
|
-
console.log("Session closed");
|
|
1584
|
-
}
|
|
2296
|
+
|
|
2297
|
+
// src/cli/main.ts
|
|
1585
2298
|
function printUsage() {
|
|
1586
2299
|
console.log(`
|
|
1587
2300
|
aomi \u2014 CLI client for Aomi on-chain agent
|
|
1588
2301
|
|
|
1589
2302
|
Usage:
|
|
1590
2303
|
aomi chat <message> Send a message and print the response
|
|
2304
|
+
aomi chat --model <rig>
|
|
2305
|
+
Set the session model before sending the message
|
|
1591
2306
|
aomi chat --verbose Stream agent responses, tool calls, and events live
|
|
2307
|
+
aomi models List models available to the current backend
|
|
2308
|
+
aomi model set <rig> Set the active model for the current session
|
|
2309
|
+
aomi sessions List local sessions with metadata tables
|
|
2310
|
+
aomi session resume <id>
|
|
2311
|
+
Resume a local session (session-id or session-N)
|
|
2312
|
+
aomi session delete <id>
|
|
2313
|
+
Delete a local session file (session-id or session-N)
|
|
1592
2314
|
aomi log Show full conversation history with tool results
|
|
1593
2315
|
aomi tx List pending and signed transactions
|
|
1594
2316
|
aomi sign <tx-id> Sign and submit a pending transaction
|
|
@@ -1600,6 +2322,7 @@ Options:
|
|
|
1600
2322
|
--backend-url <url> Backend URL (default: https://api.aomi.dev)
|
|
1601
2323
|
--api-key <key> API key for non-default namespaces
|
|
1602
2324
|
--namespace <ns> Namespace (default: "default")
|
|
2325
|
+
--model <rig> Set the active model for this session
|
|
1603
2326
|
--public-key <addr> Wallet address (so the agent knows your wallet)
|
|
1604
2327
|
--private-key <key> Hex private key for signing
|
|
1605
2328
|
--rpc-url <url> RPC URL for transaction submission
|
|
@@ -1609,49 +2332,85 @@ Environment (overridden by flags):
|
|
|
1609
2332
|
AOMI_BASE_URL Backend URL
|
|
1610
2333
|
AOMI_API_KEY API key
|
|
1611
2334
|
AOMI_NAMESPACE Namespace
|
|
2335
|
+
AOMI_MODEL Model rig
|
|
1612
2336
|
AOMI_PUBLIC_KEY Wallet address
|
|
1613
2337
|
PRIVATE_KEY Hex private key for signing
|
|
1614
2338
|
CHAIN_RPC_URL RPC URL for transaction submission
|
|
1615
2339
|
`.trim());
|
|
1616
2340
|
}
|
|
1617
|
-
async function main() {
|
|
1618
|
-
var
|
|
1619
|
-
const
|
|
1620
|
-
switch (
|
|
2341
|
+
async function main(runtime) {
|
|
2342
|
+
var _a3;
|
|
2343
|
+
const command = (_a3 = runtime.parsed.command) != null ? _a3 : runtime.parsed.flags["help"] || runtime.parsed.flags["h"] ? "help" : void 0;
|
|
2344
|
+
switch (command) {
|
|
1621
2345
|
case "chat":
|
|
1622
|
-
await chatCommand();
|
|
2346
|
+
await chatCommand(runtime);
|
|
1623
2347
|
break;
|
|
1624
2348
|
case "log":
|
|
1625
|
-
await logCommand();
|
|
2349
|
+
await logCommand(runtime);
|
|
2350
|
+
break;
|
|
2351
|
+
case "models":
|
|
2352
|
+
await modelsCommand(runtime);
|
|
2353
|
+
break;
|
|
2354
|
+
case "model":
|
|
2355
|
+
await modelCommand(runtime);
|
|
2356
|
+
break;
|
|
2357
|
+
case "sessions":
|
|
2358
|
+
await sessionsCommand(runtime);
|
|
2359
|
+
break;
|
|
2360
|
+
case "session":
|
|
2361
|
+
sessionCommand(runtime);
|
|
1626
2362
|
break;
|
|
1627
2363
|
case "tx":
|
|
1628
2364
|
txCommand();
|
|
1629
2365
|
break;
|
|
1630
2366
|
case "sign":
|
|
1631
|
-
await signCommand();
|
|
2367
|
+
await signCommand(runtime);
|
|
1632
2368
|
break;
|
|
1633
2369
|
case "status":
|
|
1634
|
-
await statusCommand();
|
|
2370
|
+
await statusCommand(runtime);
|
|
1635
2371
|
break;
|
|
1636
2372
|
case "events":
|
|
1637
|
-
await eventsCommand();
|
|
2373
|
+
await eventsCommand(runtime);
|
|
1638
2374
|
break;
|
|
1639
2375
|
case "close":
|
|
1640
|
-
closeCommand();
|
|
2376
|
+
closeCommand(runtime);
|
|
1641
2377
|
break;
|
|
1642
2378
|
case "help":
|
|
1643
2379
|
printUsage();
|
|
1644
2380
|
break;
|
|
1645
2381
|
default:
|
|
1646
2382
|
printUsage();
|
|
1647
|
-
if (
|
|
2383
|
+
if (command) {
|
|
2384
|
+
throw new CliExit(1);
|
|
2385
|
+
}
|
|
1648
2386
|
}
|
|
1649
2387
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
2388
|
+
function isPnpmExecWrapper() {
|
|
2389
|
+
var _a3, _b;
|
|
2390
|
+
const npmCommand = (_a3 = process.env.npm_command) != null ? _a3 : "";
|
|
2391
|
+
const userAgent = (_b = process.env.npm_config_user_agent) != null ? _b : "";
|
|
2392
|
+
return npmCommand === "exec" && userAgent.includes("pnpm/");
|
|
2393
|
+
}
|
|
2394
|
+
async function runCli(argv = process.argv) {
|
|
2395
|
+
const runtime = createRuntime(argv);
|
|
2396
|
+
const RED = "\x1B[31m";
|
|
2397
|
+
const RESET3 = "\x1B[0m";
|
|
2398
|
+
const strictExit = process.env.AOMI_CLI_STRICT_EXIT === "1";
|
|
2399
|
+
try {
|
|
2400
|
+
await main(runtime);
|
|
2401
|
+
} catch (err) {
|
|
2402
|
+
if (err instanceof CliExit) {
|
|
2403
|
+
if (!strictExit && isPnpmExecWrapper()) {
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
2406
|
+
process.exit(err.code);
|
|
2407
|
+
return;
|
|
2408
|
+
}
|
|
2409
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2410
|
+
console.error(`${RED}\u274C ${message}${RESET3}`);
|
|
2411
|
+
process.exit(1);
|
|
1654
2412
|
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
// src/cli.ts
|
|
2416
|
+
void runCli();
|