@acnlabs/acn-cli 0.12.0 → 0.13.0

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/index.js +325 -45
  2. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -1,16 +1,37 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
9
  var __commonJS = (cb, mod) => function __require() {
5
10
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
6
11
  };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
7
28
 
8
29
  // package.json
9
30
  var require_package = __commonJS({
10
31
  "package.json"(exports2, module2) {
11
32
  module2.exports = {
12
33
  name: "@acnlabs/acn-cli",
13
- version: "0.12.0",
34
+ version: "0.13.0",
14
35
  description: "Official CLI for ACN (Agent Collaboration Network) \u2014 zero-integration agent access",
15
36
  main: "dist/index.js",
16
37
  bin: {
@@ -48,10 +69,12 @@ var require_package = __commonJS({
48
69
  url: "https://github.com/acnlabs/ACN/issues"
49
70
  },
50
71
  dependencies: {
51
- commander: "^12.0.0"
72
+ commander: "^12.0.0",
73
+ ws: "^8.18.0"
52
74
  },
53
75
  devDependencies: {
54
76
  "@types/node": "^20.0.0",
77
+ "@types/ws": "^8.5.10",
55
78
  tsup: "^8.0.0",
56
79
  typescript: "^5.0.0",
57
80
  vitest: "^3.0.5"
@@ -64,7 +87,7 @@ var require_package = __commonJS({
64
87
  });
65
88
 
66
89
  // src/index.ts
67
- var import_commander15 = require("commander");
90
+ var import_commander16 = require("commander");
68
91
 
69
92
  // src/output.ts
70
93
  var jsonMode = false;
@@ -255,33 +278,42 @@ function acnDelete(path) {
255
278
 
256
279
  // src/commands/join.ts
257
280
  function joinCommand() {
258
- return new import_commander2.Command("join").description("Register this agent with ACN and save credentials locally").requiredOption("-n, --name <name>", "Agent name").requiredOption("-t, --tags <tags>", "Comma-separated capability tags (e.g. coding,review)").option("-e, --endpoint <url>", "Public A2A endpoint URL of this agent").option("-d, --description <text>", "Agent description").action(async (opts) => {
259
- const tags = opts.tags.split(",").map((s) => s.trim()).filter(Boolean);
260
- const body = {
261
- name: opts.name,
262
- description: opts.description ?? `${opts.name} \u2014 registered via acn-cli`,
263
- tags,
264
- ...opts.endpoint ? { endpoint: opts.endpoint } : {}
265
- };
266
- try {
267
- const res = await acnPost("/agents/join", body);
268
- saveConfig({ api_key: res.api_key, agent_id: res.agent_id });
269
- const claimLine = res.claim_url ? `
281
+ return new import_commander2.Command("join").description("Register this agent with ACN and save credentials locally").requiredOption("-n, --name <name>", "Agent name").requiredOption("-t, --tags <tags>", "Comma-separated capability tags (e.g. coding,review)").option("-e, --endpoint <url>", "Public A2A endpoint URL of this agent").option("-d, --description <text>", "Agent description").option(
282
+ "--relay",
283
+ "Receive messages in real time over an outbound WebSocket (run `acn listen`) instead of hosting a public endpoint. Registers in open/push mode with no delivery URL."
284
+ ).action(
285
+ async (opts) => {
286
+ const tags = opts.tags.split(",").map((s) => s.trim()).filter(Boolean);
287
+ const body = {
288
+ name: opts.name,
289
+ description: opts.description ?? `${opts.name} \u2014 registered via acn-cli`,
290
+ tags,
291
+ ...opts.endpoint ? { endpoint: opts.endpoint } : {},
292
+ // ADR-0012 Mode B: relay delivery needs a push mode (open) so the
293
+ // gateway actually pushes inbound messages down the WebSocket; the
294
+ // server-side validator then waives the public-URL requirement.
295
+ ...opts.relay ? { delivery: "relay", communication_policy: { mode: "open" } } : {}
296
+ };
297
+ try {
298
+ const res = await acnPost("/agents/join", body);
299
+ saveConfig({ api_key: res.api_key, agent_id: res.agent_id });
300
+ const claimLine = res.claim_url ? `
270
301
  Claim URL: ${res.claim_url}` : "";
271
- const verifyLine = res.verification_code ? `
302
+ const verifyLine = res.verification_code ? `
272
303
  Verify : ${res.verification_code}` : "";
273
- output(res, [
274
- `Registered successfully!`,
275
- ` Agent ID : ${res.agent_id}`,
276
- ` API Key : ${res.api_key}`,
277
- ` Status : ${res.status}${claimLine}${verifyLine}`,
278
- ``,
279
- `Credentials saved to ~/.acn/config.json`
280
- ].join("\n"));
281
- } catch (err) {
282
- handleError(err);
304
+ output(res, [
305
+ `Registered successfully!`,
306
+ ` Agent ID : ${res.agent_id}`,
307
+ ` API Key : ${res.api_key}`,
308
+ ` Status : ${res.status}${claimLine}${verifyLine}`,
309
+ ``,
310
+ `Credentials saved to ~/.acn/config.json`
311
+ ].join("\n"));
312
+ } catch (err) {
313
+ handleError(err);
314
+ }
283
315
  }
284
- });
316
+ );
285
317
  }
286
318
 
287
319
  // src/commands/heartbeat.ts
@@ -1230,8 +1262,255 @@ ${formatPolicy(res)}`);
1230
1262
  return cmd;
1231
1263
  }
1232
1264
 
1233
- // src/commands/session.ts
1265
+ // src/commands/listen.ts
1234
1266
  var import_commander10 = require("commander");
1267
+ var import_child_process = require("child_process");
1268
+ var import_ws = __toESM(require("ws"));
1269
+ var STRIP_HEADERS = /* @__PURE__ */ new Set([
1270
+ "host",
1271
+ "content-length",
1272
+ "connection",
1273
+ "transfer-encoding"
1274
+ ]);
1275
+ function toWebsocketUrl(baseUrl, agentId) {
1276
+ const u = new URL(baseUrl);
1277
+ u.protocol = u.protocol === "https:" ? "wss:" : "ws:";
1278
+ u.pathname = `/ws/${agentId}`;
1279
+ u.search = "";
1280
+ return u.toString();
1281
+ }
1282
+ function decodeBody(frame) {
1283
+ if (frame.body_encoding === "base64") {
1284
+ return Buffer.from(frame.body ?? "", "base64");
1285
+ }
1286
+ return Buffer.from(frame.body ?? "", "utf-8");
1287
+ }
1288
+ function errorResponse(id, status, detail) {
1289
+ return {
1290
+ type: "a2a_response",
1291
+ id,
1292
+ status,
1293
+ headers: { "content-type": "application/json" },
1294
+ body: JSON.stringify({ error: detail })
1295
+ };
1296
+ }
1297
+ async function dispatchA2aRequest(frame, opts, send, deps = {}) {
1298
+ const bodyBuf = decodeBody(frame);
1299
+ try {
1300
+ if (opts.forward) {
1301
+ await forwardToHttp(frame, bodyBuf, opts.forward, deps.fetchFn ?? fetch, send);
1302
+ return;
1303
+ }
1304
+ if (opts.exec) {
1305
+ send(await runExec(frame, bodyBuf, opts.exec, deps.spawnFn ?? import_child_process.spawn));
1306
+ return;
1307
+ }
1308
+ send(errorResponse(frame.id, 500, "no handler configured"));
1309
+ } catch (err) {
1310
+ const msg = err instanceof Error ? err.message : String(err);
1311
+ send(errorResponse(frame.id, 502, `handler failed: ${msg}`));
1312
+ }
1313
+ }
1314
+ function buildForwardHeaders(frame) {
1315
+ const headers = {};
1316
+ for (const [k, v] of Object.entries(frame.headers ?? {})) {
1317
+ if (!STRIP_HEADERS.has(k.toLowerCase())) headers[k] = v;
1318
+ }
1319
+ return headers;
1320
+ }
1321
+ async function forwardToHttp(frame, bodyBuf, base, fetchFn, send) {
1322
+ const suffix = frame.path && frame.path !== "/" ? "/" + frame.path.replace(/^\//, "") : "";
1323
+ const targetUrl = base.replace(/\/$/, "") + suffix;
1324
+ const method = (frame.method ?? "POST").toUpperCase();
1325
+ const init = { method, headers: buildForwardHeaders(frame) };
1326
+ if (method !== "GET" && method !== "HEAD") {
1327
+ init.body = bodyBuf;
1328
+ }
1329
+ const res = await fetchFn(targetUrl, init);
1330
+ const contentType = res.headers.get("content-type") ?? "application/json";
1331
+ if (contentType.includes("text/event-stream") && res.body) {
1332
+ const reader = res.body.getReader();
1333
+ let seq = 0;
1334
+ try {
1335
+ for (; ; ) {
1336
+ const { done, value } = await reader.read();
1337
+ if (done) break;
1338
+ if (value && value.length > 0) {
1339
+ send({
1340
+ type: "a2a_stream_chunk",
1341
+ id: frame.id,
1342
+ seq: seq++,
1343
+ data: Buffer.from(value).toString("base64"),
1344
+ data_encoding: "base64"
1345
+ });
1346
+ }
1347
+ }
1348
+ send({ type: "a2a_stream_end", id: frame.id, status: res.status });
1349
+ } catch (err) {
1350
+ const msg = err instanceof Error ? err.message : String(err);
1351
+ send({ type: "a2a_stream_end", id: frame.id, error: msg });
1352
+ } finally {
1353
+ reader.releaseLock();
1354
+ }
1355
+ return;
1356
+ }
1357
+ const respText = await res.text();
1358
+ send({
1359
+ type: "a2a_response",
1360
+ id: frame.id,
1361
+ status: res.status,
1362
+ headers: { "content-type": contentType },
1363
+ body: respText
1364
+ });
1365
+ }
1366
+ function runExec(frame, bodyBuf, command, spawnFn) {
1367
+ return new Promise((resolve) => {
1368
+ const child = spawnFn(command, { shell: true });
1369
+ const out = [];
1370
+ const errOut = [];
1371
+ child.stdout?.on("data", (d) => out.push(Buffer.from(d)));
1372
+ child.stderr?.on("data", (d) => errOut.push(Buffer.from(d)));
1373
+ child.on(
1374
+ "error",
1375
+ (e) => resolve(errorResponse(frame.id, 502, `exec error: ${e.message}`))
1376
+ );
1377
+ child.on("close", (code) => {
1378
+ const stdout = Buffer.concat(out).toString("utf-8");
1379
+ if (code === 0) {
1380
+ resolve({
1381
+ type: "a2a_response",
1382
+ id: frame.id,
1383
+ status: 200,
1384
+ headers: { "content-type": "application/json" },
1385
+ body: stdout
1386
+ });
1387
+ } else {
1388
+ const stderr = Buffer.concat(errOut).toString("utf-8");
1389
+ resolve(
1390
+ errorResponse(frame.id, 500, `exec exited ${code}: ${stderr.slice(0, 500)}`)
1391
+ );
1392
+ }
1393
+ });
1394
+ child.stdin?.end(bodyBuf);
1395
+ });
1396
+ }
1397
+ function rawToString(data) {
1398
+ if (typeof data === "string") return data;
1399
+ if (Buffer.isBuffer(data)) return data.toString("utf-8");
1400
+ if (Array.isArray(data)) return Buffer.concat(data).toString("utf-8");
1401
+ return Buffer.from(data).toString("utf-8");
1402
+ }
1403
+ var KEEPALIVE_INTERVAL_MS = 3e4;
1404
+ var INITIAL_BACKOFF_MS = 1e3;
1405
+ var MAX_BACKOFF_MS = 3e4;
1406
+ function runListener(cfg) {
1407
+ const wsUrl = toWebsocketUrl(cfg.baseUrl, cfg.agentId);
1408
+ let backoff = INITIAL_BACKOFF_MS;
1409
+ let stopped = false;
1410
+ const connect = () => {
1411
+ const ws = new import_ws.default(wsUrl, {
1412
+ headers: { Authorization: `Bearer ${cfg.apiKey}` }
1413
+ });
1414
+ let keepalive;
1415
+ ws.on("open", () => {
1416
+ console.error(`[acn listen] connected as ${cfg.agentId} \u2192 ${wsUrl}`);
1417
+ backoff = INITIAL_BACKOFF_MS;
1418
+ keepalive = setInterval(() => {
1419
+ if (ws.readyState === import_ws.default.OPEN) {
1420
+ ws.send(JSON.stringify({ type: "ping" }));
1421
+ }
1422
+ }, KEEPALIVE_INTERVAL_MS);
1423
+ });
1424
+ ws.on("message", (data) => {
1425
+ let frame;
1426
+ try {
1427
+ frame = JSON.parse(rawToString(data));
1428
+ } catch {
1429
+ return;
1430
+ }
1431
+ if (!frame || typeof frame !== "object") return;
1432
+ const f = frame;
1433
+ if (f.type === "a2a_request" && typeof f.id === "string") {
1434
+ const send = (out) => {
1435
+ if (ws.readyState === import_ws.default.OPEN) {
1436
+ ws.send(JSON.stringify(out));
1437
+ }
1438
+ };
1439
+ void dispatchA2aRequest(f, cfg, send);
1440
+ }
1441
+ });
1442
+ ws.on("close", (code, reason) => {
1443
+ if (keepalive) clearInterval(keepalive);
1444
+ if (stopped) return;
1445
+ if (code === 4401 || code === 4403 || code === 4429) {
1446
+ console.error(
1447
+ `[acn listen] fatal close (code ${code}): ${reason.toString() || "see api_key / agent_id"}`
1448
+ );
1449
+ process.exit(1);
1450
+ }
1451
+ console.error(
1452
+ `[acn listen] disconnected (code ${code}); reconnecting in ${backoff / 1e3}s`
1453
+ );
1454
+ setTimeout(connect, backoff);
1455
+ backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);
1456
+ });
1457
+ ws.on("error", (err) => {
1458
+ console.error(`[acn listen] socket error: ${err.message}`);
1459
+ });
1460
+ };
1461
+ process.on("SIGINT", () => {
1462
+ stopped = true;
1463
+ console.error("\n[acn listen] stopping");
1464
+ process.exit(0);
1465
+ });
1466
+ connect();
1467
+ }
1468
+ function listenCommand() {
1469
+ const cmd = new import_commander10.Command("listen").description(
1470
+ "Hold an outbound connection to ACN and answer relayed A2A requests in real time (ADR-0012 Mode B). For agents with no public endpoint."
1471
+ ).option(
1472
+ "--forward <url>",
1473
+ "Tunnel each relayed request to a local HTTP server (e.g. http://localhost:8080)"
1474
+ ).option(
1475
+ "--exec <command>",
1476
+ "Run a shell command per request: body on stdin, stdout becomes the response"
1477
+ ).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action((opts) => {
1478
+ const config = loadConfig();
1479
+ const apiKey = config.api_key;
1480
+ const agentId = opts.agentId ?? config.agent_id;
1481
+ if (!apiKey) {
1482
+ console.error(
1483
+ "No API key found. Run `acn join` first or `acn config set api-key <key>`."
1484
+ );
1485
+ process.exit(1);
1486
+ }
1487
+ if (!agentId) {
1488
+ console.error(
1489
+ "No agent ID found. Run `acn join` first or `acn config set agent-id <id>`."
1490
+ );
1491
+ process.exit(1);
1492
+ }
1493
+ if (!opts.forward && !opts.exec) {
1494
+ console.error("Provide a handler: --forward <url> or --exec <command>.");
1495
+ process.exit(1);
1496
+ }
1497
+ if (opts.forward && opts.exec) {
1498
+ console.error("Use only one handler: --forward or --exec, not both.");
1499
+ process.exit(1);
1500
+ }
1501
+ runListener({
1502
+ agentId,
1503
+ apiKey,
1504
+ baseUrl: config.base_url,
1505
+ forward: opts.forward,
1506
+ exec: opts.exec
1507
+ });
1508
+ });
1509
+ return cmd;
1510
+ }
1511
+
1512
+ // src/commands/session.ts
1513
+ var import_commander11 = require("commander");
1235
1514
  function requireAgentId3() {
1236
1515
  const config = loadConfig();
1237
1516
  if (!config.api_key) {
@@ -1276,7 +1555,7 @@ function formatEntry2(s, index) {
1276
1555
  return lines.join("\n");
1277
1556
  }
1278
1557
  function sessionCommand() {
1279
- const cmd = new import_commander10.Command("session").description(
1558
+ const cmd = new import_commander11.Command("session").description(
1280
1559
  "Real-time session layer: bidirectional channel between two agents"
1281
1560
  );
1282
1561
  cmd.command("invite <target_agent_id>").description("Invite an agent to a real-time session").option("--ttl-seconds <s>", "Session TTL in seconds (60\u20131800, default 300)", parseInt).option("--metadata <json>", "Optional JSON object attached to the invitation (max 4KB)").action(
@@ -1354,7 +1633,7 @@ ${formatEntry2(res)}`);
1354
1633
  }
1355
1634
 
1356
1635
  // src/commands/subnet.ts
1357
- var import_commander11 = require("commander");
1636
+ var import_commander12 = require("commander");
1358
1637
  function requireAgentId4() {
1359
1638
  const config = loadConfig();
1360
1639
  if (!config.api_key) {
@@ -1442,7 +1721,7 @@ function formatSubnet(s, index) {
1442
1721
  return lines.join("\n");
1443
1722
  }
1444
1723
  function subnetCommand() {
1445
- const cmd = new import_commander11.Command("subnet").description("Manage ACN subnets");
1724
+ const cmd = new import_commander12.Command("subnet").description("Manage ACN subnets");
1446
1725
  cmd.command("list").description(
1447
1726
  "List subnets. Without --all/--parent shows only subnets you have joined."
1448
1727
  ).option("--all", "Show all public subnets on ACN (not just your own)").option(
@@ -1659,7 +1938,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
1659
1938
  handleError(err);
1660
1939
  }
1661
1940
  });
1662
- const requests = new import_commander11.Command("requests").description(
1941
+ const requests = new import_commander12.Command("requests").description(
1663
1942
  "Manage join-requests for a subnet (ADR-0004)"
1664
1943
  );
1665
1944
  requests.command("list <subnet_id>").description(
@@ -1801,7 +2080,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
1801
2080
  }
1802
2081
  );
1803
2082
  cmd.addCommand(requests);
1804
- const invitations = new import_commander11.Command("invitations").description(
2083
+ const invitations = new import_commander12.Command("invitations").description(
1805
2084
  "Manage invitations on a subnet (ADR-0004)"
1806
2085
  );
1807
2086
  invitations.command("send <subnet_id>").description(
@@ -1937,7 +2216,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
1937
2216
  }
1938
2217
  );
1939
2218
  cmd.addCommand(invitations);
1940
- const allowlist = new import_commander11.Command("allowlist").description(
2219
+ const allowlist = new import_commander12.Command("allowlist").description(
1941
2220
  "Manage a subnet allowlist (ADR-0004)"
1942
2221
  );
1943
2222
  allowlist.command("list <subnet_id>").description("Owner-only: list allowlist entries for a subnet.").option("--limit <n>", "Page size (1-500, default 100)", "100").option("--offset <n>", "Page offset (default 0)", "0").action(
@@ -2005,7 +2284,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
2005
2284
  }
2006
2285
  );
2007
2286
  cmd.addCommand(allowlist);
2008
- const harness = new import_commander11.Command("harness").description("Manage Org Harness webhook for a subnet");
2287
+ const harness = new import_commander12.Command("harness").description("Manage Org Harness webhook for a subnet");
2009
2288
  harness.command("set <subnet_id>").description("Register an Org Harness webhook on a subnet you own").requiredOption("--url <url>", "Harness webhook URL (HTTPS)").option("--secret <secret>", "HMAC-SHA256 signing secret (recommended)").action(async (subnetId, opts) => {
2010
2289
  const config = loadConfig();
2011
2290
  if (!config.api_key) {
@@ -2048,7 +2327,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
2048
2327
  }
2049
2328
 
2050
2329
  // src/commands/follow.ts
2051
- var import_commander12 = require("commander");
2330
+ var import_commander13 = require("commander");
2052
2331
  function requireAgentId5() {
2053
2332
  const config = loadConfig();
2054
2333
  if (!config.api_key) {
@@ -2071,7 +2350,7 @@ function formatAgent2(a, i) {
2071
2350
  ].join("\n");
2072
2351
  }
2073
2352
  function followCommand() {
2074
- const cmd = new import_commander12.Command("follow").description("Follow/unfollow agents and inspect follow graph");
2353
+ const cmd = new import_commander13.Command("follow").description("Follow/unfollow agents and inspect follow graph");
2075
2354
  cmd.command("add <target_id>").description("Follow another agent").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (targetId, opts) => {
2076
2355
  const agentId = opts.agentId ?? requireAgentId5();
2077
2356
  try {
@@ -2162,7 +2441,7 @@ function followCommand() {
2162
2441
  }
2163
2442
 
2164
2443
  // src/commands/wallet.ts
2165
- var import_commander13 = require("commander");
2444
+ var import_commander14 = require("commander");
2166
2445
  function requireAgentId6() {
2167
2446
  const config = loadConfig();
2168
2447
  if (!config.api_key) {
@@ -2205,7 +2484,7 @@ async function showWalletInfo(opts) {
2205
2484
  }
2206
2485
  }
2207
2486
  function walletCommand() {
2208
- const cmd = new import_commander13.Command("wallet").description("View and manage agent's wallet & payment info");
2487
+ const cmd = new import_commander14.Command("wallet").description("View and manage agent's wallet & payment info");
2209
2488
  cmd.command("info", { isDefault: true }).description("Show wallet, payment methods, pricing, and ERC-8004 status").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(showWalletInfo);
2210
2489
  cmd.command("set-capability").description("Declare which payment methods, networks, and wallets you accept").requiredOption(
2211
2490
  "--methods <csv>",
@@ -2384,7 +2663,7 @@ function walletCommand() {
2384
2663
  }
2385
2664
 
2386
2665
  // src/commands/pay.ts
2387
- var import_commander14 = require("commander");
2666
+ var import_commander15 = require("commander");
2388
2667
  function requireAgentId7() {
2389
2668
  const config = loadConfig();
2390
2669
  if (!config.api_key) {
@@ -2398,8 +2677,8 @@ function requireAgentId7() {
2398
2677
  return config.agent_id;
2399
2678
  }
2400
2679
  function payCommand() {
2401
- const cmd = new import_commander14.Command("pay").description("Manage payment tasks between agents");
2402
- const createCmd = new import_commander14.Command("create").description("Create a payment task to another agent");
2680
+ const cmd = new import_commander15.Command("pay").description("Manage payment tasks between agents");
2681
+ const createCmd = new import_commander15.Command("create").description("Create a payment task to another agent");
2403
2682
  createCmd.requiredOption("--to <agent>", "Recipient agent ID").requiredOption("--amount <n>", "Payment amount (positive number)").requiredOption("--currency <c>", "Currency code, e.g. USD, USDC").requiredOption("--method <m>", "Payment method, e.g. usdc, eth, platform_credits").requiredOption("--network <n>", "Network, e.g. ethereum, base, solana").option("--description <text>", "Free-text description for the payment task").option("--metadata <json>", "Additional metadata as JSON object").action(
2404
2683
  async (opts) => {
2405
2684
  const fromAgent = requireAgentId7();
@@ -2445,7 +2724,7 @@ function payCommand() {
2445
2724
  }
2446
2725
  }
2447
2726
  );
2448
- const confirmCmd = new import_commander14.Command("confirm").description(
2727
+ const confirmCmd = new import_commander15.Command("confirm").description(
2449
2728
  "Confirm an external payment has been made (buyer only)"
2450
2729
  );
2451
2730
  confirmCmd.requiredOption("--task-id <id>", "Payment task ID to confirm").requiredOption(
@@ -2467,7 +2746,7 @@ function payCommand() {
2467
2746
  handleError(err);
2468
2747
  }
2469
2748
  });
2470
- const statusCmd = new import_commander14.Command("status").description(
2749
+ const statusCmd = new import_commander15.Command("status").description(
2471
2750
  "Show payment tasks for the authenticated agent"
2472
2751
  );
2473
2752
  statusCmd.option("--status <s>", "Filter by status (e.g. created, payment_confirmed)").option("--limit <n>", "Max results (default 50)", "50").action(async (opts) => {
@@ -2490,7 +2769,7 @@ function payCommand() {
2490
2769
 
2491
2770
  // src/index.ts
2492
2771
  var { version } = require_package();
2493
- var program = new import_commander15.Command();
2772
+ var program = new import_commander16.Command();
2494
2773
  program.name("acn").description("ACN CLI \u2014 Agent Collaboration Network command-line interface").version(version).option("--json", "Output raw JSON (useful for agent parsing)").hook("preAction", (thisCommand) => {
2495
2774
  const opts = thisCommand.opts();
2496
2775
  if (opts.json) setJsonMode(true);
@@ -2504,6 +2783,7 @@ program.addCommand(tasksCommand());
2504
2783
  program.addCommand(messageCommand());
2505
2784
  program.addCommand(notifyCommand());
2506
2785
  program.addCommand(inboxCommand());
2786
+ program.addCommand(listenCommand());
2507
2787
  program.addCommand(sessionCommand());
2508
2788
  program.addCommand(subnetCommand());
2509
2789
  program.addCommand(followCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acnlabs/acn-cli",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Official CLI for ACN (Agent Collaboration Network) — zero-integration agent access",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -38,10 +38,12 @@
38
38
  "url": "https://github.com/acnlabs/ACN/issues"
39
39
  },
40
40
  "dependencies": {
41
- "commander": "^12.0.0"
41
+ "commander": "^12.0.0",
42
+ "ws": "^8.18.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@types/node": "^20.0.0",
46
+ "@types/ws": "^8.5.10",
45
47
  "tsup": "^8.0.0",
46
48
  "typescript": "^5.0.0",
47
49
  "vitest": "^3.0.5"