@agent-commons/cli 0.1.4 → 0.1.6

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.
Files changed (2) hide show
  1. package/dist/bin.js +760 -27
  2. package/package.json +2 -2
package/dist/bin.js CHANGED
@@ -24,11 +24,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/bin.ts
27
- var import_commander12 = require("commander");
27
+ var import_commander16 = require("commander");
28
+ var import_path3 = require("path");
29
+ var import_os3 = require("os");
30
+ var import_child_process2 = require("child_process");
28
31
 
29
32
  // src/commands/login.ts
30
33
  var import_commander = require("commander");
31
34
  var readline = __toESM(require("readline"));
35
+ var import_fs2 = require("fs");
36
+ var import_path2 = require("path");
37
+ var import_os2 = require("os");
32
38
 
33
39
  // src/config.ts
34
40
  var import_fs = require("fs");
@@ -37,7 +43,8 @@ var import_path = require("path");
37
43
  var import_sdk = require("@agent-commons/sdk");
38
44
  var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".agc");
39
45
  var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
40
- var DEFAULT_API_URL = process.env.AGC_API_URL ?? "http://localhost:3001";
46
+ var DEFAULT_API_URL = process.env.AGC_API_URL ?? "https://api.agentcommons.io";
47
+ var DEFAULT_APP_URL = "https://www.agentcommons.io";
41
48
  function loadConfig() {
42
49
  const fromEnv = {
43
50
  ...process.env.AGC_API_URL && { apiUrl: process.env.AGC_API_URL },
@@ -81,6 +88,7 @@ function makeClient(overrides) {
81
88
  // src/ui.ts
82
89
  var import_chalk = __toESM(require("chalk"));
83
90
  var import_ora = __toESM(require("ora"));
91
+ var import_child_process = require("child_process");
84
92
  var c = {
85
93
  primary: (s) => import_chalk.default.cyan(s),
86
94
  success: (s) => import_chalk.default.green(s),
@@ -98,6 +106,80 @@ var sym = {
98
106
  bullet: import_chalk.default.dim("\u2022"),
99
107
  dot: import_chalk.default.dim("\xB7")
100
108
  };
109
+ function banner(version = "0.1.4") {
110
+ const line = import_chalk.default.cyan(" \u2500".padEnd(2) + "\u2500".repeat(44));
111
+ console.log("");
112
+ console.log(line);
113
+ console.log(
114
+ import_chalk.default.cyan(" \u2502 ") + import_chalk.default.bold.white(" \u25C8 Agent Commons") + import_chalk.default.dim(" \xB7 CLI") + " " + import_chalk.default.cyan(`v${version}`)
115
+ );
116
+ console.log(import_chalk.default.cyan(" \u2502 ") + import_chalk.default.dim(" The Open AI Agent Network \xB7 agentcommons.io"));
117
+ console.log(line);
118
+ console.log("");
119
+ }
120
+ function step(n, total, title) {
121
+ const fraction = import_chalk.default.dim(`${n}/${total}`);
122
+ console.log(`
123
+ ${import_chalk.default.cyan.bold(" Step " + n)} ${fraction} ${import_chalk.default.bold(title)}`);
124
+ console.log(import_chalk.default.dim(" " + "\u2500".repeat(38)));
125
+ }
126
+ async function select(prompt2, choices) {
127
+ if (!process.stdin.isTTY) {
128
+ return choices[0].value;
129
+ }
130
+ let idx = 0;
131
+ const total = choices.length;
132
+ const render = (first = false) => {
133
+ if (!first) {
134
+ process.stdout.write(`\x1B[${total + 2}A\x1B[0J`);
135
+ }
136
+ console.log("\n" + import_chalk.default.bold(" " + prompt2));
137
+ for (let i = 0; i < total; i++) {
138
+ const { label, hint } = choices[i];
139
+ if (i === idx) {
140
+ const hintStr = hint ? import_chalk.default.dim(" " + hint) : "";
141
+ process.stdout.write(import_chalk.default.cyan(" \u203A ") + import_chalk.default.bold.white(label) + hintStr + "\n");
142
+ } else {
143
+ process.stdout.write(import_chalk.default.dim(" " + label) + "\n");
144
+ }
145
+ }
146
+ };
147
+ render(true);
148
+ return new Promise((resolve) => {
149
+ process.stdin.setRawMode(true);
150
+ process.stdin.resume();
151
+ process.stdin.setEncoding("utf8");
152
+ const handler = (data) => {
153
+ const key = String(data);
154
+ if (key === "\x1B[A" || key === "k") {
155
+ idx = (idx - 1 + total) % total;
156
+ render();
157
+ } else if (key === "\x1B[B" || key === "j") {
158
+ idx = (idx + 1) % total;
159
+ render();
160
+ } else if (key === "\r" || key === "\n" || key === " ") {
161
+ cleanup();
162
+ process.stdout.write("\n");
163
+ resolve(choices[idx].value);
164
+ } else if (key === "") {
165
+ cleanup();
166
+ process.stdout.write("\n");
167
+ process.exit(130);
168
+ }
169
+ };
170
+ const cleanup = () => {
171
+ process.stdin.removeListener("data", handler);
172
+ process.stdin.setRawMode(false);
173
+ process.stdin.pause();
174
+ };
175
+ process.stdin.on("data", handler);
176
+ });
177
+ }
178
+ function openBrowser(url) {
179
+ const cmd = process.platform === "darwin" ? `open "${url}"` : process.platform === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
180
+ (0, import_child_process.exec)(cmd, () => {
181
+ });
182
+ }
101
183
  function spin(text) {
102
184
  return (0, import_ora.default)({ text, color: "cyan" }).start();
103
185
  }
@@ -174,6 +256,7 @@ function statusBadge(status) {
174
256
  }
175
257
 
176
258
  // src/commands/login.ts
259
+ var CONFIG_FILE2 = (0, import_path2.join)((0, import_os2.homedir)(), ".agc", "config.json");
177
260
  function prompt(question, hidden = false) {
178
261
  return new Promise((resolve) => {
179
262
  const rl = readline.createInterface({
@@ -202,26 +285,70 @@ function loginCommand() {
202
285
  cmd.option("--api-url <url>", "API base URL", DEFAULT_API_URL).option("--api-key <key>", "API key (or set AGC_API_KEY env var)").option("--initiator <id>", "Default initiator ID (wallet address or user ID)").action(async (opts) => {
203
286
  try {
204
287
  const current = loadConfig();
205
- const apiUrl = opts.apiUrl !== DEFAULT_API_URL ? opts.apiUrl : await prompt(`API URL [${current.apiUrl ?? DEFAULT_API_URL}]: `) || (current.apiUrl ?? DEFAULT_API_URL);
206
- const appUrl = apiUrl.includes("localhost") ? "http://localhost:3000" : apiUrl.replace(/\/api$/, "").replace("api.", "").replace(":3001", ":3000");
288
+ const isFirstRun = !(0, import_fs2.existsSync)(CONFIG_FILE2);
289
+ banner();
290
+ if (isFirstRun) {
291
+ console.log(c.bold(" Welcome to Agent Commons CLI!"));
292
+ console.log(c.dim(" Let's get you set up in three quick steps.\n"));
293
+ } else {
294
+ console.log(c.bold(" Update your credentials"));
295
+ console.log(c.dim(" Press Enter to keep existing values.\n"));
296
+ }
297
+ step(1, 3, "API Endpoint");
298
+ const defaultUrl = current.apiUrl ?? DEFAULT_API_URL;
299
+ let apiUrl;
300
+ if (opts.apiUrl !== DEFAULT_API_URL) {
301
+ apiUrl = opts.apiUrl;
302
+ console.log(` ${c.dim("Using:")} ${apiUrl}`);
303
+ } else {
304
+ const answer = await prompt(
305
+ ` ${c.dim("URL")} [${c.dim(defaultUrl)}]: `
306
+ );
307
+ apiUrl = answer || defaultUrl;
308
+ }
309
+ console.log(` ${sym.ok} ${c.dim("Endpoint:")} ${c.primary(apiUrl)}`);
310
+ const appUrl = apiUrl.includes("localhost") ? "http://localhost:3000" : DEFAULT_APP_URL;
311
+ const settingsUrl = `${appUrl}/settings`;
312
+ step(2, 3, "API Key");
207
313
  let apiKey = opts.apiKey;
208
314
  if (!apiKey) {
209
- console.log(`
210
- Generate an API key at:
211
- ${c.bold(`${appUrl}/settings/api-keys`)}
315
+ console.log(` ${sym.arrow} Opening your browser to generate an API key\u2026`);
316
+ console.log(` ${c.dim(settingsUrl)}
212
317
  `);
213
- apiKey = await prompt(`API Key (sk-ac-...): `);
318
+ openBrowser(settingsUrl);
319
+ console.log(c.dim(" Once you have your key, paste it below."));
320
+ console.log(c.dim(" (Keys look like: sk-ac-xxxxxxxxxxxxxxxx)\n"));
321
+ apiKey = await prompt(` ${c.dim("API Key:")} `);
214
322
  if (!apiKey) apiKey = current.apiKey;
215
323
  }
324
+ if (!apiKey) {
325
+ console.log(`
326
+ ${c.warn("\u26A0")} No API key provided \u2014 you can set one later with ${c.bold("agc config set apiKey <key>")}`);
327
+ } else {
328
+ console.log(` ${sym.ok} ${c.dim("Key saved:")} ****${apiKey.slice(-4)}`);
329
+ }
330
+ step(3, 3, "Your Identity");
216
331
  let initiator = opts.initiator;
217
332
  if (!initiator) {
218
- initiator = await prompt(`Wallet address (0x...): `);
333
+ const defaultInitiator = current.initiator ?? "";
334
+ const hint = defaultInitiator ? `[${c.dim(defaultInitiator.slice(0, 8) + "\u2026")}] ` : "";
335
+ initiator = await prompt(` ${c.dim("Wallet address (0x\u2026):")} ${hint}`);
219
336
  if (!initiator) initiator = current.initiator;
220
337
  }
338
+ if (!initiator) {
339
+ console.log(` ${c.warn("\u26A0")} No wallet address \u2014 set one later with ${c.bold("agc config set initiator <address>")}`);
340
+ } else {
341
+ console.log(` ${sym.ok} ${c.dim("Address:")} ${c.id(initiator.slice(0, 10) + "\u2026" + initiator.slice(-6))}`);
342
+ }
221
343
  saveConfig({ apiUrl, apiKey, initiator });
222
344
  console.log(`
223
- ${sym.ok} Credentials saved to ~/.agc/config.json`);
224
- console.log(c.dim(" Run `agc whoami` to verify the connection."));
345
+ ${sym.ok} ${c.success("All set!")} Credentials saved to ${c.dim("~/.agc/config.json")}`);
346
+ console.log(`
347
+ ${c.dim("Next steps:")}`);
348
+ console.log(` ${sym.arrow} ${c.dim("Run")} ${c.bold("agc")} ${c.dim("for an interactive menu")}`);
349
+ console.log(` ${sym.arrow} ${c.dim("Run")} ${c.bold("agc whoami")} ${c.dim("to verify your connection")}`);
350
+ console.log(` ${sym.arrow} ${c.dim("Run")} ${c.bold("agc chat --agent <id>")} ${c.dim("to start chatting")}
351
+ `);
225
352
  } catch (err) {
226
353
  printError(err);
227
354
  process.exit(1);
@@ -381,6 +508,76 @@ ${sym.ok} Agent created`);
381
508
  process.exit(1);
382
509
  }
383
510
  });
511
+ const autonomy = cmd.command("autonomy").description("Manage agent heartbeat / autonomy");
512
+ autonomy.command("status").description("Show autonomy status for an agent").requiredOption("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
513
+ const client = makeClient();
514
+ const spinner = spin("Fetching autonomy status\u2026");
515
+ try {
516
+ const res = await client.agents.getAutonomy(opts.agent);
517
+ spinner.stop();
518
+ const s = res.data;
519
+ if (opts.json) return jsonOut(s);
520
+ console.log(`
521
+ ${c.bold("Autonomy Status")}`);
522
+ detail([
523
+ ["Enabled", s.enabled ? c.bold("yes") : "no"],
524
+ ["Interval", s.intervalSec ? `${s.intervalSec}s` : "n/a"],
525
+ ["Armed", s.isArmed ? c.bold("yes") : "no"],
526
+ ["Last beat", s.lastBeatAt ? new Date(s.lastBeatAt).toLocaleString() : "never"],
527
+ ["Next beat", s.nextBeatAt ? new Date(s.nextBeatAt).toLocaleString() : "n/a"]
528
+ ]);
529
+ } catch (err) {
530
+ spinner.stop();
531
+ printError(err);
532
+ process.exit(1);
533
+ }
534
+ });
535
+ autonomy.command("enable").description("Enable autonomous heartbeat for an agent").requiredOption("--agent <agentId>", "Agent ID").option("--interval <seconds>", "Heartbeat interval in seconds (min 30)", "300").action(async (opts) => {
536
+ const client = makeClient();
537
+ const spinner = spin("Enabling autonomy\u2026");
538
+ try {
539
+ await client.agents.setAutonomy(opts.agent, {
540
+ enabled: true,
541
+ intervalSec: parseInt(opts.interval, 10)
542
+ });
543
+ spinner.stop();
544
+ console.log(`
545
+ ${sym.ok} Autonomy enabled for agent ${c.id(opts.agent)}`);
546
+ console.log(c.dim(` Heartbeat every ${opts.interval}s`));
547
+ } catch (err) {
548
+ spinner.stop();
549
+ printError(err);
550
+ process.exit(1);
551
+ }
552
+ });
553
+ autonomy.command("disable").description("Disable autonomous heartbeat for an agent").requiredOption("--agent <agentId>", "Agent ID").action(async (opts) => {
554
+ const client = makeClient();
555
+ const spinner = spin("Disabling autonomy\u2026");
556
+ try {
557
+ await client.agents.setAutonomy(opts.agent, { enabled: false });
558
+ spinner.stop();
559
+ console.log(`
560
+ ${sym.ok} Autonomy disabled for agent ${c.id(opts.agent)}`);
561
+ } catch (err) {
562
+ spinner.stop();
563
+ printError(err);
564
+ process.exit(1);
565
+ }
566
+ });
567
+ autonomy.command("trigger").description("Trigger a single heartbeat beat immediately").requiredOption("--agent <agentId>", "Agent ID").action(async (opts) => {
568
+ const client = makeClient();
569
+ const spinner = spin("Triggering heartbeat\u2026");
570
+ try {
571
+ await client.agents.triggerHeartbeat(opts.agent);
572
+ spinner.stop();
573
+ console.log(`
574
+ ${sym.ok} Heartbeat triggered for agent ${c.id(opts.agent)}`);
575
+ } catch (err) {
576
+ spinner.stop();
577
+ printError(err);
578
+ process.exit(1);
579
+ }
580
+ });
384
581
  return cmd;
385
582
  }
386
583
 
@@ -388,33 +585,29 @@ ${sym.ok} Agent created`);
388
585
  var import_commander3 = require("commander");
389
586
  function sessionsCommand() {
390
587
  const cmd = new import_commander3.Command("sessions").description("Manage chat sessions");
391
- cmd.command("list").description("List sessions for the current initiator + agent").option("--agent <agentId>", "Filter by agent ID").option("--json", "Output as JSON").action(async (opts) => {
588
+ cmd.command("list").description("List sessions \u2014 all for the current user, or filtered by agent").option("--agent <agentId>", "Filter by agent ID (default: all agents)").option("--json", "Output as JSON").action(async (opts) => {
392
589
  const cfg = loadConfig();
393
590
  if (!cfg.initiator) {
394
591
  console.error(c.error("No initiator set. Run `agc login` first."));
395
592
  process.exit(1);
396
593
  }
397
- const agentId = opts.agent ?? cfg.defaultAgentId;
398
- if (!agentId) {
399
- console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
400
- process.exit(1);
401
- }
402
594
  const spinner = spin("Fetching sessions\u2026");
403
595
  try {
404
596
  const client = makeClient();
405
- const res = await client.sessions.list(agentId, cfg.initiator);
597
+ const agentId = opts.agent ?? cfg.defaultAgentId;
598
+ const res = agentId ? await client.sessions.list(agentId, cfg.initiator) : await client.sessions.listByUser(cfg.initiator);
406
599
  const sessions = res?.data ?? res ?? [];
407
600
  spinner.stop();
408
601
  if (opts.json) return jsonOut(sessions);
409
- section(`Sessions (${sessions.length})`);
602
+ section(`Sessions (${sessions.length})${agentId ? ` \u2014 agent ${agentId.slice(0, 8)}\u2026` : " \u2014 all agents"}`);
410
603
  table(
411
604
  sessions.map((s) => ({
412
605
  ID: s.sessionId.slice(0, 8) + "\u2026",
606
+ Agent: s.agentId ? s.agentId.slice(0, 8) + "\u2026" : "",
413
607
  Title: s.title ?? c.dim("(untitled)"),
414
- Model: s.model?.modelId ?? s.model?.name ?? "",
415
608
  Created: relativeTime(s.createdAt)
416
609
  })),
417
- ["ID", "Title", "Model", "Created"]
610
+ ["ID", "Agent", "Title", "Created"]
418
611
  );
419
612
  } catch (err) {
420
613
  spinner.stop();
@@ -666,9 +859,24 @@ function workflowCommand() {
666
859
  ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
667
860
  console.log(` Status: ${statusBadge(execution.status)}`);
668
861
  if (!opts.watch) {
862
+ const result = execution.result ?? execution.outputData;
669
863
  if (execution.status === "completed") {
670
864
  console.log("\n" + c.label("Result"));
671
- console.log(" " + JSON.stringify(execution.result ?? execution.outputData, null, 2));
865
+ console.log(" " + JSON.stringify(result, null, 2));
866
+ const steps = execution.stepResults ?? execution.nodeResults;
867
+ if (steps && Object.keys(steps).length > 0) {
868
+ console.log("\n" + c.label("Step Results"));
869
+ for (const [nodeId, step2] of Object.entries(steps)) {
870
+ const icon = step2.status === "success" ? sym.ok : step2.status === "error" ? sym.fail : "\xB7";
871
+ const dur = step2.duration != null ? c.dim(` (${(step2.duration / 1e3).toFixed(2)}s)`) : "";
872
+ console.log(` ${icon} ${c.id(nodeId)}${dur}`);
873
+ if (step2.error) console.log(` ${c.error(step2.error)}`);
874
+ else if (step2.output !== void 0) console.log(` ${JSON.stringify(step2.output, null, 2).replace(/\n/g, "\n ")}`);
875
+ }
876
+ }
877
+ } else {
878
+ console.log(c.dim(`
879
+ Workflow is ${execution.status}. Use --watch to stream progress.`));
672
880
  }
673
881
  return;
674
882
  }
@@ -682,10 +890,20 @@ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
682
890
  console.log(`
683
891
  ${sym.ok} ${c.success("Completed")}`);
684
892
  const e = event;
685
- if (e.outputData) {
893
+ if (e.outputData != null) {
686
894
  console.log("\n" + c.label("Output"));
687
895
  console.log(" " + JSON.stringify(e.outputData, null, 2));
688
896
  }
897
+ if (e.nodeResults && Object.keys(e.nodeResults).length > 0) {
898
+ console.log("\n" + c.label("Step Results"));
899
+ for (const [nodeId, step2] of Object.entries(e.nodeResults)) {
900
+ const icon = step2.status === "success" ? sym.ok : step2.status === "error" ? sym.fail : "\xB7";
901
+ const dur = step2.duration != null ? c.dim(` (${(step2.duration / 1e3).toFixed(2)}s)`) : "";
902
+ console.log(` ${icon} ${c.id(nodeId)}${dur}`);
903
+ if (step2.error) console.log(` ${c.error(step2.error)}`);
904
+ else if (step2.output !== void 0) console.log(` ${JSON.stringify(step2.output, null, 2).replace(/\n/g, "\n ")}`);
905
+ }
906
+ }
689
907
  break;
690
908
  } else if (event.type === "failed" || event.type === "cancelled") {
691
909
  process.stdout.write("\n");
@@ -1929,8 +2147,78 @@ ${sym.ok} ${c.bold("Wallet created")}`);
1929
2147
  process.exit(1);
1930
2148
  }
1931
2149
  });
2150
+ cmd.command("send").description("Send USDC (or ETH) from an agent wallet to another address").requiredOption("--agent <agentId>", "Agent ID").requiredOption("--to <address>", "Recipient address (0x\u2026)").requiredOption("--amount <amount>", "Amount to send (e.g. 10.5)").option("--token <symbol>", "Token to send: USDC or ETH (default: USDC)", "USDC").option("--wallet <walletId>", "Specific wallet ID (defaults to primary)").action(async (opts) => {
2151
+ const client = makeClient();
2152
+ const spinner = spin("Preparing transfer\u2026");
2153
+ try {
2154
+ let walletId = opts.wallet;
2155
+ if (!walletId) {
2156
+ const primary = await client.wallets.primary(opts.agent);
2157
+ const w = primary?.data ?? primary;
2158
+ if (!w?.id) {
2159
+ spinner.stop();
2160
+ console.error(c.error(`No wallet found for agent ${opts.agent}. Run: agc wallet create --agent ${opts.agent}`));
2161
+ process.exit(1);
2162
+ }
2163
+ walletId = w.id;
2164
+ }
2165
+ spinner.text = `Sending ${opts.amount} ${opts.token} \u2192 ${opts.to}\u2026`;
2166
+ const result = await client.wallets.transfer(walletId, {
2167
+ toAddress: opts.to,
2168
+ amount: opts.amount,
2169
+ tokenSymbol: opts.token
2170
+ });
2171
+ const tx = result?.txHash ?? result?.data?.txHash ?? result;
2172
+ spinner.stop();
2173
+ console.log(`
2174
+ ${c.bold("Transfer sent")}`);
2175
+ detail([
2176
+ ["Amount", `${opts.amount} ${opts.token}`],
2177
+ ["To", opts.to],
2178
+ ["Tx Hash", c.id(tx)]
2179
+ ]);
2180
+ } catch (err) {
2181
+ spinner.stop();
2182
+ printError(err);
2183
+ process.exit(1);
2184
+ }
2185
+ });
2186
+ cmd.command("x402-fetch").description("Fetch a URL using an agent wallet to pay any x402 (402 Payment Required) challenge").requiredOption("--agent <agentId>", "Agent ID").requiredOption("--url <url>", "Target URL to fetch").option("--method <method>", "HTTP method", "GET").option("--header <header>", "Extra header in Key:Value format (repeatable)", collect, []).option("--body <body>", "Request body string").option("--json", "Output response as JSON").action(async (opts) => {
2187
+ const client = makeClient();
2188
+ const spinner = spin(`Fetching ${opts.url}\u2026`);
2189
+ try {
2190
+ const headers = {};
2191
+ for (const h of opts.header) {
2192
+ const idx = h.indexOf(":");
2193
+ if (idx > 0) headers[h.slice(0, idx).trim()] = h.slice(idx + 1).trim();
2194
+ }
2195
+ const res = await client.wallets.x402Fetch(opts.agent, {
2196
+ url: opts.url,
2197
+ method: opts.method,
2198
+ headers: Object.keys(headers).length ? headers : void 0,
2199
+ body: opts.body
2200
+ });
2201
+ spinner.stop();
2202
+ if (opts.json) return jsonOut(res);
2203
+ console.log(`
2204
+ ${c.bold("Response")} status ${res.status}`);
2205
+ if (res.status === 200) {
2206
+ console.log(c.dim(JSON.stringify(res.body, null, 2).slice(0, 1e3)));
2207
+ } else {
2208
+ console.log(c.warn(JSON.stringify(res.body, null, 2)));
2209
+ }
2210
+ } catch (err) {
2211
+ spinner.stop();
2212
+ printError(err);
2213
+ process.exit(1);
2214
+ }
2215
+ });
1932
2216
  return cmd;
1933
2217
  }
2218
+ function collect(val, acc) {
2219
+ acc.push(val);
2220
+ return acc;
2221
+ }
1934
2222
  function chainName(chainId) {
1935
2223
  const names = {
1936
2224
  "84532": "Base Sepolia",
@@ -1941,9 +2229,446 @@ function chainName(chainId) {
1941
2229
  return names[chainId] ?? `chain ${chainId}`;
1942
2230
  }
1943
2231
 
2232
+ // src/commands/models.ts
2233
+ var import_commander12 = require("commander");
2234
+ function modelsCommand() {
2235
+ const cmd = new import_commander12.Command("models").description("List available LLM models");
2236
+ cmd.command("ls").description("List all available models grouped by provider").option("--provider <name>", "Filter by provider (openai, anthropic, google, mistral, groq, ollama)").option("--json", "Output as JSON").action(async (opts) => {
2237
+ const client = makeClient();
2238
+ const spinner = spin("Fetching models\u2026");
2239
+ try {
2240
+ const res = await client.models.list();
2241
+ spinner.stop();
2242
+ const all = res?.data ?? res ?? [];
2243
+ if (opts.json) return jsonOut(all);
2244
+ const filtered = opts.provider ? all.filter((m) => m.provider === opts.provider) : all;
2245
+ if (filtered.length === 0) {
2246
+ console.log(c.warn(" No models found."));
2247
+ return;
2248
+ }
2249
+ const grouped = {};
2250
+ for (const m of filtered) {
2251
+ if (!grouped[m.provider]) grouped[m.provider] = [];
2252
+ grouped[m.provider].push(m);
2253
+ }
2254
+ for (const [provider, models] of Object.entries(grouped)) {
2255
+ console.log(`
2256
+ ${c.bold(provider.toUpperCase())}`);
2257
+ for (const m of models) {
2258
+ const tags = [
2259
+ m.tier,
2260
+ m.supportsTools ? "tools" : "",
2261
+ m.supportsVision ? "vision" : ""
2262
+ ].filter(Boolean).join(", ");
2263
+ const price = m.inputPricePer1kTokens > 0 ? c.dim(` ($${m.inputPricePer1kTokens}/$${m.outputPricePer1kTokens} /1k)`) : c.dim(" (free/local)");
2264
+ console.log(` ${c.id(m.modelId.padEnd(36))} ${m.displayName.padEnd(24)} ${c.dim(tags)}${price}`);
2265
+ }
2266
+ }
2267
+ console.log();
2268
+ } catch (err) {
2269
+ spinner.stop();
2270
+ printError(err);
2271
+ process.exit(1);
2272
+ }
2273
+ });
2274
+ return cmd;
2275
+ }
2276
+
2277
+ // src/commands/memory.ts
2278
+ var import_commander13 = require("commander");
2279
+ function memoryCommand() {
2280
+ const cmd = new import_commander13.Command("memory").description("View and manage agent memories");
2281
+ cmd.command("list").description("List memories for an agent").option("--agent <agentId>", "Agent ID (defaults to configured agent)").option("--type <type>", "Filter by type: episodic | semantic | procedural").option("--limit <n>", "Max results", "50").option("--json", "Output as JSON").action(async (opts) => {
2282
+ const cfg = loadConfig();
2283
+ const agentId = opts.agent ?? cfg.defaultAgentId;
2284
+ if (!agentId) {
2285
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
2286
+ process.exit(1);
2287
+ }
2288
+ const spinner = spin("Fetching memories\u2026");
2289
+ try {
2290
+ const client = makeClient();
2291
+ const res = await client.memory.list(agentId, {
2292
+ type: opts.type,
2293
+ limit: parseInt(opts.limit, 10)
2294
+ });
2295
+ const memories = res?.data ?? res ?? [];
2296
+ spinner.stop();
2297
+ if (opts.json) return jsonOut(memories);
2298
+ section(`Memories for ${agentId.slice(0, 12)}\u2026 (${memories.length})`);
2299
+ if (memories.length === 0) {
2300
+ console.log(c.dim(" No memories yet"));
2301
+ return;
2302
+ }
2303
+ table(
2304
+ memories.map((m) => ({
2305
+ ID: m.memoryId?.slice(0, 8) + "\u2026",
2306
+ Type: m.memoryType ?? "",
2307
+ Content: (m.content ?? "").slice(0, 60),
2308
+ Created: relativeTime(m.createdAt)
2309
+ })),
2310
+ ["ID", "Type", "Content", "Created"]
2311
+ );
2312
+ } catch (err) {
2313
+ spinner.stop();
2314
+ printError(err);
2315
+ process.exit(1);
2316
+ }
2317
+ });
2318
+ cmd.command("stats").description("Show memory statistics for an agent").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
2319
+ const cfg = loadConfig();
2320
+ const agentId = opts.agent ?? cfg.defaultAgentId;
2321
+ if (!agentId) {
2322
+ console.error(c.error("Specify --agent <agentId>"));
2323
+ process.exit(1);
2324
+ }
2325
+ const spinner = spin("Fetching stats\u2026");
2326
+ try {
2327
+ const client = makeClient();
2328
+ const res = await client.memory.stats(agentId);
2329
+ const stats = res?.data ?? res;
2330
+ spinner.stop();
2331
+ if (opts.json) return jsonOut(stats);
2332
+ section("Memory Stats");
2333
+ detail([
2334
+ ["Total", String(stats.totalCount ?? 0)],
2335
+ ["Episodic", String(stats.episodicCount ?? 0)],
2336
+ ["Semantic", String(stats.semanticCount ?? 0)],
2337
+ ["Procedural", String(stats.proceduralCount ?? 0)]
2338
+ ]);
2339
+ } catch (err) {
2340
+ spinner.stop();
2341
+ printError(err);
2342
+ process.exit(1);
2343
+ }
2344
+ });
2345
+ cmd.command("create").description("Manually add a memory for an agent").requiredOption("--agent <agentId>", "Agent ID").requiredOption("--content <text>", "Memory content").option("--type <type>", "Memory type: episodic | semantic | procedural", "semantic").option("--json", "Output as JSON").action(async (opts) => {
2346
+ const spinner = spin("Creating memory\u2026");
2347
+ try {
2348
+ const client = makeClient();
2349
+ const res = await client.memory.create({
2350
+ agentId: opts.agent,
2351
+ content: opts.content,
2352
+ memoryType: opts.type
2353
+ });
2354
+ const memory = res?.data ?? res;
2355
+ spinner.stop();
2356
+ if (opts.json) return jsonOut(memory);
2357
+ console.log(`
2358
+ ${sym.ok} Memory created`);
2359
+ detail([
2360
+ ["ID", c.id(memory.memoryId)],
2361
+ ["Type", memory.memoryType ?? ""],
2362
+ ["Content", memory.content ?? ""]
2363
+ ]);
2364
+ } catch (err) {
2365
+ spinner.stop();
2366
+ printError(err);
2367
+ process.exit(1);
2368
+ }
2369
+ });
2370
+ cmd.command("delete <memoryId>").description("Delete a memory by ID").option("--json", "Output as JSON").action(async (memoryId, opts) => {
2371
+ const spinner = spin("Deleting memory\u2026");
2372
+ try {
2373
+ const client = makeClient();
2374
+ await client.memory.delete(memoryId);
2375
+ spinner.stop();
2376
+ if (opts.json) return jsonOut({ deleted: true, memoryId });
2377
+ console.log(`
2378
+ ${sym.ok} Memory ${c.id(memoryId)} deleted`);
2379
+ } catch (err) {
2380
+ spinner.stop();
2381
+ printError(err);
2382
+ process.exit(1);
2383
+ }
2384
+ });
2385
+ cmd.command("search <query>").description("Semantic search over agent memories").option("--agent <agentId>", "Agent ID").option("--limit <n>", "Max results", "10").option("--json", "Output as JSON").action(async (query, opts) => {
2386
+ const cfg = loadConfig();
2387
+ const agentId = opts.agent ?? cfg.defaultAgentId;
2388
+ if (!agentId) {
2389
+ console.error(c.error("Specify --agent <agentId>"));
2390
+ process.exit(1);
2391
+ }
2392
+ const spinner = spin("Searching memories\u2026");
2393
+ try {
2394
+ const client = makeClient();
2395
+ const res = await client.memory.retrieve(agentId, query, parseInt(opts.limit, 10));
2396
+ const memories = res?.data ?? res ?? [];
2397
+ spinner.stop();
2398
+ if (opts.json) return jsonOut(memories);
2399
+ section(`Search results (${memories.length})`);
2400
+ if (memories.length === 0) {
2401
+ console.log(c.dim(" No relevant memories found"));
2402
+ return;
2403
+ }
2404
+ memories.forEach((m, i) => {
2405
+ console.log(`
2406
+ ${c.dim(`${i + 1}.`)} ${m.content ?? ""}`);
2407
+ console.log(` ${c.dim(`type: ${m.memoryType ?? ""} \xB7 ${relativeTime(m.createdAt)}`)}`);
2408
+ });
2409
+ } catch (err) {
2410
+ spinner.stop();
2411
+ printError(err);
2412
+ process.exit(1);
2413
+ }
2414
+ });
2415
+ return cmd;
2416
+ }
2417
+
2418
+ // src/commands/usage.ts
2419
+ var import_commander14 = require("commander");
2420
+ function usageCommand() {
2421
+ const cmd = new import_commander14.Command("usage").description("View token usage and cost by agent");
2422
+ cmd.command("agents").description("Show usage summary for all your agents").option("--owner <address>", "Owner address (defaults to configured initiator)").option("--from <date>", "Start date (ISO, e.g. 2025-01-01)").option("--to <date>", "End date (ISO)").option("--json", "Output as JSON").action(async (opts) => {
2423
+ const cfg = loadConfig();
2424
+ const owner = opts.owner ?? cfg.initiator;
2425
+ if (!owner) {
2426
+ console.error(c.error("Specify --owner or run `agc login` first"));
2427
+ process.exit(1);
2428
+ }
2429
+ const spinner = spin("Fetching agents\u2026");
2430
+ try {
2431
+ const client = makeClient();
2432
+ const agentsRes = await client.agents.list(owner);
2433
+ const agents = agentsRes?.data ?? [];
2434
+ spinner.stop();
2435
+ if (agents.length === 0) {
2436
+ console.log(c.dim("No agents found"));
2437
+ return;
2438
+ }
2439
+ spin("Fetching usage\u2026");
2440
+ const rows = await Promise.allSettled(
2441
+ agents.map(
2442
+ (a) => client.usage.getAgentUsage(a.agentId, {
2443
+ from: opts.from,
2444
+ to: opts.to
2445
+ }).then((r) => ({
2446
+ agentId: a.agentId,
2447
+ name: a.name || a.agentId.slice(0, 12),
2448
+ ...r?.data ?? r ?? {}
2449
+ }))
2450
+ )
2451
+ );
2452
+ const data = rows.filter((r) => r.status === "fulfilled").map((r) => r.value);
2453
+ if (opts.json) return jsonOut(data);
2454
+ let totalTokens = 0, totalCost = 0, totalCalls = 0;
2455
+ data.forEach((r) => {
2456
+ totalTokens += r.totalTokens ?? 0;
2457
+ totalCost += r.totalCostUsd ?? 0;
2458
+ totalCalls += r.callCount ?? 0;
2459
+ });
2460
+ section("Usage Summary");
2461
+ detail([
2462
+ ["Total tokens", totalTokens.toLocaleString()],
2463
+ ["Total cost", `$${totalCost.toFixed(4)} USD`],
2464
+ ["LLM calls", totalCalls.toLocaleString()]
2465
+ ]);
2466
+ const active = data.filter((r) => (r.totalTokens ?? 0) > 0);
2467
+ if (active.length) {
2468
+ console.log("");
2469
+ table(
2470
+ active.sort((a, b) => (b.totalCostUsd ?? 0) - (a.totalCostUsd ?? 0)).map((r) => ({
2471
+ Agent: r.name,
2472
+ Calls: (r.callCount ?? 0).toLocaleString(),
2473
+ Tokens: (r.totalTokens ?? 0).toLocaleString(),
2474
+ "Cost $": (r.totalCostUsd ?? 0).toFixed(4)
2475
+ })),
2476
+ ["Agent", "Calls", "Tokens", "Cost $"]
2477
+ );
2478
+ }
2479
+ } catch (err) {
2480
+ printError(err);
2481
+ process.exit(1);
2482
+ }
2483
+ });
2484
+ cmd.command("agent <agentId>").description("Show detailed usage for a specific agent").option("--from <date>", "Start date (ISO)").option("--to <date>", "End date (ISO)").option("--json", "Output as JSON").action(async (agentId, opts) => {
2485
+ const spinner = spin("Fetching usage\u2026");
2486
+ try {
2487
+ const client = makeClient();
2488
+ const res = await client.usage.getAgentUsage(agentId, {
2489
+ from: opts.from,
2490
+ to: opts.to
2491
+ });
2492
+ const data = res?.data ?? res;
2493
+ spinner.stop();
2494
+ if (opts.json) return jsonOut(data);
2495
+ section(`Usage \u2014 ${agentId.slice(0, 12)}\u2026`);
2496
+ detail([
2497
+ ["Calls", (data.callCount ?? 0).toLocaleString()],
2498
+ ["Input tokens", (data.totalInputTokens ?? 0).toLocaleString()],
2499
+ ["Output tokens", (data.totalOutputTokens ?? 0).toLocaleString()],
2500
+ ["Total tokens", (data.totalTokens ?? 0).toLocaleString()],
2501
+ ["Cost", `$${(data.totalCostUsd ?? 0).toFixed(6)} USD`]
2502
+ ]);
2503
+ } catch (err) {
2504
+ spinner.stop();
2505
+ printError(err);
2506
+ process.exit(1);
2507
+ }
2508
+ });
2509
+ return cmd;
2510
+ }
2511
+
2512
+ // src/commands/logs.ts
2513
+ var import_commander15 = require("commander");
2514
+ var STATUS_COLOR = {
2515
+ success: (s) => c.bold(s),
2516
+ error: (s) => c.error(s),
2517
+ warning: (s) => c.warn(s)
2518
+ };
2519
+ function colorStatus(status) {
2520
+ return (STATUS_COLOR[status] ?? c.dim)(status);
2521
+ }
2522
+ function logsCommand() {
2523
+ const cmd = new import_commander15.Command("logs").description("View agent activity logs");
2524
+ cmd.command("list").alias("ls").description("List recent log entries for an agent").option("--agent <agentId>", "Agent ID (defaults to configured agent)").option("--session <sessionId>", "Filter by session ID").option("--status <status>", "Filter: success | error | warning").option("--limit <n>", "Max entries to show", "50").option("--json", "Output as JSON").action(async (opts) => {
2525
+ const cfg = loadConfig();
2526
+ const agentId = opts.agent ?? cfg.defaultAgentId;
2527
+ if (!agentId) {
2528
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
2529
+ process.exit(1);
2530
+ }
2531
+ const spinner = spin("Fetching logs\u2026");
2532
+ try {
2533
+ const client = makeClient();
2534
+ const qs = new URLSearchParams({ limit: opts.limit });
2535
+ if (opts.session) qs.set("sessionId", opts.session);
2536
+ const res = await client.request("GET", `/v1/logs/agents/${agentId}?${qs}`);
2537
+ let logs = res?.data ?? res ?? [];
2538
+ if (opts.status) logs = logs.filter((l) => l.status === opts.status);
2539
+ spinner.stop();
2540
+ if (opts.json) return jsonOut(logs);
2541
+ section(`Logs \u2014 ${agentId.slice(0, 12)}\u2026 (${logs.length})`);
2542
+ if (logs.length === 0) {
2543
+ console.log(c.dim(" No logs yet"));
2544
+ return;
2545
+ }
2546
+ logs.forEach((l) => {
2547
+ const tools = (l.tools ?? []).length > 0 ? ` ${c.dim(`[${l.tools.length} tools]`)}` : "";
2548
+ const rt = l.responseTime > 0 ? c.dim(` ${l.responseTime}ms`) : "";
2549
+ console.log(
2550
+ ` ${colorStatus((l.status ?? "info").padEnd(7))} ${c.bold(l.action ?? "")}${rt}${tools}`
2551
+ );
2552
+ if (l.message) {
2553
+ console.log(` ${" ".repeat(10)}${c.dim(l.message.slice(0, 80))}`);
2554
+ }
2555
+ console.log(` ${" ".repeat(10)}${c.dim(relativeTime(l.timestamp))}`);
2556
+ console.log("");
2557
+ });
2558
+ } catch (err) {
2559
+ spin("").stop();
2560
+ printError(err);
2561
+ process.exit(1);
2562
+ }
2563
+ });
2564
+ cmd.command("errors").description("Show only error log entries for an agent").option("--agent <agentId>", "Agent ID").option("--limit <n>", "Max entries", "20").option("--json", "Output as JSON").action(async (opts) => {
2565
+ const cfg = loadConfig();
2566
+ const agentId = opts.agent ?? cfg.defaultAgentId;
2567
+ if (!agentId) {
2568
+ console.error(c.error("Specify --agent <agentId>"));
2569
+ process.exit(1);
2570
+ }
2571
+ const spinner = spin("Fetching error logs\u2026");
2572
+ try {
2573
+ const client = makeClient();
2574
+ const res = await client.request("GET", `/v1/logs/agents/${agentId}?limit=${opts.limit}`);
2575
+ const errors = (res?.data ?? []).filter((l) => l.status === "error");
2576
+ spinner.stop();
2577
+ if (opts.json) return jsonOut(errors);
2578
+ section(`Errors \u2014 ${agentId.slice(0, 12)}\u2026 (${errors.length})`);
2579
+ if (errors.length === 0) {
2580
+ console.log(`${sym.ok} No errors found`);
2581
+ return;
2582
+ }
2583
+ errors.forEach((l) => {
2584
+ console.log(` ${c.error("\u2716")} ${c.bold(l.action ?? "")} ${c.dim(relativeTime(l.timestamp))}`);
2585
+ if (l.message) console.log(` ${c.dim(l.message)}`);
2586
+ console.log("");
2587
+ });
2588
+ } catch (err) {
2589
+ spinner.stop();
2590
+ printError(err);
2591
+ process.exit(1);
2592
+ }
2593
+ });
2594
+ return cmd;
2595
+ }
2596
+
1944
2597
  // src/bin.ts
1945
- var program = new import_commander12.Command();
1946
- program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.1.0", "-v, --version");
2598
+ var CONFIG_FILE3 = (0, import_path3.join)((0, import_os3.homedir)(), ".agc", "config.json");
2599
+ async function interactiveMenu() {
2600
+ banner();
2601
+ const cfg = loadConfig();
2602
+ const isSetup = !!(cfg.apiKey && cfg.initiator);
2603
+ if (!isSetup) {
2604
+ console.log(c.bold(" Welcome to Agent Commons CLI!"));
2605
+ console.log(c.dim(" Looks like this is your first time here \u2014 let's get you set up.\n"));
2606
+ console.log(` ${sym.arrow} Running ${c.bold("agc login")} to configure your credentials\u2026
2607
+ `);
2608
+ runSubcommand(["login"]);
2609
+ return;
2610
+ }
2611
+ console.log(
2612
+ ` ${c.dim("Connected to")} ${c.primary(cfg.apiUrl)} ${c.dim("\xB7")} ${c.dim("Wallet")} ${c.id(cfg.initiator.slice(0, 8) + "\u2026" + cfg.initiator.slice(-4))}
2613
+ `
2614
+ );
2615
+ const action = await select("What would you like to do?", [
2616
+ { label: "Chat with an agent", value: "chat", hint: "agc chat" },
2617
+ { label: "Run an agent (one-shot)", value: "run", hint: "agc run" },
2618
+ { label: "View sessions", value: "sessions", hint: "agc sessions list" },
2619
+ { label: "Manage agents", value: "agents", hint: "agc agents list" },
2620
+ { label: "Tasks", value: "tasks", hint: "agc task list" },
2621
+ { label: "Workflows", value: "workflows", hint: "agc workflow list" },
2622
+ { label: "MCP servers", value: "mcp", hint: "agc mcp list" },
2623
+ { label: "Skills", value: "skills", hint: "agc skills list" },
2624
+ { label: "Wallet & balance", value: "wallet", hint: "agc wallet balance" },
2625
+ { label: "Usage & cost", value: "usage", hint: "agc usage" },
2626
+ { label: "Logs", value: "logs", hint: "agc logs" },
2627
+ { label: "Config & credentials", value: "config", hint: "agc config get" },
2628
+ { label: "Exit", value: "exit" }
2629
+ ]);
2630
+ if (action === "exit") {
2631
+ process.exit(0);
2632
+ }
2633
+ const commandMap = {
2634
+ chat: cfg.defaultAgentId ? ["chat", "--agent", cfg.defaultAgentId] : ["chat", "--agent"],
2635
+ run: cfg.defaultAgentId ? ["run", "--agent", cfg.defaultAgentId, "--message"] : ["run", "--agent"],
2636
+ sessions: ["sessions", "list"],
2637
+ agents: ["agents", "list"],
2638
+ tasks: ["task", "list"],
2639
+ workflows: ["workflow", "list"],
2640
+ mcp: ["mcp", "list"],
2641
+ skills: ["skills", "list"],
2642
+ wallet: ["wallet", "balance"],
2643
+ usage: ["usage"],
2644
+ logs: ["logs"],
2645
+ config: ["config", "get"],
2646
+ exit: []
2647
+ };
2648
+ if ((action === "chat" || action === "run") && !cfg.defaultAgentId) {
2649
+ console.log(
2650
+ `
2651
+ ${c.warn("\u26A0")} No default agent configured.
2652
+ ${sym.arrow} ${c.dim("Run")} ${c.bold("agc agents list")} ${c.dim("to find an agent ID, then")}
2653
+ ${sym.arrow} ${c.dim("Run")} ${c.bold("agc config set defaultAgentId <id>")} ${c.dim("to set a default.")}
2654
+ `
2655
+ );
2656
+ console.log(` ${c.dim("Or pass it directly: ")}${c.bold(`agc ${action} --agent <id>`)}
2657
+ `);
2658
+ return;
2659
+ }
2660
+ runSubcommand(commandMap[action]);
2661
+ }
2662
+ function runSubcommand(args) {
2663
+ const child = (0, import_child_process2.spawn)(process.argv[0], [process.argv[1], ...args], {
2664
+ stdio: "inherit"
2665
+ });
2666
+ child.on("exit", (code) => process.exit(code ?? 0));
2667
+ }
2668
+ var program = new import_commander16.Command();
2669
+ program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.1.4", "-v, --version").action(async () => {
2670
+ await interactiveMenu();
2671
+ });
1947
2672
  program.addCommand(loginCommand());
1948
2673
  program.addCommand(logoutCommand());
1949
2674
  program.addCommand(whoamiCommand());
@@ -1958,9 +2683,17 @@ program.addCommand(chatCommand());
1958
2683
  program.addCommand(mcpCommand());
1959
2684
  program.addCommand(skillsCommand());
1960
2685
  program.addCommand(walletCommand());
2686
+ program.addCommand(modelsCommand());
2687
+ program.addCommand(memoryCommand());
2688
+ program.addCommand(usageCommand());
2689
+ program.addCommand(logsCommand());
1961
2690
  program.on("command:*", () => {
1962
- console.error(`Unknown command: ${program.args.join(" ")}
1963
- Run \`agc --help\` to see available commands.`);
2691
+ console.error(
2692
+ `
2693
+ ${c.error("Unknown command:")} ${program.args.join(" ")}
2694
+ Run ${c.bold("agc --help")} to see available commands, or just ${c.bold("agc")} for the interactive menu.
2695
+ `
2696
+ );
1964
2697
  process.exit(1);
1965
2698
  });
1966
2699
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-commons/cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Agent Commons CLI — chat, run, and manage agents from your terminal",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -14,7 +14,7 @@
14
14
  "commander": "^12.1.0",
15
15
  "chalk": "^5.3.0",
16
16
  "ora": "^8.1.1",
17
- "@agent-commons/sdk": "0.1.4"
17
+ "@agent-commons/sdk": "0.1.6"
18
18
  },
19
19
  "devDependencies": {
20
20
  "tsup": "^8.3.5",