@agent-commons/cli 0.1.1

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 +1961 -0
  2. package/package.json +35 -0
package/dist/bin.js ADDED
@@ -0,0 +1,1961 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/bin.ts
27
+ var import_commander12 = require("commander");
28
+
29
+ // src/commands/login.ts
30
+ var import_commander = require("commander");
31
+ var readline = __toESM(require("readline"));
32
+
33
+ // src/config.ts
34
+ var import_fs = require("fs");
35
+ var import_os = require("os");
36
+ var import_path = require("path");
37
+ var import_sdk = require("@agent-commons/sdk");
38
+ var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".agc");
39
+ var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
40
+ var DEFAULT_API_URL = process.env.AGC_API_URL ?? "http://localhost:3001";
41
+ function loadConfig() {
42
+ const fromEnv = {
43
+ ...process.env.AGC_API_URL && { apiUrl: process.env.AGC_API_URL },
44
+ ...process.env.AGC_API_KEY && { apiKey: process.env.AGC_API_KEY },
45
+ ...process.env.AGC_INITIATOR && { initiator: process.env.AGC_INITIATOR },
46
+ ...process.env.AGC_AGENT_ID && { defaultAgentId: process.env.AGC_AGENT_ID }
47
+ };
48
+ let fromFile = {};
49
+ if ((0, import_fs.existsSync)(CONFIG_FILE)) {
50
+ try {
51
+ fromFile = JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf8"));
52
+ } catch {
53
+ }
54
+ }
55
+ return {
56
+ apiUrl: DEFAULT_API_URL,
57
+ ...fromFile,
58
+ ...fromEnv
59
+ };
60
+ }
61
+ function saveConfig(updates) {
62
+ const current = loadConfig();
63
+ const next = { ...current, ...updates };
64
+ if (!(0, import_fs.existsSync)(CONFIG_DIR)) (0, import_fs.mkdirSync)(CONFIG_DIR, { recursive: true });
65
+ (0, import_fs.writeFileSync)(CONFIG_FILE, JSON.stringify(next, null, 2), { mode: 384 });
66
+ }
67
+ function clearConfig() {
68
+ if ((0, import_fs.existsSync)(CONFIG_FILE)) {
69
+ (0, import_fs.writeFileSync)(CONFIG_FILE, JSON.stringify({ apiUrl: DEFAULT_API_URL }, null, 2));
70
+ }
71
+ }
72
+ function makeClient(overrides) {
73
+ const cfg = { ...loadConfig(), ...overrides };
74
+ return new import_sdk.CommonsClient({
75
+ baseUrl: cfg.apiUrl,
76
+ apiKey: cfg.apiKey,
77
+ initiator: cfg.initiator
78
+ });
79
+ }
80
+
81
+ // src/ui.ts
82
+ var import_chalk = __toESM(require("chalk"));
83
+ var import_ora = __toESM(require("ora"));
84
+ var c = {
85
+ primary: (s) => import_chalk.default.cyan(s),
86
+ success: (s) => import_chalk.default.green(s),
87
+ warn: (s) => import_chalk.default.yellow(s),
88
+ error: (s) => import_chalk.default.red(s),
89
+ dim: (s) => import_chalk.default.dim(s),
90
+ bold: (s) => import_chalk.default.bold(s),
91
+ id: (s) => import_chalk.default.magenta(s),
92
+ label: (s) => import_chalk.default.cyan.bold(s)
93
+ };
94
+ var sym = {
95
+ ok: import_chalk.default.green("\u2713"),
96
+ fail: import_chalk.default.red("\u2717"),
97
+ arrow: import_chalk.default.cyan("\u2192"),
98
+ bullet: import_chalk.default.dim("\u2022"),
99
+ dot: import_chalk.default.dim("\xB7")
100
+ };
101
+ function spin(text) {
102
+ return (0, import_ora.default)({ text, color: "cyan" }).start();
103
+ }
104
+ function table(rows, columns) {
105
+ if (rows.length === 0) {
106
+ console.log(c.dim(" (none)"));
107
+ return;
108
+ }
109
+ const widths = columns.map(
110
+ (col) => Math.max(col.length, ...rows.map((r) => (r[col] ?? "").length))
111
+ );
112
+ const header = columns.map((col, i) => c.label(col.toUpperCase().padEnd(widths[i]))).join(" ");
113
+ const divider = widths.map((w) => import_chalk.default.dim("\u2500".repeat(w))).join(" ");
114
+ console.log(" " + header);
115
+ console.log(" " + divider);
116
+ for (const row of rows) {
117
+ const line = columns.map((col, i) => (row[col] ?? "").padEnd(widths[i])).join(" ");
118
+ console.log(" " + line);
119
+ }
120
+ }
121
+ function section(title) {
122
+ console.log("\n" + c.bold(title));
123
+ }
124
+ function detail(pairs) {
125
+ const labelWidth = Math.max(...pairs.map(([k]) => k.length));
126
+ for (const [key, val] of pairs) {
127
+ if (val === void 0 || val === "") continue;
128
+ console.log(` ${c.dim(key.padEnd(labelWidth))} ${val}`);
129
+ }
130
+ }
131
+ function relativeTime(iso) {
132
+ const ms = Date.now() - new Date(iso).getTime();
133
+ if (ms < 6e4) return `${Math.round(ms / 1e3)}s ago`;
134
+ if (ms < 36e5) return `${Math.round(ms / 6e4)}m ago`;
135
+ if (ms < 864e5) return `${Math.round(ms / 36e5)}h ago`;
136
+ return `${Math.round(ms / 864e5)}d ago`;
137
+ }
138
+ function printError(err) {
139
+ if (err instanceof Error) {
140
+ console.error(c.error(`
141
+ Error: ${err.message}`));
142
+ } else {
143
+ console.error(c.error(`
144
+ Unknown error: ${String(err)}`));
145
+ }
146
+ }
147
+ function jsonOut(data) {
148
+ process.stdout.write(JSON.stringify(data, null, 2) + "\n");
149
+ }
150
+ function statusBadge(status) {
151
+ switch (status) {
152
+ case "completed":
153
+ case "connected":
154
+ case "active":
155
+ case "success":
156
+ return import_chalk.default.green(status);
157
+ case "running":
158
+ case "working":
159
+ case "submitted":
160
+ return import_chalk.default.cyan(status);
161
+ case "pending":
162
+ return import_chalk.default.yellow(status);
163
+ case "failed":
164
+ case "error":
165
+ case "canceled":
166
+ return import_chalk.default.red(status);
167
+ case "cancelled":
168
+ return import_chalk.default.gray(status);
169
+ case "awaiting_approval":
170
+ return import_chalk.default.magenta(status);
171
+ default:
172
+ return import_chalk.default.dim(status);
173
+ }
174
+ }
175
+
176
+ // src/commands/login.ts
177
+ function prompt(question, hidden = false) {
178
+ return new Promise((resolve) => {
179
+ const rl = readline.createInterface({
180
+ input: process.stdin,
181
+ output: hidden ? void 0 : process.stdout,
182
+ terminal: hidden
183
+ });
184
+ if (hidden) {
185
+ process.stdout.write(question);
186
+ process.stdin.once("data", (data) => {
187
+ process.stdout.write("\n");
188
+ rl.close();
189
+ resolve(data.toString().trim());
190
+ });
191
+ process.stdin.setRawMode?.(false);
192
+ } else {
193
+ rl.question(question, (ans) => {
194
+ rl.close();
195
+ resolve(ans.trim());
196
+ });
197
+ }
198
+ });
199
+ }
200
+ function loginCommand() {
201
+ const cmd = new import_commander.Command("login").description("Configure API credentials");
202
+ 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
+ try {
204
+ 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
+ let apiKey = opts.apiKey;
207
+ if (!apiKey) {
208
+ apiKey = await prompt(`API Key [${current.apiKey ? "****" : "none"}]: `);
209
+ if (!apiKey) apiKey = current.apiKey;
210
+ }
211
+ let initiator = opts.initiator;
212
+ if (!initiator) {
213
+ initiator = await prompt(`Initiator ID [${current.initiator ?? "none"}]: `);
214
+ if (!initiator) initiator = current.initiator;
215
+ }
216
+ saveConfig({ apiUrl, apiKey, initiator });
217
+ console.log(`
218
+ ${sym.ok} Credentials saved to ~/.agc/config.json`);
219
+ console.log(c.dim(" Run `agc whoami` to verify the connection."));
220
+ } catch (err) {
221
+ printError(err);
222
+ process.exit(1);
223
+ }
224
+ });
225
+ return cmd;
226
+ }
227
+ function logoutCommand() {
228
+ return new import_commander.Command("logout").description("Clear stored credentials").action(() => {
229
+ clearConfig();
230
+ console.log(`${sym.ok} Credentials cleared.`);
231
+ });
232
+ }
233
+ function whoamiCommand() {
234
+ return new import_commander.Command("whoami").description("Show current configuration and verify API connectivity").option("--json", "Output as JSON").action(async (opts) => {
235
+ const cfg = loadConfig();
236
+ if (opts.json) {
237
+ console.log(JSON.stringify({ apiUrl: cfg.apiUrl, initiator: cfg.initiator, hasApiKey: !!cfg.apiKey }, null, 2));
238
+ return;
239
+ }
240
+ console.log(`
241
+ ${c.bold("Current configuration")}`);
242
+ detail([
243
+ ["API URL", cfg.apiUrl],
244
+ ["Initiator", cfg.initiator ?? c.dim("(not set)")],
245
+ ["API Key", cfg.apiKey ? `****${cfg.apiKey.slice(-4)}` : c.dim("(not set)")],
246
+ ["Agent ID", cfg.defaultAgentId ?? c.dim("(not set)")]
247
+ ]);
248
+ try {
249
+ const client = makeClient();
250
+ if (cfg.initiator) {
251
+ await client.agents.list(cfg.initiator);
252
+ console.log(`
253
+ ${sym.ok} ${c.success("Connected")} to ${cfg.apiUrl}`);
254
+ } else {
255
+ console.log(`
256
+ ${c.warn("\u26A0")} Set an initiator to verify connectivity.`);
257
+ }
258
+ } catch (err) {
259
+ console.log(`
260
+ ${sym.fail} ${c.error("Could not reach API")}: ${err.message}`);
261
+ }
262
+ });
263
+ }
264
+ function configCommand() {
265
+ const cmd = new import_commander.Command("config").description("Get or set configuration values");
266
+ cmd.command("set <key> <value>").description("Set a config value (apiUrl, apiKey, initiator, defaultAgentId)").action((key, value) => {
267
+ const allowed = ["apiUrl", "apiKey", "initiator", "defaultAgentId"];
268
+ if (!allowed.includes(key)) {
269
+ console.error(c.error(`Unknown key "${key}". Allowed: ${allowed.join(", ")}`));
270
+ process.exit(1);
271
+ }
272
+ saveConfig({ [key]: value });
273
+ console.log(`${sym.ok} ${key} = ${key === "apiKey" ? "****" : value}`);
274
+ });
275
+ cmd.command("get [key]").description("Get a config value or show all").action((key) => {
276
+ const cfg = loadConfig();
277
+ if (key) {
278
+ console.log(cfg[key] ?? c.dim("(not set)"));
279
+ } else {
280
+ detail([
281
+ ["apiUrl", cfg.apiUrl],
282
+ ["initiator", cfg.initiator ?? ""],
283
+ ["apiKey", cfg.apiKey ? `****${cfg.apiKey.slice(-4)}` : ""],
284
+ ["defaultAgentId", cfg.defaultAgentId ?? ""]
285
+ ]);
286
+ }
287
+ });
288
+ return cmd;
289
+ }
290
+
291
+ // src/commands/agents.ts
292
+ var import_commander2 = require("commander");
293
+ function agentsCommand() {
294
+ const cmd = new import_commander2.Command("agents").description("Manage agents");
295
+ cmd.command("list").description("List agents owned by the current initiator").option("--json", "Output as JSON").action(async (opts) => {
296
+ const cfg = loadConfig();
297
+ if (!cfg.initiator) {
298
+ console.error(c.error("No initiator set. Run `agc login` first."));
299
+ process.exit(1);
300
+ }
301
+ const spinner = spin("Fetching agents\u2026");
302
+ try {
303
+ const client = makeClient();
304
+ const res = await client.agents.list(cfg.initiator);
305
+ const agents = res?.data ?? res ?? [];
306
+ spinner.stop();
307
+ if (opts.json) return jsonOut(agents);
308
+ section(`Agents (${agents.length})`);
309
+ table(
310
+ agents.map((a) => ({
311
+ ID: a.agentId.slice(0, 8) + "\u2026",
312
+ Name: a.name,
313
+ Model: `${a.modelProvider}/${a.modelId}`,
314
+ Created: relativeTime(a.createdAt)
315
+ })),
316
+ ["ID", "Name", "Model", "Created"]
317
+ );
318
+ } catch (err) {
319
+ spinner.stop();
320
+ printError(err);
321
+ process.exit(1);
322
+ }
323
+ });
324
+ cmd.command("get <agentId>").description("Show details for an agent").option("--json", "Output as JSON").action(async (agentId, opts) => {
325
+ const spinner = spin("Fetching agent\u2026");
326
+ try {
327
+ const client = makeClient();
328
+ const res = await client.agents.get(agentId);
329
+ const agent = res?.data ?? res;
330
+ spinner.stop();
331
+ if (opts.json) return jsonOut(agent);
332
+ section(agent.name);
333
+ detail([
334
+ ["Agent ID", c.id(agent.agentId)],
335
+ ["Provider", `${agent.modelProvider} / ${agent.modelId}`],
336
+ ["Instructions", agent.instructions?.slice(0, 80) ?? c.dim("(none)")],
337
+ ["Tools", [...agent.commonTools ?? [], ...agent.externalTools ?? []].join(", ") || c.dim("(none)")],
338
+ ["Created", relativeTime(agent.createdAt)]
339
+ ]);
340
+ } catch (err) {
341
+ spinner.stop();
342
+ printError(err);
343
+ process.exit(1);
344
+ }
345
+ });
346
+ cmd.command("create").description("Create a new agent").requiredOption("--name <name>", "Agent name").option("--instructions <text>", "System instructions").option("--provider <provider>", "Model provider (openai|anthropic|google|groq)", "openai").option("--model <id>", "Model ID", "gpt-4o").option("--json", "Output as JSON").action(async (opts) => {
347
+ const cfg = loadConfig();
348
+ if (!cfg.initiator) {
349
+ console.error(c.error("No initiator set. Run `agc login` first."));
350
+ process.exit(1);
351
+ }
352
+ const spinner = spin("Creating agent\u2026");
353
+ try {
354
+ const client = makeClient();
355
+ const res = await client.agents.create({
356
+ name: opts.name,
357
+ instructions: opts.instructions,
358
+ owner: cfg.initiator,
359
+ modelProvider: opts.provider,
360
+ modelId: opts.model
361
+ });
362
+ const agent = res?.data ?? res;
363
+ spinner.stop();
364
+ if (opts.json) return jsonOut(agent);
365
+ console.log(`
366
+ ${sym.ok} Agent created`);
367
+ detail([
368
+ ["Agent ID", c.id(agent.agentId)],
369
+ ["Name", agent.name],
370
+ ["Model", `${agent.modelProvider}/${agent.modelId}`]
371
+ ]);
372
+ console.log(c.dim("\n Tip: agc config set defaultAgentId " + agent.agentId));
373
+ } catch (err) {
374
+ spinner.stop();
375
+ printError(err);
376
+ process.exit(1);
377
+ }
378
+ });
379
+ return cmd;
380
+ }
381
+
382
+ // src/commands/sessions.ts
383
+ var import_commander3 = require("commander");
384
+ function sessionsCommand() {
385
+ const cmd = new import_commander3.Command("sessions").description("Manage chat sessions");
386
+ 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) => {
387
+ const cfg = loadConfig();
388
+ if (!cfg.initiator) {
389
+ console.error(c.error("No initiator set. Run `agc login` first."));
390
+ process.exit(1);
391
+ }
392
+ const agentId = opts.agent ?? cfg.defaultAgentId;
393
+ if (!agentId) {
394
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
395
+ process.exit(1);
396
+ }
397
+ const spinner = spin("Fetching sessions\u2026");
398
+ try {
399
+ const client = makeClient();
400
+ const res = await client.sessions.list(agentId, cfg.initiator);
401
+ const sessions = res?.data ?? res ?? [];
402
+ spinner.stop();
403
+ if (opts.json) return jsonOut(sessions);
404
+ section(`Sessions (${sessions.length})`);
405
+ table(
406
+ sessions.map((s) => ({
407
+ ID: s.sessionId.slice(0, 8) + "\u2026",
408
+ Title: s.title ?? c.dim("(untitled)"),
409
+ Model: s.model?.modelId ?? s.model?.name ?? "",
410
+ Created: relativeTime(s.createdAt)
411
+ })),
412
+ ["ID", "Title", "Model", "Created"]
413
+ );
414
+ } catch (err) {
415
+ spinner.stop();
416
+ printError(err);
417
+ process.exit(1);
418
+ }
419
+ });
420
+ cmd.command("get <sessionId>").description("Show session details").option("--json", "Output as JSON").action(async (sessionId, opts) => {
421
+ const spinner = spin("Fetching session\u2026");
422
+ try {
423
+ const client = makeClient();
424
+ const res = await client.sessions.get(sessionId);
425
+ const session = res?.data ?? res;
426
+ spinner.stop();
427
+ if (opts.json) return jsonOut(session);
428
+ section("Session");
429
+ detail([
430
+ ["Session ID", c.id(session.sessionId)],
431
+ ["Title", session.title ?? c.dim("(untitled)")],
432
+ ["Agent ID", session.agentId],
433
+ ["Model", session.model?.modelId ?? session.model?.name ?? ""],
434
+ ["Initiator", session.initiator ?? ""],
435
+ ["Created", relativeTime(session.createdAt)]
436
+ ]);
437
+ } catch (err) {
438
+ spinner.stop();
439
+ printError(err);
440
+ process.exit(1);
441
+ }
442
+ });
443
+ cmd.command("create").description("Create a new session").option("--agent <agentId>", "Agent ID").option("--title <title>", "Session title").option("--model <id>", "Model ID (e.g. gpt-4o, claude-sonnet-4-6)").option("--provider <provider>", "Model provider").option("--json", "Output as JSON").action(async (opts) => {
444
+ const cfg = loadConfig();
445
+ const agentId = opts.agent ?? cfg.defaultAgentId;
446
+ if (!agentId) {
447
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
448
+ process.exit(1);
449
+ }
450
+ if (!cfg.initiator) {
451
+ console.error(c.error("No initiator set. Run `agc login` first."));
452
+ process.exit(1);
453
+ }
454
+ const spinner = spin("Creating session\u2026");
455
+ try {
456
+ const client = makeClient();
457
+ const res = await client.sessions.create({
458
+ agentId,
459
+ initiator: cfg.initiator,
460
+ title: opts.title,
461
+ ...opts.model && { model: { modelId: opts.model, provider: opts.provider } }
462
+ });
463
+ const session = res?.data ?? res;
464
+ spinner.stop();
465
+ if (opts.json) return jsonOut(session);
466
+ console.log(`
467
+ ${sym.ok} Session created`);
468
+ detail([
469
+ ["Session ID", c.id(session.sessionId)],
470
+ ["Title", session.title ?? c.dim("(untitled)")]
471
+ ]);
472
+ } catch (err) {
473
+ spinner.stop();
474
+ printError(err);
475
+ process.exit(1);
476
+ }
477
+ });
478
+ return cmd;
479
+ }
480
+
481
+ // src/commands/tools.ts
482
+ var import_commander4 = require("commander");
483
+ function toolsCommand() {
484
+ const cmd = new import_commander4.Command("tools").description("Discover and manage tools");
485
+ cmd.command("list").description("List available tools").option("--owner <id>", "Filter by owner ID").option("--json", "Output as JSON").action(async (opts) => {
486
+ const cfg = loadConfig();
487
+ const spinner = spin("Fetching tools\u2026");
488
+ try {
489
+ const client = makeClient();
490
+ const filter = opts.owner ? { owner: opts.owner } : {};
491
+ const res = await client.tools.list(filter);
492
+ const tools = res?.data ?? res ?? [];
493
+ spinner.stop();
494
+ if (opts.json) return jsonOut(tools);
495
+ section(`Tools (${tools.length})`);
496
+ table(
497
+ tools.map((t) => ({
498
+ ID: (t.toolId ?? "").slice(0, 8) + "\u2026",
499
+ Name: t.name ?? "",
500
+ Description: (t.description ?? "").slice(0, 50),
501
+ Tags: (t.tags ?? []).join(", ")
502
+ })),
503
+ ["ID", "Name", "Description", "Tags"]
504
+ );
505
+ } catch (err) {
506
+ spinner.stop();
507
+ printError(err);
508
+ process.exit(1);
509
+ }
510
+ });
511
+ cmd.command("get <toolId>").description("Show tool details and schema").option("--json", "Output as JSON").action(async (toolId, opts) => {
512
+ const spinner = spin("Fetching tool\u2026");
513
+ try {
514
+ const client = makeClient();
515
+ const res = await client.tools.list({ toolId });
516
+ const tools = res?.data ?? res ?? [];
517
+ const tool = tools.find((t) => t.toolId === toolId || t.name === toolId);
518
+ spinner.stop();
519
+ if (!tool) {
520
+ console.error(c.error(`Tool "${toolId}" not found.`));
521
+ process.exit(1);
522
+ }
523
+ if (opts.json) return jsonOut(tool);
524
+ section(tool.name);
525
+ detail([
526
+ ["Tool ID", c.id(tool.toolId)],
527
+ ["Description", tool.description ?? c.dim("(none)")],
528
+ ["Tags", (tool.tags ?? []).join(", ") || c.dim("(none)")],
529
+ ["Public", tool.isPublic ? "yes" : "no"],
530
+ ["Created", relativeTime(tool.createdAt)]
531
+ ]);
532
+ if (tool.schema) {
533
+ console.log("\n " + c.label("Schema"));
534
+ console.log(" " + JSON.stringify(tool.schema, null, 2).split("\n").join("\n "));
535
+ }
536
+ } catch (err) {
537
+ spinner.stop();
538
+ printError(err);
539
+ process.exit(1);
540
+ }
541
+ });
542
+ cmd.command("exec <toolName>").description("Execute a tool directly by name").option("--agent <agentId>", "Agent context for tool execution").option("--args <json>", "Tool arguments as JSON object", "{}").option("--json", "Output result as JSON").action(async (toolName, opts) => {
543
+ const cfg = loadConfig();
544
+ const agentId = opts.agent ?? cfg.defaultAgentId;
545
+ if (!agentId) {
546
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
547
+ process.exit(1);
548
+ }
549
+ let args = {};
550
+ try {
551
+ args = JSON.parse(opts.args);
552
+ } catch {
553
+ console.error(c.error("--args must be valid JSON"));
554
+ process.exit(1);
555
+ }
556
+ const prompt2 = `Call the tool "${toolName}" with these arguments: ${JSON.stringify(args)}. Return only the tool result, nothing else.`;
557
+ const spinner = spin(`Executing ${toolName}\u2026`);
558
+ try {
559
+ const client = makeClient();
560
+ const result = await client.run.once({
561
+ agentId,
562
+ messages: [{ role: "user", content: prompt2 }],
563
+ ...cfg.initiator && { initiatorId: cfg.initiator }
564
+ });
565
+ spinner.stop();
566
+ if (opts.json) return jsonOut(result);
567
+ console.log(`
568
+ ${sym.ok} ${c.label(toolName)}`);
569
+ const text = result?.content ?? result?.text ?? result?.message ?? JSON.stringify(result, null, 2);
570
+ console.log(text);
571
+ } catch (err) {
572
+ spinner.stop();
573
+ printError(err);
574
+ process.exit(1);
575
+ }
576
+ });
577
+ return cmd;
578
+ }
579
+
580
+ // src/commands/workflow.ts
581
+ var import_commander5 = require("commander");
582
+ function workflowCommand() {
583
+ const cmd = new import_commander5.Command("workflow").description("Run and monitor workflows").alias("wf");
584
+ cmd.command("list").description("List workflows owned by the current initiator").option("--json", "Output as JSON").action(async (opts) => {
585
+ const cfg = loadConfig();
586
+ if (!cfg.initiator) {
587
+ console.error(c.error("No initiator set. Run `agc login` first."));
588
+ process.exit(1);
589
+ }
590
+ const spinner = spin("Fetching workflows\u2026");
591
+ try {
592
+ const client = makeClient();
593
+ const workflows = await client.workflows.list(cfg.initiator, "user");
594
+ spinner.stop();
595
+ if (opts.json) return jsonOut(workflows);
596
+ section(`Workflows (${workflows.length})`);
597
+ table(
598
+ workflows.map((w) => ({
599
+ ID: w.workflowId.slice(0, 8) + "\u2026",
600
+ Name: w.name,
601
+ Nodes: String((w.definition?.nodes ?? []).length),
602
+ Public: w.isPublic ? "yes" : "no",
603
+ Created: relativeTime(w.createdAt)
604
+ })),
605
+ ["ID", "Name", "Nodes", "Public", "Created"]
606
+ );
607
+ } catch (err) {
608
+ spinner.stop();
609
+ printError(err);
610
+ process.exit(1);
611
+ }
612
+ });
613
+ cmd.command("get <workflowId>").description("Show workflow details").option("--json", "Output as JSON").action(async (workflowId, opts) => {
614
+ const spinner = spin("Fetching workflow\u2026");
615
+ try {
616
+ const client = makeClient();
617
+ const wf = await client.workflows.get(workflowId);
618
+ spinner.stop();
619
+ if (opts.json) return jsonOut(wf);
620
+ section(wf.name);
621
+ detail([
622
+ ["Workflow ID", c.id(wf.workflowId)],
623
+ ["Description", wf.description ?? c.dim("(none)")],
624
+ ["Nodes", String((wf.definition?.nodes ?? []).length)],
625
+ ["Public", wf.isPublic ? "yes" : "no"],
626
+ ["Created", relativeTime(wf.createdAt)]
627
+ ]);
628
+ if (wf.definition?.nodes?.length) {
629
+ console.log("\n " + c.label("Nodes"));
630
+ for (const node of wf.definition.nodes) {
631
+ console.log(` ${c.dim("\xB7")} ${node.id} ${c.dim("(" + (node.type ?? "tool") + ")")}`);
632
+ }
633
+ }
634
+ } catch (err) {
635
+ spinner.stop();
636
+ printError(err);
637
+ process.exit(1);
638
+ }
639
+ });
640
+ cmd.command("run <workflowId>").description("Execute a workflow").option("--agent <agentId>", "Agent context").option("--session <sessionId>", "Session context").option("--input <json>", "Input data as JSON string", "{}").option("--watch", "Stream execution progress via SSE").option("--json", "Output result as JSON").action(async (workflowId, opts) => {
641
+ const cfg = loadConfig();
642
+ const agentId = opts.agent ?? cfg.defaultAgentId;
643
+ let inputData = {};
644
+ try {
645
+ inputData = JSON.parse(opts.input);
646
+ } catch {
647
+ console.error(c.error("--input must be valid JSON"));
648
+ process.exit(1);
649
+ }
650
+ const spinner = spin("Executing workflow\u2026");
651
+ try {
652
+ const client = makeClient();
653
+ const execution = await client.workflows.execute(workflowId, {
654
+ agentId,
655
+ sessionId: opts.session,
656
+ inputData
657
+ });
658
+ spinner.stop();
659
+ if (opts.json && !opts.watch) return jsonOut(execution);
660
+ console.log(`
661
+ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
662
+ console.log(` Status: ${statusBadge(execution.status)}`);
663
+ if (!opts.watch) {
664
+ if (execution.status === "completed") {
665
+ console.log("\n" + c.label("Result"));
666
+ console.log(" " + JSON.stringify(execution.result ?? execution.outputData, null, 2));
667
+ }
668
+ return;
669
+ }
670
+ console.log(c.dim("\nStreaming execution progress...\n"));
671
+ for await (const event of client.workflows.stream(workflowId, execution.executionId)) {
672
+ if (event.type === "status") {
673
+ const e = event;
674
+ process.stdout.write(`\r ${statusBadge(e.status ?? "")} node: ${c.dim(e.currentNode ?? "\u2026")} `);
675
+ } else if (event.type === "completed") {
676
+ process.stdout.write("\n");
677
+ console.log(`
678
+ ${sym.ok} ${c.success("Completed")}`);
679
+ const e = event;
680
+ if (e.outputData) {
681
+ console.log("\n" + c.label("Output"));
682
+ console.log(" " + JSON.stringify(e.outputData, null, 2));
683
+ }
684
+ break;
685
+ } else if (event.type === "failed" || event.type === "cancelled") {
686
+ process.stdout.write("\n");
687
+ console.error(`
688
+ ${sym.fail} ${c.error(event.errorMessage ?? event.type)}`);
689
+ break;
690
+ } else if (event.type === "awaiting_approval") {
691
+ process.stdout.write("\n");
692
+ const e = event;
693
+ console.log(`
694
+ ${c.warn("\u23F8 Awaiting approval")} at node ${c.id(e.pausedAtNode ?? "")}`);
695
+ console.log(c.dim(` Token: ${e.approvalToken}`));
696
+ console.log(c.dim(` Use: agc workflow approve ${workflowId} ${execution.executionId} <token>`));
697
+ }
698
+ }
699
+ } catch (err) {
700
+ spinner.stop();
701
+ printError(err);
702
+ process.exit(1);
703
+ }
704
+ });
705
+ cmd.command("executions <workflowId>").description("List recent executions for a workflow").option("--limit <n>", "Max results", "20").option("--json", "Output as JSON").action(async (workflowId, opts) => {
706
+ const spinner = spin("Fetching executions\u2026");
707
+ try {
708
+ const client = makeClient();
709
+ const executions = await client.workflows.listExecutions(workflowId, Number(opts.limit));
710
+ spinner.stop();
711
+ if (opts.json) return jsonOut(executions);
712
+ section(`Executions (${executions.length})`);
713
+ table(
714
+ executions.map((e) => ({
715
+ ID: e.executionId.slice(0, 8) + "\u2026",
716
+ Status: statusBadge(e.status),
717
+ Node: e.currentNode ?? "",
718
+ Started: e.startedAt ? relativeTime(e.startedAt) : ""
719
+ })),
720
+ ["ID", "Status", "Node", "Started"]
721
+ );
722
+ } catch (err) {
723
+ spinner.stop();
724
+ printError(err);
725
+ process.exit(1);
726
+ }
727
+ });
728
+ cmd.command("approve <workflowId> <executionId> <token>").description("Approve a paused human_approval step").option("--data <json>", "Approval data as JSON", "{}").action(async (workflowId, executionId, token, opts) => {
729
+ let approvalData = {};
730
+ try {
731
+ approvalData = JSON.parse(opts.data);
732
+ } catch {
733
+ }
734
+ const spinner = spin("Approving\u2026");
735
+ try {
736
+ const client = makeClient();
737
+ await client.workflows.approveExecution(workflowId, executionId, {
738
+ approvalToken: token,
739
+ approvalData
740
+ });
741
+ spinner.stop();
742
+ console.log(`${sym.ok} Execution ${c.id(executionId)} approved \u2014 workflow resuming.`);
743
+ } catch (err) {
744
+ spinner.stop();
745
+ printError(err);
746
+ process.exit(1);
747
+ }
748
+ });
749
+ cmd.command("reject <workflowId> <executionId> <token>").description("Reject a paused human_approval step").option("--reason <text>", "Rejection reason").action(async (workflowId, executionId, token, opts) => {
750
+ const spinner = spin("Rejecting\u2026");
751
+ try {
752
+ const client = makeClient();
753
+ await client.workflows.rejectExecution(workflowId, executionId, {
754
+ approvalToken: token,
755
+ reason: opts.reason
756
+ });
757
+ spinner.stop();
758
+ console.log(`${sym.ok} Execution ${c.id(executionId)} rejected.`);
759
+ } catch (err) {
760
+ spinner.stop();
761
+ printError(err);
762
+ process.exit(1);
763
+ }
764
+ });
765
+ return cmd;
766
+ }
767
+
768
+ // src/commands/task.ts
769
+ var import_commander6 = require("commander");
770
+ function taskCommand() {
771
+ const cmd = new import_commander6.Command("task").description("Manage and execute tasks").alias("t");
772
+ cmd.command("list").description("List tasks").option("--agent <agentId>", "Filter by agent ID").option("--session <sessionId>", "Filter by session ID").option("--json", "Output as JSON").action(async (opts) => {
773
+ const cfg = loadConfig();
774
+ const agentId = opts.agent ?? cfg.defaultAgentId;
775
+ const spinner = spin("Fetching tasks\u2026");
776
+ try {
777
+ const client = makeClient();
778
+ const filter = {};
779
+ if (agentId) filter.agentId = agentId;
780
+ if (opts.session) filter.sessionId = opts.session;
781
+ if (cfg.initiator) {
782
+ filter.ownerId = cfg.initiator;
783
+ filter.ownerType = "user";
784
+ }
785
+ const res = await client.tasks.list(filter);
786
+ const tasks = res?.data ?? res ?? [];
787
+ spinner.stop();
788
+ if (opts.json) return jsonOut(tasks);
789
+ section(`Tasks (${tasks.length})`);
790
+ table(
791
+ tasks.map((t) => ({
792
+ ID: t.taskId.slice(0, 8) + "\u2026",
793
+ Title: (t.title ?? t.description ?? "").slice(0, 40),
794
+ Status: statusBadge(t.status ?? ""),
795
+ Agent: (t.agentId ?? "").slice(0, 8) + "\u2026",
796
+ Created: relativeTime(t.createdAt)
797
+ })),
798
+ ["ID", "Title", "Status", "Agent", "Created"]
799
+ );
800
+ } catch (err) {
801
+ spinner.stop();
802
+ printError(err);
803
+ process.exit(1);
804
+ }
805
+ });
806
+ cmd.command("get <taskId>").description("Show task details").option("--json", "Output as JSON").action(async (taskId, opts) => {
807
+ const spinner = spin("Fetching task\u2026");
808
+ try {
809
+ const client = makeClient();
810
+ const res = await client.tasks.get(taskId);
811
+ const task = res?.data ?? res;
812
+ spinner.stop();
813
+ if (opts.json) return jsonOut(task);
814
+ section("Task");
815
+ detail([
816
+ ["Task ID", c.id(task.taskId)],
817
+ ["Title", task.title ?? task.description ?? c.dim("(none)")],
818
+ ["Status", statusBadge(task.status ?? "")],
819
+ ["Agent ID", task.agentId ?? c.dim("(none)")],
820
+ ["Session ID", task.sessionId ?? c.dim("(none)")],
821
+ ["Created", relativeTime(task.createdAt)]
822
+ ]);
823
+ if (task.result) {
824
+ console.log("\n " + c.label("Result"));
825
+ console.log(" " + JSON.stringify(task.result, null, 2).split("\n").join("\n "));
826
+ }
827
+ } catch (err) {
828
+ spinner.stop();
829
+ printError(err);
830
+ process.exit(1);
831
+ }
832
+ });
833
+ cmd.command("create").description("Create a new task").requiredOption("--title <title>", "Task title").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Session ID").option("--workflow <workflowId>", "Workflow ID to attach").option("--input <json>", "Input data as JSON", "{}").option("--timeout <ms>", "Execution timeout in milliseconds").option("--execute", "Execute immediately after creation").option("--watch", "Stream execution progress (implies --execute)").option("--json", "Output as JSON").action(async (opts) => {
834
+ const cfg = loadConfig();
835
+ const agentId = opts.agent ?? cfg.defaultAgentId;
836
+ if (!agentId) {
837
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
838
+ process.exit(1);
839
+ }
840
+ let inputData = {};
841
+ try {
842
+ inputData = JSON.parse(opts.input);
843
+ } catch {
844
+ console.error(c.error("--input must be valid JSON"));
845
+ process.exit(1);
846
+ }
847
+ const spinner = spin("Creating task\u2026");
848
+ try {
849
+ const client = makeClient();
850
+ const res = await client.tasks.create({
851
+ title: opts.title,
852
+ agentId,
853
+ sessionId: opts.session,
854
+ workflowId: opts.workflow,
855
+ inputData,
856
+ ...opts.timeout && { timeoutMs: Number(opts.timeout) },
857
+ ...cfg.initiator && { ownerId: cfg.initiator, ownerType: "user" }
858
+ });
859
+ const task = res?.data ?? res;
860
+ spinner.stop();
861
+ if (opts.json && !opts.execute && !opts.watch) return jsonOut(task);
862
+ console.log(`
863
+ ${sym.ok} Task created: ${c.id(task.taskId)}`);
864
+ if (!opts.execute && !opts.watch) return;
865
+ const execSpinner = spin("Executing task\u2026");
866
+ const execRes = await client.tasks.execute(task.taskId);
867
+ execSpinner.stop();
868
+ console.log(` Status: ${statusBadge(execRes?.data?.status ?? "pending")}`);
869
+ if (!opts.watch) {
870
+ if (execRes?.data?.result) {
871
+ console.log("\n" + c.label("Result"));
872
+ console.log(" " + JSON.stringify(execRes.data.result, null, 2));
873
+ }
874
+ return;
875
+ }
876
+ console.log(c.dim("\nStreaming task progress...\n"));
877
+ for await (const event of client.tasks.stream(task.taskId)) {
878
+ if (event.type === "token") {
879
+ process.stdout.write(event.content ?? "");
880
+ } else if (event.type === "status") {
881
+ const e = event;
882
+ process.stdout.write(`\r ${statusBadge(e.status ?? "")} `);
883
+ } else if (event.type === "final" || event.type === "completed") {
884
+ process.stdout.write("\n");
885
+ console.log(`
886
+ ${sym.ok} ${c.success("Completed")}`);
887
+ const e = event;
888
+ if (e.result ?? e.outputData) {
889
+ console.log("\n" + c.label("Output"));
890
+ console.log(" " + JSON.stringify(e.result ?? e.outputData, null, 2));
891
+ }
892
+ break;
893
+ } else if (event.type === "failed" || event.type === "error") {
894
+ process.stdout.write("\n");
895
+ console.error(`
896
+ ${sym.fail} ${c.error(event.message ?? event.type)}`);
897
+ break;
898
+ }
899
+ }
900
+ } catch (err) {
901
+ spinner.stop();
902
+ printError(err);
903
+ process.exit(1);
904
+ }
905
+ });
906
+ cmd.command("execute <taskId>").description("Execute an existing task").option("--watch", "Stream execution progress via SSE").option("--json", "Output result as JSON").action(async (taskId, opts) => {
907
+ const spinner = spin("Executing task\u2026");
908
+ try {
909
+ const client = makeClient();
910
+ const res = await client.tasks.execute(taskId);
911
+ spinner.stop();
912
+ if (opts.json && !opts.watch) return jsonOut(res);
913
+ console.log(`
914
+ ${sym.ok} Execution started`);
915
+ console.log(` Status: ${statusBadge(res?.data?.status ?? "pending")}`);
916
+ if (!opts.watch) return;
917
+ console.log(c.dim("\nStreaming task progress...\n"));
918
+ for await (const event of client.tasks.stream(taskId)) {
919
+ if (event.type === "token") {
920
+ process.stdout.write(event.content ?? "");
921
+ } else if (event.type === "final" || event.type === "completed") {
922
+ process.stdout.write("\n");
923
+ console.log(`
924
+ ${sym.ok} ${c.success("Completed")}`);
925
+ break;
926
+ } else if (event.type === "failed" || event.type === "error") {
927
+ process.stdout.write("\n");
928
+ console.error(`
929
+ ${sym.fail} ${c.error(event.message ?? event.type)}`);
930
+ break;
931
+ }
932
+ }
933
+ } catch (err) {
934
+ spinner.stop();
935
+ printError(err);
936
+ process.exit(1);
937
+ }
938
+ });
939
+ cmd.command("cancel <taskId>").description("Cancel a running task").action(async (taskId) => {
940
+ const spinner = spin("Cancelling task\u2026");
941
+ try {
942
+ const client = makeClient();
943
+ await client.tasks.cancel(taskId);
944
+ spinner.stop();
945
+ console.log(`${sym.ok} Task ${c.id(taskId)} cancelled.`);
946
+ } catch (err) {
947
+ spinner.stop();
948
+ printError(err);
949
+ process.exit(1);
950
+ }
951
+ });
952
+ return cmd;
953
+ }
954
+
955
+ // src/commands/run.ts
956
+ var import_commander7 = require("commander");
957
+ function runCommand() {
958
+ return new import_commander7.Command("run").description("Send a single prompt to an agent and stream the response").argument("<prompt>", "Prompt text to send").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Session ID").option("--no-stream", "Disable streaming (wait for full response)").option("--json", "Output raw event stream as JSON lines").action(async (prompt2, opts) => {
959
+ const cfg = loadConfig();
960
+ const agentId = opts.agent ?? cfg.defaultAgentId;
961
+ if (!agentId) {
962
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
963
+ process.exit(1);
964
+ }
965
+ const params = {
966
+ agentId,
967
+ sessionId: opts.session,
968
+ messages: [{ role: "user", content: prompt2 }],
969
+ ...cfg.initiator && { initiatorId: cfg.initiator }
970
+ };
971
+ if (opts.noStream) {
972
+ const spinner = spin("Running\u2026");
973
+ try {
974
+ const client = makeClient();
975
+ const result = await client.run.once(params);
976
+ spinner.stop();
977
+ if (opts.json) return jsonOut(result);
978
+ const text = result?.content ?? result?.text ?? result?.message ?? JSON.stringify(result);
979
+ console.log(text);
980
+ } catch (err) {
981
+ spinner.stop();
982
+ printError(err);
983
+ process.exit(1);
984
+ }
985
+ return;
986
+ }
987
+ try {
988
+ const client = makeClient();
989
+ let hasOutput = false;
990
+ for await (const event of client.agents.stream(params)) {
991
+ if (opts.json) {
992
+ console.log(JSON.stringify(event));
993
+ continue;
994
+ }
995
+ if (event.type === "token") {
996
+ process.stdout.write(event.content ?? "");
997
+ hasOutput = true;
998
+ } else if (event.type === "final") {
999
+ if (hasOutput) process.stdout.write("\n");
1000
+ const e = event;
1001
+ if (e.content && !hasOutput) console.log(e.content);
1002
+ break;
1003
+ } else if (event.type === "error") {
1004
+ if (hasOutput) process.stdout.write("\n");
1005
+ console.error(`
1006
+ ${sym.fail} ${c.error(event.message ?? "Error")}`);
1007
+ process.exit(1);
1008
+ }
1009
+ }
1010
+ if (hasOutput && !opts.json) process.stdout.write("\n");
1011
+ } catch (err) {
1012
+ printError(err);
1013
+ process.exit(1);
1014
+ }
1015
+ });
1016
+ }
1017
+
1018
+ // src/commands/chat.ts
1019
+ var import_commander8 = require("commander");
1020
+ var readline2 = __toESM(require("readline"));
1021
+ var HELP_TEXT = `
1022
+ ${c.label("Slash commands")}
1023
+ /help Show this help
1024
+ /session Print the current session ID (copy it to resume later)
1025
+ /clear Clear the terminal screen
1026
+ /quit Exit (session is preserved \u2014 resume with --resume <id>)
1027
+ `;
1028
+ function chatCommand() {
1029
+ return new import_commander8.Command("chat").description("Start an interactive chat REPL with an agent").option("--agent <agentId>", "Agent ID (or set defaultAgentId in config)").option("--resume <sessionId>", "Resume an existing session by ID").option("--no-stream", "Disable token streaming (wait for full response)").action(async (opts) => {
1030
+ const cfg = loadConfig();
1031
+ const agentId = opts.agent ?? cfg.defaultAgentId;
1032
+ if (!agentId) {
1033
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
1034
+ process.exit(1);
1035
+ }
1036
+ if (!cfg.initiator) {
1037
+ console.error(c.error("No initiator set. Run `agc login` first."));
1038
+ process.exit(1);
1039
+ }
1040
+ const client = makeClient();
1041
+ let sessionId = opts.resume ?? "";
1042
+ const isResume = !!opts.resume;
1043
+ if (!isResume) {
1044
+ const spinner = spin("Creating session\u2026");
1045
+ try {
1046
+ const res = await client.sessions.create({
1047
+ agentId,
1048
+ initiator: cfg.initiator,
1049
+ title: `agc chat ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`
1050
+ });
1051
+ const session = res?.data ?? res;
1052
+ sessionId = session.sessionId;
1053
+ spinner.stop();
1054
+ } catch (err) {
1055
+ spinner.stop();
1056
+ printError(err);
1057
+ process.exit(1);
1058
+ }
1059
+ } else {
1060
+ const spinner = spin("Loading session\u2026");
1061
+ try {
1062
+ const res = await client.sessions.get(sessionId);
1063
+ const session = res?.data ?? res;
1064
+ if (session.agentId && session.agentId !== agentId) {
1065
+ spinner.stop();
1066
+ console.log(c.warn(` Note: session ${sessionId} was created with agent ${session.agentId}, not ${agentId}`));
1067
+ } else {
1068
+ spinner.stop();
1069
+ }
1070
+ } catch {
1071
+ spinner.stop();
1072
+ console.error(c.error(`Session "${sessionId}" not found.`));
1073
+ process.exit(1);
1074
+ }
1075
+ }
1076
+ let walletLine = "";
1077
+ try {
1078
+ const primary = await client.wallets.primary(agentId);
1079
+ const w = primary?.data ?? primary;
1080
+ if (w?.id) {
1081
+ const bal = await client.wallets.balance(w.id).catch(() => null);
1082
+ const b = bal?.data ?? bal;
1083
+ const addr = `${w.address.slice(0, 6)}\u2026${w.address.slice(-4)}`;
1084
+ const usdc = b?.usdc ?? "0";
1085
+ walletLine = `${addr} ${c.bold(usdc + " USDC")}`;
1086
+ }
1087
+ } catch {
1088
+ }
1089
+ console.log(`
1090
+ ${c.bold("Agent Commons Chat")}`);
1091
+ const headerRows = [
1092
+ ["Agent", agentId],
1093
+ ["Session", c.id(sessionId) + (isResume ? c.dim(" (resumed)") : c.dim(" (new)"))]
1094
+ ];
1095
+ if (walletLine) headerRows.push(["Wallet", walletLine]);
1096
+ detail(headerRows);
1097
+ console.log(c.dim("\nType your message and press Enter. Type /help for commands.\n"));
1098
+ const rl = readline2.createInterface({
1099
+ input: process.stdin,
1100
+ output: process.stdout,
1101
+ terminal: true,
1102
+ prompt: c.primary("you") + c.dim(" \u203A ")
1103
+ });
1104
+ rl.prompt();
1105
+ rl.on("line", async (line) => {
1106
+ const input = line.trim();
1107
+ if (!input) {
1108
+ rl.prompt();
1109
+ return;
1110
+ }
1111
+ if (input === "/quit" || input === "/exit" || input === "/q") {
1112
+ console.log(c.dim(`
1113
+ Session saved. Resume with: agc chat --resume ${sessionId}`));
1114
+ rl.close();
1115
+ process.exit(0);
1116
+ }
1117
+ if (input === "/help") {
1118
+ console.log(HELP_TEXT);
1119
+ rl.prompt();
1120
+ return;
1121
+ }
1122
+ if (input === "/session") {
1123
+ console.log(c.dim(` ${sessionId}`));
1124
+ console.log(c.dim(` Resume with: agc chat --resume ${sessionId}`));
1125
+ rl.prompt();
1126
+ return;
1127
+ }
1128
+ if (input === "/clear") {
1129
+ process.stdout.write("\x1B[2J\x1B[H");
1130
+ rl.prompt();
1131
+ return;
1132
+ }
1133
+ if (input.startsWith("/")) {
1134
+ console.log(c.warn(` Unknown command "${input}". Type /help for available commands.`));
1135
+ rl.prompt();
1136
+ return;
1137
+ }
1138
+ rl.pause();
1139
+ const params = {
1140
+ agentId,
1141
+ sessionId,
1142
+ messages: [{ role: "user", content: input }]
1143
+ };
1144
+ process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
1145
+ if (opts.noStream) {
1146
+ const spinner = spin("");
1147
+ try {
1148
+ const result = await client.run.once(params);
1149
+ spinner.stop();
1150
+ const text = extractText(result);
1151
+ console.log(text);
1152
+ } catch (err) {
1153
+ spinner.stop();
1154
+ console.error(`
1155
+ ${sym.fail} ${c.error(err.message ?? String(err))}`);
1156
+ }
1157
+ } else {
1158
+ try {
1159
+ let hasOutput = false;
1160
+ for await (const event of client.agents.stream(params)) {
1161
+ if (event.type === "token") {
1162
+ process.stdout.write(event.content ?? "");
1163
+ hasOutput = true;
1164
+ } else if (event.type === "toolStart") {
1165
+ const name = event.toolName ?? "";
1166
+ if (hasOutput) process.stdout.write("\n");
1167
+ process.stdout.write(c.dim(` [tool] ${name}\u2026`));
1168
+ hasOutput = false;
1169
+ } else if (event.type === "toolEnd") {
1170
+ process.stdout.write(c.dim(" done\n"));
1171
+ process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
1172
+ hasOutput = false;
1173
+ } else if (event.type === "final") {
1174
+ const e = event;
1175
+ const text = extractText(e?.payload);
1176
+ if (text && !hasOutput) process.stdout.write(text);
1177
+ const usage = e?.payload?.usage;
1178
+ if (usage) {
1179
+ const tokens = usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
1180
+ const cost = typeof usage.costUsd === "number" ? `$${usage.costUsd.toFixed(4)}` : "";
1181
+ const parts = [tokens ? `${tokens.toLocaleString()} tokens` : "", cost].filter(Boolean);
1182
+ if (parts.length) process.stdout.write("\n" + c.dim(` \u21B3 ${parts.join(" \xB7 ")}`));
1183
+ }
1184
+ break;
1185
+ } else if (event.type === "error") {
1186
+ if (hasOutput) process.stdout.write("\n");
1187
+ console.error(`
1188
+ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
1189
+ break;
1190
+ }
1191
+ }
1192
+ process.stdout.write("\n");
1193
+ } catch (err) {
1194
+ process.stdout.write("\n");
1195
+ console.error(`${sym.fail} ${c.error(err.message ?? String(err))}`);
1196
+ }
1197
+ }
1198
+ console.log();
1199
+ rl.resume();
1200
+ rl.prompt();
1201
+ });
1202
+ rl.on("close", () => {
1203
+ process.exit(0);
1204
+ });
1205
+ process.on("SIGINT", () => {
1206
+ console.log(c.dim(`
1207
+ Session preserved. Resume with: agc chat --resume ${sessionId}`));
1208
+ process.exit(130);
1209
+ });
1210
+ });
1211
+ }
1212
+ function extractText(payload) {
1213
+ if (!payload) return "";
1214
+ if (typeof payload === "string") return payload;
1215
+ if (typeof payload.content === "string") return payload.content;
1216
+ if (Array.isArray(payload.content)) {
1217
+ return payload.content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
1218
+ }
1219
+ if (payload.text) return payload.text;
1220
+ if (payload.message) return payload.message;
1221
+ return JSON.stringify(payload);
1222
+ }
1223
+
1224
+ // src/commands/mcp.ts
1225
+ var import_commander9 = require("commander");
1226
+ function mcpCommand() {
1227
+ const cmd = new import_commander9.Command("mcp").description("Manage MCP (Model Context Protocol) servers");
1228
+ cmd.command("list").description("List MCP servers for the current initiator").option("--agent <agentId>", "List servers owned by an agent instead of the user").option("--json", "Output as JSON").action(async (opts) => {
1229
+ const cfg = loadConfig();
1230
+ if (!cfg.initiator && !opts.agent) {
1231
+ console.error(c.error("No initiator set. Run `agc login` first."));
1232
+ process.exit(1);
1233
+ }
1234
+ const ownerId = opts.agent ?? cfg.initiator;
1235
+ const ownerType = opts.agent ? "agent" : "user";
1236
+ const spinner = spin("Fetching MCP servers\u2026");
1237
+ try {
1238
+ const client = makeClient();
1239
+ const res = await client.mcp.listServers(ownerId, ownerType);
1240
+ const servers = res.servers ?? [];
1241
+ spinner.stop();
1242
+ if (opts.json) return jsonOut(servers);
1243
+ section(`MCP Servers (${servers.length})`);
1244
+ if (!servers.length) {
1245
+ console.log(c.dim(" No MCP servers configured."));
1246
+ console.log(c.dim(' Add one with: agc mcp add --name "filesystem" --type stdio --command "npx @mcp/server-filesystem ~/projects"'));
1247
+ return;
1248
+ }
1249
+ table(
1250
+ servers.map((s) => ({
1251
+ ID: (s.serverId ?? "").slice(0, 8) + "\u2026",
1252
+ Name: s.name ?? "",
1253
+ Type: s.connectionType ?? "",
1254
+ Tools: String(s.toolCount ?? 0),
1255
+ Created: relativeTime(s.createdAt)
1256
+ })),
1257
+ ["ID", "Name", "Type", "Tools", "Created"]
1258
+ );
1259
+ } catch (err) {
1260
+ spinner.stop();
1261
+ printError(err);
1262
+ process.exit(1);
1263
+ }
1264
+ });
1265
+ cmd.command("get <serverId>").description("Show details for an MCP server").option("--json", "Output as JSON").action(async (serverId, opts) => {
1266
+ const spinner = spin("Fetching server\u2026");
1267
+ try {
1268
+ const client = makeClient();
1269
+ const server = await client.mcp.getServer(serverId);
1270
+ spinner.stop();
1271
+ if (opts.json) return jsonOut(server);
1272
+ section(server.name ?? serverId);
1273
+ detail([
1274
+ ["Server ID", c.id(server.serverId)],
1275
+ ["Type", server.connectionType ?? c.dim("(unknown)")],
1276
+ ["Tools", String(server.toolCount ?? 0)],
1277
+ ["Public", server.isPublic ? "yes" : "no"],
1278
+ ["Created", relativeTime(server.createdAt)]
1279
+ ]);
1280
+ const cfg = server.connectionConfig;
1281
+ if (cfg) {
1282
+ console.log("\n " + c.label("Connection Config"));
1283
+ const safe = { ...cfg, apiKey: cfg.apiKey ? "****" : void 0, token: cfg.token ? "****" : void 0 };
1284
+ console.log(" " + JSON.stringify(safe, null, 2).split("\n").join("\n "));
1285
+ }
1286
+ } catch (err) {
1287
+ spinner.stop();
1288
+ printError(err);
1289
+ process.exit(1);
1290
+ }
1291
+ });
1292
+ cmd.command("add").description("Register a new MCP server").requiredOption("--name <name>", "Server name").requiredOption("--type <type>", "Connection type: stdio | sse | http | streamable-http").option("--command <cmd>", 'Command to run (for stdio type, e.g. "npx @mcp/server-filesystem ~/projects")').option("--url <url>", "Server URL (for sse/http types)").option("--agent <agentId>", "Assign to an agent instead of the current user").option("--public", "Make server publicly visible").option("--json", "Output as JSON").action(async (opts) => {
1293
+ const cfg = loadConfig();
1294
+ if (!cfg.initiator && !opts.agent) {
1295
+ console.error(c.error("No initiator set. Run `agc login` first."));
1296
+ process.exit(1);
1297
+ }
1298
+ const validTypes = ["stdio", "sse", "http", "streamable-http"];
1299
+ if (!validTypes.includes(opts.type)) {
1300
+ console.error(c.error(`Invalid type "${opts.type}". Choose from: ${validTypes.join(", ")}`));
1301
+ process.exit(1);
1302
+ }
1303
+ if (opts.type === "stdio" && !opts.command) {
1304
+ console.error(c.error("--command is required for stdio type"));
1305
+ process.exit(1);
1306
+ }
1307
+ if ((opts.type === "sse" || opts.type === "http" || opts.type === "streamable-http") && !opts.url) {
1308
+ console.error(c.error("--url is required for sse/http/streamable-http types"));
1309
+ process.exit(1);
1310
+ }
1311
+ const connectionConfig = {};
1312
+ if (opts.command) connectionConfig.command = opts.command;
1313
+ if (opts.url) connectionConfig.url = opts.url;
1314
+ const ownerId = opts.agent ?? cfg.initiator;
1315
+ const ownerType = opts.agent ? "agent" : "user";
1316
+ const spinner = spin("Registering MCP server\u2026");
1317
+ try {
1318
+ const client = makeClient();
1319
+ const server = await client.mcp.createServer({
1320
+ name: opts.name,
1321
+ connectionType: opts.type,
1322
+ connectionConfig,
1323
+ isPublic: !!opts.public,
1324
+ ownerId,
1325
+ ownerType
1326
+ });
1327
+ spinner.stop();
1328
+ if (opts.json) return jsonOut(server);
1329
+ console.log(`
1330
+ ${sym.ok} MCP server registered`);
1331
+ detail([
1332
+ ["Server ID", c.id(server.serverId)],
1333
+ ["Name", server.name],
1334
+ ["Type", server.connectionType]
1335
+ ]);
1336
+ console.log(c.dim(`
1337
+ Connect and sync tools with: agc mcp sync ${server.serverId}`));
1338
+ } catch (err) {
1339
+ spinner.stop();
1340
+ printError(err);
1341
+ process.exit(1);
1342
+ }
1343
+ });
1344
+ cmd.command("connect <serverId>").description("Connect to an MCP server").action(async (serverId) => {
1345
+ const spinner = spin("Connecting\u2026");
1346
+ try {
1347
+ const client = makeClient();
1348
+ const res = await client.mcp.connect(serverId);
1349
+ spinner.stop();
1350
+ if (res.connected) {
1351
+ console.log(`${sym.ok} Connected to ${c.id(serverId)}`);
1352
+ console.log(c.dim(` Run \`agc mcp sync ${serverId}\` to discover tools.`));
1353
+ } else {
1354
+ console.log(c.warn("Connection returned but reported not connected."));
1355
+ }
1356
+ } catch (err) {
1357
+ spinner.stop();
1358
+ printError(err);
1359
+ process.exit(1);
1360
+ }
1361
+ });
1362
+ cmd.command("disconnect <serverId>").description("Disconnect from an MCP server").action(async (serverId) => {
1363
+ const spinner = spin("Disconnecting\u2026");
1364
+ try {
1365
+ const client = makeClient();
1366
+ await client.mcp.disconnect(serverId);
1367
+ spinner.stop();
1368
+ console.log(`${sym.ok} Disconnected from ${c.id(serverId)}`);
1369
+ } catch (err) {
1370
+ spinner.stop();
1371
+ printError(err);
1372
+ process.exit(1);
1373
+ }
1374
+ });
1375
+ cmd.command("sync <serverId>").description("Sync tools, resources, and prompts from an MCP server").option("--json", "Output as JSON").action(async (serverId, opts) => {
1376
+ const spinner = spin("Syncing\u2026");
1377
+ try {
1378
+ const client = makeClient();
1379
+ const res = await client.mcp.sync(serverId);
1380
+ spinner.stop();
1381
+ if (opts.json) return jsonOut(res);
1382
+ console.log(`${sym.ok} Sync complete`);
1383
+ detail([
1384
+ ["Tools discovered", String(res.toolsDiscovered)],
1385
+ ["Resources discovered", String(res.resourcesDiscovered)],
1386
+ ["Prompts discovered", String(res.promptsDiscovered)]
1387
+ ]);
1388
+ } catch (err) {
1389
+ spinner.stop();
1390
+ printError(err);
1391
+ process.exit(1);
1392
+ }
1393
+ });
1394
+ cmd.command("tools <serverId>").description("List tools discovered from an MCP server").option("--json", "Output as JSON").action(async (serverId, opts) => {
1395
+ const spinner = spin("Fetching tools\u2026");
1396
+ try {
1397
+ const client = makeClient();
1398
+ const res = await client.mcp.listTools(serverId);
1399
+ const tools = res.tools ?? [];
1400
+ spinner.stop();
1401
+ if (opts.json) return jsonOut(tools);
1402
+ section(`MCP Tools (${res.total ?? tools.length})`);
1403
+ table(
1404
+ tools.map((t) => ({
1405
+ Name: t.name ?? "",
1406
+ Description: (t.description ?? "").slice(0, 60)
1407
+ })),
1408
+ ["Name", "Description"]
1409
+ );
1410
+ } catch (err) {
1411
+ spinner.stop();
1412
+ printError(err);
1413
+ process.exit(1);
1414
+ }
1415
+ });
1416
+ cmd.command("resources <serverId>").description("List resources from an MCP server").option("--json", "Output as JSON").action(async (serverId, opts) => {
1417
+ const spinner = spin("Fetching resources\u2026");
1418
+ try {
1419
+ const client = makeClient();
1420
+ const res = await client.mcp.listResources(serverId);
1421
+ const resources = res.resources ?? [];
1422
+ spinner.stop();
1423
+ if (opts.json) return jsonOut(resources);
1424
+ section(`MCP Resources (${res.total ?? resources.length})`);
1425
+ table(
1426
+ resources.map((r) => ({
1427
+ URI: r.uri ?? "",
1428
+ Name: r.name ?? "",
1429
+ MimeType: r.mimeType ?? c.dim("(none)")
1430
+ })),
1431
+ ["URI", "Name", "MimeType"]
1432
+ );
1433
+ } catch (err) {
1434
+ spinner.stop();
1435
+ printError(err);
1436
+ process.exit(1);
1437
+ }
1438
+ });
1439
+ cmd.command("read <serverId> <uri>").description("Read a resource from an MCP server by URI").option("--json", "Output as JSON").action(async (serverId, uri, opts) => {
1440
+ const spinner = spin("Reading resource\u2026");
1441
+ try {
1442
+ const client = makeClient();
1443
+ const res = await client.mcp.readResource(serverId, uri);
1444
+ spinner.stop();
1445
+ if (opts.json) return jsonOut(res);
1446
+ section(`Resource: ${uri}`);
1447
+ const contents = res.contents;
1448
+ if (typeof contents === "string") {
1449
+ console.log(contents);
1450
+ } else {
1451
+ console.log(JSON.stringify(contents, null, 2));
1452
+ }
1453
+ } catch (err) {
1454
+ spinner.stop();
1455
+ printError(err);
1456
+ process.exit(1);
1457
+ }
1458
+ });
1459
+ cmd.command("prompts <serverId>").description("List prompts from an MCP server").option("--json", "Output as JSON").action(async (serverId, opts) => {
1460
+ const spinner = spin("Fetching prompts\u2026");
1461
+ try {
1462
+ const client = makeClient();
1463
+ const res = await client.mcp.listPrompts(serverId);
1464
+ const prompts = res.prompts ?? [];
1465
+ spinner.stop();
1466
+ if (opts.json) return jsonOut(prompts);
1467
+ section(`MCP Prompts (${res.total ?? prompts.length})`);
1468
+ table(
1469
+ prompts.map((p) => ({
1470
+ Name: p.name ?? "",
1471
+ Description: (p.description ?? "").slice(0, 60)
1472
+ })),
1473
+ ["Name", "Description"]
1474
+ );
1475
+ } catch (err) {
1476
+ spinner.stop();
1477
+ printError(err);
1478
+ process.exit(1);
1479
+ }
1480
+ });
1481
+ cmd.command("prompt <serverId> <promptName>").description("Render an MCP prompt with optional arguments").option("--args <json>", "Prompt arguments as JSON object", "{}").option("--json", "Output as JSON").action(async (serverId, promptName, opts) => {
1482
+ let args = {};
1483
+ try {
1484
+ args = JSON.parse(opts.args);
1485
+ } catch {
1486
+ console.error(c.error("--args must be valid JSON"));
1487
+ process.exit(1);
1488
+ }
1489
+ const spinner = spin("Rendering prompt\u2026");
1490
+ try {
1491
+ const client = makeClient();
1492
+ const res = await client.mcp.getPrompt(serverId, promptName, args);
1493
+ spinner.stop();
1494
+ if (opts.json) return jsonOut(res);
1495
+ if (res.description) console.log(c.dim(res.description) + "\n");
1496
+ for (const msg of res.messages ?? []) {
1497
+ const role = c.label(msg.role ?? "unknown");
1498
+ const text = typeof msg.content === "string" ? msg.content : msg.content?.text ?? JSON.stringify(msg.content);
1499
+ console.log(`${role}: ${text}
1500
+ `);
1501
+ }
1502
+ } catch (err) {
1503
+ spinner.stop();
1504
+ printError(err);
1505
+ process.exit(1);
1506
+ }
1507
+ });
1508
+ cmd.command("remove <serverId>").description("Delete an MCP server").action(async (serverId) => {
1509
+ const spinner = spin("Removing server\u2026");
1510
+ try {
1511
+ const client = makeClient();
1512
+ await client.mcp.deleteServer(serverId);
1513
+ spinner.stop();
1514
+ console.log(`${sym.ok} MCP server ${c.id(serverId)} removed.`);
1515
+ } catch (err) {
1516
+ spinner.stop();
1517
+ printError(err);
1518
+ process.exit(1);
1519
+ }
1520
+ });
1521
+ return cmd;
1522
+ }
1523
+
1524
+ // src/commands/skills.ts
1525
+ var import_commander10 = require("commander");
1526
+ function skillsCommand() {
1527
+ const cmd = new import_commander10.Command("skills").description("Discover and manage skills");
1528
+ cmd.command("list").description("List available skills").option("--owner <id>", "Filter by owner ID").option("--platform", "Show platform-only skills").option("--json", "Output as JSON").action(async (opts) => {
1529
+ const spinner = spin("Fetching skills\u2026");
1530
+ try {
1531
+ const client = makeClient();
1532
+ const filter = {};
1533
+ if (opts.owner) filter.ownerId = opts.owner;
1534
+ if (opts.platform) filter.ownerType = "platform";
1535
+ const res = await client.skills.list(filter);
1536
+ const skills = res?.data ?? res ?? [];
1537
+ spinner.stop();
1538
+ if (opts.json) return jsonOut(skills);
1539
+ section(`Skills (${skills.length})`);
1540
+ table(
1541
+ skills.map((s) => ({
1542
+ Slug: s.slug ?? "",
1543
+ Name: s.name ?? "",
1544
+ Description: (s.description ?? "").slice(0, 55),
1545
+ Tags: (s.tags ?? []).join(", "),
1546
+ Source: s.source ?? ""
1547
+ })),
1548
+ ["Slug", "Name", "Description", "Tags", "Source"]
1549
+ );
1550
+ } catch (err) {
1551
+ spinner.stop();
1552
+ printError(err);
1553
+ process.exit(1);
1554
+ }
1555
+ });
1556
+ cmd.command("index").description("Show compact skill index (progressive disclosure view)").option("--owner <id>", "Filter by owner ID").option("--json", "Output as JSON").action(async (opts) => {
1557
+ const spinner = spin("Fetching skill index\u2026");
1558
+ try {
1559
+ const client = makeClient();
1560
+ const res = await client.skills.getIndex(opts.owner);
1561
+ const index = res?.data ?? res ?? [];
1562
+ spinner.stop();
1563
+ if (opts.json) return jsonOut(index);
1564
+ section(`Skill Index (${index.length})`);
1565
+ table(
1566
+ index.map((s) => ({
1567
+ "Icon": s.icon ?? " ",
1568
+ "Slug": s.slug ?? "",
1569
+ "Name": s.name ?? "",
1570
+ "Description": (s.description ?? "").slice(0, 55),
1571
+ "Triggers": (s.triggers ?? []).slice(0, 3).join(", ")
1572
+ })),
1573
+ ["Icon", "Slug", "Name", "Description", "Triggers"]
1574
+ );
1575
+ } catch (err) {
1576
+ spinner.stop();
1577
+ printError(err);
1578
+ process.exit(1);
1579
+ }
1580
+ });
1581
+ cmd.command("get <skillId>").description("Show full skill details and instructions").option("--json", "Output as JSON").action(async (skillId, opts) => {
1582
+ const spinner = spin("Fetching skill\u2026");
1583
+ try {
1584
+ const client = makeClient();
1585
+ const res = await client.skills.get(skillId);
1586
+ const skill = res?.data ?? res;
1587
+ spinner.stop();
1588
+ if (!skill) {
1589
+ console.error(c.error(`Skill "${skillId}" not found.`));
1590
+ process.exit(1);
1591
+ }
1592
+ if (opts.json) return jsonOut(skill);
1593
+ section(skill.name);
1594
+ detail([
1595
+ ["Skill ID", c.id(skill.skillId)],
1596
+ ["Slug", skill.slug],
1597
+ ["Description", skill.description ?? c.dim("(none)")],
1598
+ ["Tags", (skill.tags ?? []).join(", ") || c.dim("(none)")],
1599
+ ["Tools", (skill.tools ?? []).join(", ") || c.dim("(none)")],
1600
+ ["Source", skill.source ?? c.dim("(none)")],
1601
+ ["Version", skill.version ?? "1.0.0"],
1602
+ ["Public", skill.isPublic ? "yes" : "no"],
1603
+ ["Usage", String(skill.usageCount ?? 0)]
1604
+ ]);
1605
+ if (skill.instructions) {
1606
+ console.log("\n " + c.label("Instructions"));
1607
+ const lines = skill.instructions.split("\n");
1608
+ for (const line of lines) {
1609
+ console.log(" " + c.dim(line));
1610
+ }
1611
+ }
1612
+ } catch (err) {
1613
+ spinner.stop();
1614
+ printError(err);
1615
+ process.exit(1);
1616
+ }
1617
+ });
1618
+ cmd.command("create").description("Create a new skill").requiredOption("--slug <slug>", "Unique slug identifier").requiredOption("--name <name>", "Display name").requiredOption("--description <desc>", "Short description").requiredOption("--instructions <text>", "Full skill instructions (markdown)").option("--tools <tools>", "Comma-separated tool names").option("--triggers <triggers>", "Comma-separated trigger phrases").option("--tags <tags>", "Comma-separated tags").option("--icon <icon>", "Emoji icon").option("--public", "Make skill publicly discoverable").option("--json", "Output result as JSON").action(async (opts) => {
1619
+ const cfg = loadConfig();
1620
+ const spinner = spin("Creating skill\u2026");
1621
+ try {
1622
+ const client = makeClient();
1623
+ const res = await client.skills.create({
1624
+ slug: opts.slug,
1625
+ name: opts.name,
1626
+ description: opts.description,
1627
+ instructions: opts.instructions,
1628
+ tools: opts.tools ? opts.tools.split(",").map((t) => t.trim()) : [],
1629
+ triggers: opts.triggers ? opts.triggers.split(",").map((t) => t.trim()) : [],
1630
+ tags: opts.tags ? opts.tags.split(",").map((t) => t.trim()) : [],
1631
+ icon: opts.icon,
1632
+ isPublic: !!opts.public,
1633
+ ownerId: cfg.initiator,
1634
+ ownerType: "user",
1635
+ source: "user"
1636
+ });
1637
+ const skill = res?.data ?? res;
1638
+ spinner.stop();
1639
+ if (opts.json) return jsonOut(skill);
1640
+ console.log(`${sym.ok} Skill ${c.id(skill.skillId)} created`);
1641
+ detail([
1642
+ ["Slug", skill.slug],
1643
+ ["Name", skill.name]
1644
+ ]);
1645
+ } catch (err) {
1646
+ spinner.stop();
1647
+ printError(err);
1648
+ process.exit(1);
1649
+ }
1650
+ });
1651
+ cmd.command("install <slug>").description("Install a skill by slug (fetch full instructions and print as SKILL.md)").action(async (slug) => {
1652
+ const spinner = spin("Loading skill\u2026");
1653
+ try {
1654
+ const client = makeClient();
1655
+ const res = await client.skills.get(slug);
1656
+ const skill = res?.data ?? res;
1657
+ spinner.stop();
1658
+ if (!skill) {
1659
+ console.error(c.error(`Skill "${slug}" not found.`));
1660
+ process.exit(1);
1661
+ }
1662
+ const md = [
1663
+ `# SKILL: ${skill.name}`,
1664
+ ``,
1665
+ `**Slug:** ${skill.slug}`,
1666
+ `**Version:** ${skill.version ?? "1.0.0"}`,
1667
+ `**Tags:** ${(skill.tags ?? []).join(", ")}`,
1668
+ `**Tools:** ${(skill.tools ?? []).join(", ") || "none"}`,
1669
+ ``,
1670
+ `## Description`,
1671
+ ``,
1672
+ skill.description,
1673
+ ``,
1674
+ `## Instructions`,
1675
+ ``,
1676
+ skill.instructions
1677
+ ].join("\n");
1678
+ console.log(md);
1679
+ } catch (err) {
1680
+ spinner.stop();
1681
+ printError(err);
1682
+ process.exit(1);
1683
+ }
1684
+ });
1685
+ cmd.command("publish <slug>").description("Make a skill publicly discoverable").option("--json", "Output result as JSON").action(async (slug, opts) => {
1686
+ const spinner = spin(`Publishing skill "${slug}"\u2026`);
1687
+ try {
1688
+ const client = makeClient();
1689
+ const res = await client.skills.update(slug, { isPublic: true });
1690
+ const skill = res?.data ?? res;
1691
+ spinner.stop();
1692
+ if (opts.json) return jsonOut(skill);
1693
+ console.log(`${sym.ok} Skill ${c.id(skill.slug)} is now ${c.success("public")}`);
1694
+ } catch (err) {
1695
+ spinner.stop();
1696
+ printError(err);
1697
+ process.exit(1);
1698
+ }
1699
+ });
1700
+ cmd.command("unpublish <slug>").description("Make a skill private (remove from public marketplace)").option("--json", "Output result as JSON").action(async (slug, opts) => {
1701
+ const spinner = spin(`Unpublishing skill "${slug}"\u2026`);
1702
+ try {
1703
+ const client = makeClient();
1704
+ const res = await client.skills.update(slug, { isPublic: false });
1705
+ const skill = res?.data ?? res;
1706
+ spinner.stop();
1707
+ if (opts.json) return jsonOut(skill);
1708
+ console.log(`${sym.ok} Skill ${c.id(skill.slug)} is now ${c.warn("private")}`);
1709
+ } catch (err) {
1710
+ spinner.stop();
1711
+ printError(err);
1712
+ process.exit(1);
1713
+ }
1714
+ });
1715
+ cmd.command("update <slug>").description("Update skill properties").option("--name <name>", "New display name").option("--description <desc>", "New description").option("--instructions <text>", "New instructions (markdown)").option("--tools <tools>", "Comma-separated tool names (replaces existing)").option("--triggers <triggers>", "Comma-separated trigger phrases (replaces existing)").option("--tags <tags>", "Comma-separated tags (replaces existing)").option("--icon <icon>", "Emoji icon").option("--json", "Output result as JSON").action(async (slug, opts) => {
1716
+ const updates = {};
1717
+ if (opts.name) updates.name = opts.name;
1718
+ if (opts.description) updates.description = opts.description;
1719
+ if (opts.instructions) updates.instructions = opts.instructions;
1720
+ if (opts.tools) updates.tools = opts.tools.split(",").map((t) => t.trim());
1721
+ if (opts.triggers) updates.triggers = opts.triggers.split(",").map((t) => t.trim());
1722
+ if (opts.tags) updates.tags = opts.tags.split(",").map((t) => t.trim());
1723
+ if (opts.icon) updates.icon = opts.icon;
1724
+ if (Object.keys(updates).length === 0) {
1725
+ console.error(c.warn("No fields to update. Use --name, --description, --instructions, etc."));
1726
+ process.exit(1);
1727
+ }
1728
+ const spinner = spin(`Updating skill "${slug}"\u2026`);
1729
+ try {
1730
+ const client = makeClient();
1731
+ const res = await client.skills.update(slug, updates);
1732
+ const skill = res?.data ?? res;
1733
+ spinner.stop();
1734
+ if (opts.json) return jsonOut(skill);
1735
+ console.log(`${sym.ok} Skill ${c.id(skill.slug)} updated`);
1736
+ detail([
1737
+ ["Name", skill.name],
1738
+ ["Description", skill.description ?? c.dim("(none)")],
1739
+ ["Public", skill.isPublic ? c.success("yes") : c.warn("no")],
1740
+ ["Tags", (skill.tags ?? []).join(", ") || c.dim("(none)")]
1741
+ ]);
1742
+ } catch (err) {
1743
+ spinner.stop();
1744
+ printError(err);
1745
+ process.exit(1);
1746
+ }
1747
+ });
1748
+ cmd.command("delete <slug>").description("Permanently delete a skill").option("--yes", "Skip confirmation prompt").option("--json", "Output result as JSON").action(async (slug, opts) => {
1749
+ if (!opts.yes) {
1750
+ const readline3 = await import("readline");
1751
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
1752
+ const answer = await new Promise(
1753
+ (resolve) => rl.question(c.warn(`Delete skill "${slug}"? This cannot be undone. [y/N] `), resolve)
1754
+ );
1755
+ rl.close();
1756
+ if (!["y", "yes"].includes(answer.trim().toLowerCase())) {
1757
+ console.log(c.dim("Aborted."));
1758
+ return;
1759
+ }
1760
+ }
1761
+ const spinner = spin(`Deleting skill "${slug}"\u2026`);
1762
+ try {
1763
+ const client = makeClient();
1764
+ const res = await client.skills.delete(slug);
1765
+ spinner.stop();
1766
+ if (opts.json) return jsonOut(res);
1767
+ console.log(`${sym.ok} Skill ${c.id(slug)} deleted`);
1768
+ } catch (err) {
1769
+ spinner.stop();
1770
+ printError(err);
1771
+ process.exit(1);
1772
+ }
1773
+ });
1774
+ return cmd;
1775
+ }
1776
+
1777
+ // src/commands/wallet.ts
1778
+ var import_commander11 = require("commander");
1779
+ function walletCommand() {
1780
+ const cmd = new import_commander11.Command("wallet").description("Manage agent wallets");
1781
+ cmd.command("list").description("List all wallets for an agent").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--json", "Output as JSON").action(async (opts) => {
1782
+ const cfg = loadConfig();
1783
+ const agentId = opts.agent ?? cfg.defaultAgentId;
1784
+ if (!agentId) {
1785
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
1786
+ process.exit(1);
1787
+ }
1788
+ const spinner = spin("Fetching wallets\u2026");
1789
+ try {
1790
+ const client = makeClient();
1791
+ const wallets = await client.wallets.list(agentId);
1792
+ spinner.stop();
1793
+ if (opts.json) return jsonOut(wallets);
1794
+ const list = wallets?.data ?? wallets ?? [];
1795
+ section(`Wallets for agent ${agentId.slice(0, 8)}\u2026 (${list.length})`);
1796
+ table(
1797
+ list.map((w) => ({
1798
+ ID: w.id.slice(0, 8) + "\u2026",
1799
+ Type: w.walletType,
1800
+ Address: w.address,
1801
+ Chain: chainName(w.chainId),
1802
+ Label: w.label ?? "Primary",
1803
+ Active: w.isActive ? sym.pass : sym.fail
1804
+ })),
1805
+ ["ID", "Type", "Address", "Chain", "Label", "Active"]
1806
+ );
1807
+ } catch (err) {
1808
+ spinner.stop();
1809
+ printError(err);
1810
+ process.exit(1);
1811
+ }
1812
+ });
1813
+ cmd.command("show").description("Show the agent's primary wallet address").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--json", "Output as JSON").action(async (opts) => {
1814
+ const cfg = loadConfig();
1815
+ const agentId = opts.agent ?? cfg.defaultAgentId;
1816
+ if (!agentId) {
1817
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
1818
+ process.exit(1);
1819
+ }
1820
+ const spinner = spin("Fetching primary wallet\u2026");
1821
+ try {
1822
+ const client = makeClient();
1823
+ const wallet = await client.wallets.primary(agentId);
1824
+ spinner.stop();
1825
+ if (!wallet) {
1826
+ console.log(c.warn(` No wallet found for agent ${agentId}`));
1827
+ console.log(c.dim(` Run: agc wallet create --agent ${agentId}`));
1828
+ return;
1829
+ }
1830
+ const w = wallet?.data ?? wallet;
1831
+ if (opts.json) return jsonOut(w);
1832
+ section("Primary Wallet");
1833
+ detail([
1834
+ ["Address", w.address],
1835
+ ["Type", w.walletType],
1836
+ ["Chain", chainName(w.chainId)],
1837
+ ["Label", w.label ?? "Primary"],
1838
+ ["Wallet ID", w.id]
1839
+ ]);
1840
+ } catch (err) {
1841
+ spinner.stop();
1842
+ printError(err);
1843
+ process.exit(1);
1844
+ }
1845
+ });
1846
+ cmd.command("balance").description("Show the agent's wallet USDC and ETH balance").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--wallet <walletId>", "Specific wallet ID (defaults to primary)").option("--json", "Output as JSON").action(async (opts) => {
1847
+ const cfg = loadConfig();
1848
+ const agentId = opts.agent ?? cfg.defaultAgentId;
1849
+ if (!agentId) {
1850
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
1851
+ process.exit(1);
1852
+ }
1853
+ const spinner = spin("Fetching balance\u2026");
1854
+ try {
1855
+ const client = makeClient();
1856
+ let walletId = opts.wallet;
1857
+ if (!walletId) {
1858
+ const primary = await client.wallets.primary(agentId);
1859
+ const w = primary?.data ?? primary;
1860
+ if (!w) {
1861
+ spinner.stop();
1862
+ console.log(c.warn(` No wallet found. Run: agc wallet create --agent ${agentId}`));
1863
+ return;
1864
+ }
1865
+ walletId = w.id;
1866
+ }
1867
+ const balance = await client.wallets.balance(walletId);
1868
+ spinner.stop();
1869
+ const b = balance?.data ?? balance;
1870
+ if (opts.json) return jsonOut(b);
1871
+ section("Wallet Balance");
1872
+ detail([
1873
+ ["Address", b.address],
1874
+ ["Chain", chainName(b.chainId)],
1875
+ ["USDC", c.bold(b.usdc + " USDC")],
1876
+ ["ETH", b.native + " ETH"]
1877
+ ]);
1878
+ console.log();
1879
+ console.log(c.dim(" Fund this wallet by sending USDC to the address above."));
1880
+ console.log(c.dim(" Network: Base Sepolia (chain 84532)"));
1881
+ } catch (err) {
1882
+ spinner.stop();
1883
+ printError(err);
1884
+ process.exit(1);
1885
+ }
1886
+ });
1887
+ cmd.command("create").description("Create a new wallet for an agent").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--type <type>", "Wallet type: eoa | external (default: eoa)", "eoa").option("--label <label>", "Wallet label (default: Primary)", "Primary").option("--address <address>", "For --type external: owner-provided address").option("--json", "Output as JSON").action(async (opts) => {
1888
+ const cfg = loadConfig();
1889
+ const agentId = opts.agent ?? cfg.defaultAgentId;
1890
+ if (!agentId) {
1891
+ console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
1892
+ process.exit(1);
1893
+ }
1894
+ if (opts.type === "external" && !opts.address) {
1895
+ console.error(c.error("--address is required for --type external"));
1896
+ process.exit(1);
1897
+ }
1898
+ const spinner = spin("Creating wallet\u2026");
1899
+ try {
1900
+ const client = makeClient();
1901
+ const wallet = await client.wallets.create({
1902
+ agentId,
1903
+ walletType: opts.type,
1904
+ label: opts.label,
1905
+ externalAddress: opts.address
1906
+ });
1907
+ spinner.stop();
1908
+ const w = wallet?.data ?? wallet;
1909
+ if (opts.json) return jsonOut(w);
1910
+ console.log(`
1911
+ ${sym.pass} ${c.bold("Wallet created")}`);
1912
+ detail([
1913
+ ["Address", c.bold(w.address)],
1914
+ ["Type", w.walletType],
1915
+ ["Chain", chainName(w.chainId)],
1916
+ ["Label", w.label],
1917
+ ["Wallet ID", w.id]
1918
+ ]);
1919
+ console.log();
1920
+ console.log(c.dim(" Fund this wallet by sending USDC to the address above."));
1921
+ } catch (err) {
1922
+ spinner.stop();
1923
+ printError(err);
1924
+ process.exit(1);
1925
+ }
1926
+ });
1927
+ return cmd;
1928
+ }
1929
+ function chainName(chainId) {
1930
+ const names = {
1931
+ "84532": "Base Sepolia",
1932
+ "8453": "Base",
1933
+ "1": "Ethereum",
1934
+ "137": "Polygon"
1935
+ };
1936
+ return names[chainId] ?? `chain ${chainId}`;
1937
+ }
1938
+
1939
+ // src/bin.ts
1940
+ var program = new import_commander12.Command();
1941
+ program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.1.0", "-v, --version");
1942
+ program.addCommand(loginCommand());
1943
+ program.addCommand(logoutCommand());
1944
+ program.addCommand(whoamiCommand());
1945
+ program.addCommand(configCommand());
1946
+ program.addCommand(agentsCommand());
1947
+ program.addCommand(sessionsCommand());
1948
+ program.addCommand(toolsCommand());
1949
+ program.addCommand(workflowCommand());
1950
+ program.addCommand(taskCommand());
1951
+ program.addCommand(runCommand());
1952
+ program.addCommand(chatCommand());
1953
+ program.addCommand(mcpCommand());
1954
+ program.addCommand(skillsCommand());
1955
+ program.addCommand(walletCommand());
1956
+ program.on("command:*", () => {
1957
+ console.error(`Unknown command: ${program.args.join(" ")}
1958
+ Run \`agc --help\` to see available commands.`);
1959
+ process.exit(1);
1960
+ });
1961
+ program.parse(process.argv);