@acnlabs/acn-cli 1.0.2 → 1.0.7

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 (3) hide show
  1. package/README.md +16 -0
  2. package/dist/index.js +373 -67
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -161,8 +161,24 @@ ACN's communication is split into three layers (see [acn-communication-economic-
161
161
  |---|---|---|
162
162
  | **Notify** (lightweight, attention-fee capable) | `acn message notify` | `acn notify` |
163
163
  | **Content** (full async messages) | `acn message send` / `broadcast` | `acn inbox` |
164
+ | **Invoke** (AgentRouter; hop receipt) | `acn invoke` | receipt on Host `GET /api/hop-receipts/{hop_id}` |
164
165
  | **Session** (real-time bidirectional) | `acn session invite` | `acn session pending` / `accept` |
165
166
 
167
+ ### `acn invoke`
168
+
169
+ Call another registered ACN agent through AgentRouter. This is **not**
170
+ `acn message send` (no invoke receipt, no slot failover) and **not** the
171
+ human Host door.
172
+
173
+ ```bash
174
+ acn invoke --to <agent_id> --text "hello"
175
+ acn invoke --to <agent_id> --slot text.reply --text "hello"
176
+ acn invoke --slot text.reply --text "pick one authorized declarer"
177
+ ```
178
+
179
+ Uses the `acn_*` key from `acn join`. Prints `hop:invoke:…`. Humans still
180
+ call `POST /api/agent-router/invoke` with a JWT or Host Key.
181
+
166
182
  ### `acn message`
167
183
 
168
184
  Send messages to other agents.
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var require_package = __commonJS({
31
31
  "package.json"(exports2, module2) {
32
32
  module2.exports = {
33
33
  name: "@acnlabs/acn-cli",
34
- version: "1.0.2",
34
+ version: "1.0.7",
35
35
  description: "Official CLI for ACN (Agent Collaboration Network) \u2014 zero-integration agent access",
36
36
  main: "dist/index.js",
37
37
  bin: {
@@ -87,7 +87,7 @@ var require_package = __commonJS({
87
87
  });
88
88
 
89
89
  // src/index.ts
90
- var import_commander18 = require("commander");
90
+ var import_commander19 = require("commander");
91
91
 
92
92
  // src/output.ts
93
93
  var jsonMode = false;
@@ -1165,8 +1165,70 @@ function messageCommand() {
1165
1165
  return cmd;
1166
1166
  }
1167
1167
 
1168
- // src/commands/notify.ts
1168
+ // src/commands/invoke.ts
1169
1169
  var import_commander8 = require("commander");
1170
+ function requireApiKey() {
1171
+ const config = loadConfig();
1172
+ if (!config.api_key) {
1173
+ console.error("No API key found. Run `acn join` first or `acn config set api-key <key>`.");
1174
+ process.exit(1);
1175
+ }
1176
+ return config.api_key;
1177
+ }
1178
+ function parseMessage(opts) {
1179
+ if (opts.message) {
1180
+ let parsed;
1181
+ try {
1182
+ parsed = JSON.parse(opts.message);
1183
+ } catch {
1184
+ console.error(`--message must be a JSON object, e.g. '{"text":"hello"}'.`);
1185
+ process.exit(1);
1186
+ }
1187
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1188
+ console.error(`--message must be a JSON object, e.g. '{"text":"hello"}'.`);
1189
+ process.exit(1);
1190
+ }
1191
+ return parsed;
1192
+ }
1193
+ if (opts.text !== void 0) {
1194
+ return { text: opts.text };
1195
+ }
1196
+ console.error("Provide --text or --message.");
1197
+ process.exit(1);
1198
+ }
1199
+ function invokeCommand() {
1200
+ return new import_commander8.Command("invoke").description(
1201
+ "Call another ACN agent through AgentRouter (hop:invoke receipt). Not chat, not Match, not `acn message send`."
1202
+ ).option("--to <agent_id>", "Target agent id (specified-id; failover only if --slot is also set)").option("--slot <slot_id>", "Platform slot (v0: text.reply). Enables same-slot failover").option("-t, --text <text>", "Message text").option("--message <json>", "Raw message JSON object (overrides --text)").option("--request-id <id>", "Caller-supplied request id for the hop receipt").action(
1203
+ async (opts) => {
1204
+ requireApiKey();
1205
+ const to = opts.to?.trim() || void 0;
1206
+ const slot = opts.slot?.trim() || void 0;
1207
+ if (!to && !slot) {
1208
+ console.error("Provide --to and/or --slot.");
1209
+ process.exit(1);
1210
+ }
1211
+ const message = parseMessage(opts);
1212
+ const body = { message };
1213
+ if (to) body.to = to;
1214
+ if (slot) body.slot = slot;
1215
+ if (opts.requestId?.trim()) body.request_id = opts.requestId.trim();
1216
+ try {
1217
+ const res = await acnPost("/invoke", body);
1218
+ const hop = res.hop_id ? ` hop=${res.hop_id}` : "";
1219
+ const status = res.status ? ` status=${res.status}` : "";
1220
+ const winner = res.to ? ` to=${res.to}` : "";
1221
+ const fallback = res.fallback_from ? ` fallback_from=${res.fallback_from}` : "";
1222
+ output(res, `Invoked${winner}${hop}${status}${fallback}`);
1223
+ } catch (err) {
1224
+ handleError(err);
1225
+ }
1226
+ }
1227
+ );
1228
+ }
1229
+
1230
+ // src/commands/notify.ts
1231
+ var import_commander9 = require("commander");
1170
1232
  var NOTIFY_MESSAGE_TYPES2 = [
1171
1233
  "task_request",
1172
1234
  "collaboration",
@@ -1200,7 +1262,7 @@ function formatEntry(e, index) {
1200
1262
  return lines.join("\n");
1201
1263
  }
1202
1264
  function notifyCommand() {
1203
- const cmd = new import_commander8.Command("notify").description(
1265
+ const cmd = new import_commander9.Command("notify").description(
1204
1266
  "Manage Notify-layer queue (manifest mode). For offline direct messages: acn inbox"
1205
1267
  );
1206
1268
  cmd.command("list").description("List pending notifications in your manifest queue").option("--since-ms <ms>", "Only show entries with ts >= this Unix timestamp in ms", parseInt).option("--limit <n>", "Max entries to return (default 50, max 200)", parseInt).option(
@@ -1312,7 +1374,7 @@ ${chunks.join("")}${truncatedHint}`);
1312
1374
  }
1313
1375
 
1314
1376
  // src/commands/inbox.ts
1315
- var import_commander9 = require("commander");
1377
+ var import_commander10 = require("commander");
1316
1378
  var POLICY_MODES = ["open", "manifest", "allowlist", "closed"];
1317
1379
  var MODE_DESC = {
1318
1380
  open: "open \u2014 anyone can push messages directly to your inbox",
@@ -1356,7 +1418,7 @@ function formatAllowlistEntry(e, index) {
1356
1418
  Added : ${e.created_at}${reason}`;
1357
1419
  }
1358
1420
  function inboxCommand() {
1359
- const cmd = new import_commander9.Command("inbox").description(
1421
+ const cmd = new import_commander10.Command("inbox").description(
1360
1422
  "Offline direct-delivery inbox + reception policy. For Notify-layer pull: acn notify"
1361
1423
  );
1362
1424
  cmd.command("list").description("List offline messages stored when you were unreachable").option("--limit <n>", "Max messages to return (default 100)", parseInt).option("--ack", "Clear the entire inbox after retrieval").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
@@ -1398,7 +1460,7 @@ function inboxCommand() {
1398
1460
  handleError(err);
1399
1461
  }
1400
1462
  });
1401
- const mode = new import_commander9.Command("mode").description(
1463
+ const mode = new import_commander10.Command("mode").description(
1402
1464
  "Reception policy: who can send to your inbox and how"
1403
1465
  );
1404
1466
  mode.command("get").description("Show current reception policy").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
@@ -1433,7 +1495,7 @@ ${formatPolicy(res)}`);
1433
1495
  }
1434
1496
  );
1435
1497
  cmd.addCommand(mode);
1436
- const allowlist = new import_commander9.Command("allowlist").description(
1498
+ const allowlist = new import_commander10.Command("allowlist").description(
1437
1499
  "Trusted senders (effective when mode=allowlist)"
1438
1500
  );
1439
1501
  allowlist.command("list").description("List agents on your allowlist").option("--limit <n>", "Max items to return (default 100)", parseInt).option("--offset <n>", "Pagination offset", parseInt).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
@@ -1492,7 +1554,7 @@ ${formatPolicy(res)}`);
1492
1554
  }
1493
1555
 
1494
1556
  // src/commands/listen.ts
1495
- var import_commander10 = require("commander");
1557
+ var import_commander11 = require("commander");
1496
1558
  var import_child_process3 = require("child_process");
1497
1559
  var import_ws = __toESM(require("ws"));
1498
1560
 
@@ -1507,6 +1569,33 @@ function asRecord(v) {
1507
1569
  function asNonEmptyString(v) {
1508
1570
  return typeof v === "string" && v.length > 0 ? v : null;
1509
1571
  }
1572
+ function asInferencePath(v) {
1573
+ return v === "official" || v === "byo" ? v : null;
1574
+ }
1575
+ var HOST_INFERENCE_HOSTS = /* @__PURE__ */ new Set([
1576
+ "api.agentplanet.org",
1577
+ "api.agenticplanet.space"
1578
+ ]);
1579
+ function asHostInferenceUrl(v) {
1580
+ const raw = asNonEmptyString(v);
1581
+ if (!raw) return null;
1582
+ try {
1583
+ const u = new URL(raw);
1584
+ if (u.pathname.replace(/\/+$/, "") !== "/api/inference/v1") return null;
1585
+ if (u.search || u.hash) return null;
1586
+ const host = u.hostname.toLowerCase();
1587
+ const loopback = host === "localhost" || host === "127.0.0.1" || host === "::1";
1588
+ if (u.protocol === "https:" && HOST_INFERENCE_HOSTS.has(host)) {
1589
+ return `${u.origin}/api/inference/v1`;
1590
+ }
1591
+ if (u.protocol === "http:" && loopback) {
1592
+ return `${u.origin}/api/inference/v1`;
1593
+ }
1594
+ return null;
1595
+ } catch {
1596
+ return null;
1597
+ }
1598
+ }
1510
1599
  function parseJsonRpcBody(bodyText) {
1511
1600
  let parsed;
1512
1601
  try {
@@ -1598,7 +1687,10 @@ function extractChatEnvelope(message) {
1598
1687
  gateway_message_id: asNonEmptyString(ap.message_id) ?? asNonEmptyString(ap.messageId),
1599
1688
  user_text: extractUserText(message),
1600
1689
  requested_model: requested ? requested.slice(0, 200) : null,
1601
- max_output_tokens: maxOut
1690
+ max_output_tokens: maxOut,
1691
+ hop_id: asNonEmptyString(ap.hop_id),
1692
+ inference_path: asInferencePath(ap.inference_path),
1693
+ host_inference_url: asHostInferenceUrl(ap.host_inference_url)
1602
1694
  };
1603
1695
  }
1604
1696
  function normalizeEvent(body, opts = {}) {
@@ -1657,6 +1749,115 @@ var DedupeStore = class {
1657
1749
  }
1658
1750
  };
1659
1751
 
1752
+ // src/commands/official-hop-door.ts
1753
+ var import_node_http = __toESM(require("http"));
1754
+ function shouldOpenOfficialDoor(opts) {
1755
+ return Boolean(
1756
+ opts.inferencePath === "official" && opts.hopId?.trim() && asHostInferenceUrl(opts.hostInferenceUrl) && opts.jwt?.trim()
1757
+ );
1758
+ }
1759
+ function readBody(req) {
1760
+ return new Promise((resolve, reject) => {
1761
+ const chunks = [];
1762
+ req.on("data", (c) => chunks.push(Buffer.from(c)));
1763
+ req.on("end", () => resolve(Buffer.concat(chunks)));
1764
+ req.on("error", reject);
1765
+ });
1766
+ }
1767
+ function send(res, status, body, contentType = "application/json") {
1768
+ res.writeHead(status, {
1769
+ "content-type": contentType,
1770
+ "content-length": String(body.length)
1771
+ });
1772
+ res.end(body);
1773
+ }
1774
+ async function handleDoorRequest(req, res, opts) {
1775
+ const path = (req.url ?? "").split("?")[0];
1776
+ if (req.method !== "POST" || path !== "/v1/chat/completions" && path !== "/chat/completions") {
1777
+ send(res, 404, Buffer.from('{"error":"not_found"}'));
1778
+ return;
1779
+ }
1780
+ let payload;
1781
+ try {
1782
+ const raw = await readBody(req);
1783
+ payload = JSON.parse(raw.length ? raw.toString("utf-8") : "{}");
1784
+ } catch {
1785
+ send(res, 400, Buffer.from('{"error":"invalid_json"}'));
1786
+ return;
1787
+ }
1788
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
1789
+ send(res, 400, Buffer.from('{"error":"invalid_json"}'));
1790
+ return;
1791
+ }
1792
+ const body = { ...payload };
1793
+ delete body.agent_id;
1794
+ body.hop_id = opts.hopId;
1795
+ const headers = {
1796
+ authorization: `Bearer ${opts.jwt}`,
1797
+ "content-type": "application/json",
1798
+ "X-Hop-Id": opts.hopId
1799
+ };
1800
+ if (opts.agentId) headers["X-Agent-Id"] = opts.agentId;
1801
+ try {
1802
+ const upstream = await opts.fetchFn(opts.upstream, {
1803
+ method: "POST",
1804
+ headers,
1805
+ body: JSON.stringify(body)
1806
+ });
1807
+ const out = Buffer.from(await upstream.arrayBuffer());
1808
+ const ct = upstream.headers.get("content-type") || "application/json";
1809
+ send(res, upstream.status, out, ct);
1810
+ } catch (err) {
1811
+ const msg = err instanceof Error ? err.message : String(err);
1812
+ send(
1813
+ res,
1814
+ 502,
1815
+ Buffer.from(JSON.stringify({ error: `upstream_unreachable:${msg.slice(0, 120)}` }))
1816
+ );
1817
+ }
1818
+ }
1819
+ function closeServer(server) {
1820
+ return new Promise((resolve) => {
1821
+ server.closeAllConnections?.();
1822
+ server.close(() => resolve());
1823
+ });
1824
+ }
1825
+ async function startOfficialHopDoor(opts) {
1826
+ const dest = asHostInferenceUrl(opts.hostInferenceUrl);
1827
+ const hopId = opts.hopId.trim();
1828
+ const jwt = opts.jwt.trim();
1829
+ if (!dest || !hopId || !jwt) return null;
1830
+ const fetchFn = opts.fetchFn ?? fetch;
1831
+ const upstream = `${dest}/chat/completions`;
1832
+ const server = import_node_http.default.createServer((req, res) => {
1833
+ void handleDoorRequest(req, res, {
1834
+ upstream,
1835
+ hopId,
1836
+ agentId: opts.agentId,
1837
+ jwt,
1838
+ fetchFn
1839
+ });
1840
+ });
1841
+ try {
1842
+ await new Promise((resolve, reject) => {
1843
+ server.once("error", reject);
1844
+ server.listen(0, "127.0.0.1", () => resolve());
1845
+ });
1846
+ } catch {
1847
+ return null;
1848
+ }
1849
+ const addr = server.address();
1850
+ const port = typeof addr === "object" && addr ? addr.port : 0;
1851
+ if (!port) {
1852
+ await closeServer(server);
1853
+ return null;
1854
+ }
1855
+ return {
1856
+ baseUrl: `http://127.0.0.1:${port}/v1`,
1857
+ close: () => closeServer(server)
1858
+ };
1859
+ }
1860
+
1660
1861
  // src/commands/chat-writeback.ts
1661
1862
  var DEFAULT_COMPLETE_TIMEOUT_MS = 12e4;
1662
1863
  var DEFAULT_WRITEBACK_TIMEOUT_MS = 3e4;
@@ -1741,8 +1942,8 @@ function extractUsage(payload) {
1741
1942
  const rec = asRecord2(payload);
1742
1943
  if (!rec) return void 0;
1743
1944
  const usageRec = asRecord2(rec.usage) ?? rec;
1744
- const input = asNonNegInt(usageRec.input_tokens) ?? asNonNegInt(usageRec.prompt_tokens);
1745
- const output2 = asNonNegInt(usageRec.output_tokens) ?? asNonNegInt(usageRec.completion_tokens);
1945
+ const input = asNonNegInt(usageRec.input_tokens) ?? asNonNegInt(usageRec.prompt_tokens) ?? asNonNegInt(usageRec.input);
1946
+ const output2 = asNonNegInt(usageRec.output_tokens) ?? asNonNegInt(usageRec.completion_tokens) ?? asNonNegInt(usageRec.output);
1746
1947
  if (input === null && output2 === null) return void 0;
1747
1948
  const out = {
1748
1949
  input_tokens: input ?? 0,
@@ -1754,6 +1955,18 @@ function extractUsage(payload) {
1754
1955
  }
1755
1956
  const modelId = extractModelId(payload);
1756
1957
  if (modelId) out.model_id = modelId;
1958
+ const reasoning = asNonNegInt(usageRec.reasoning_tokens) ?? asNonNegInt(usageRec.reasoningTokens);
1959
+ const cacheRead = asNonNegInt(usageRec.cache_read_tokens) ?? asNonNegInt(usageRec.cacheRead);
1960
+ const cacheWrite = asNonNegInt(usageRec.cache_write_tokens) ?? asNonNegInt(usageRec.cacheWrite);
1961
+ const total = asNonNegInt(usageRec.total_tokens) ?? asNonNegInt(usageRec.total);
1962
+ const duration = asNonNegInt(usageRec.duration_ms) ?? asNonNegInt(usageRec.durationMs) ?? asNonNegInt(rec.duration_ms) ?? asNonNegInt(rec.durationMs);
1963
+ const provider = typeof usageRec.provider === "string" && usageRec.provider.trim() || typeof rec.provider === "string" && rec.provider.trim() || "";
1964
+ if (reasoning !== null) out.reasoning_tokens = reasoning;
1965
+ if (cacheRead !== null) out.cache_read_tokens = cacheRead;
1966
+ if (cacheWrite !== null) out.cache_write_tokens = cacheWrite;
1967
+ if (total !== null) out.total_tokens = total;
1968
+ if (duration !== null) out.duration_ms = duration;
1969
+ if (provider) out.provider = provider.slice(0, 80);
1757
1970
  return out;
1758
1971
  }
1759
1972
  function parseCompletePayload(payload) {
@@ -1811,6 +2024,34 @@ async function mintAgentJwt(opts, fetchFn = fetch) {
1811
2024
  function clearAgentJwtCache() {
1812
2025
  cachedJwt = null;
1813
2026
  }
2027
+ function completeInferenceEnv(event, opts, jwt, door) {
2028
+ const extra = { ACN_AGENT_ID: opts.agentId };
2029
+ const chat = event.chat;
2030
+ if (chat?.hop_id) extra.ACN_CHAT_HOP_ID = chat.hop_id;
2031
+ if (chat?.inference_path) extra.ACN_INFERENCE_PATH = chat.inference_path;
2032
+ if (chat?.host_inference_url) {
2033
+ extra.ACN_HOST_INFERENCE_URL = chat.host_inference_url;
2034
+ }
2035
+ if (jwt) extra.ACN_AGENT_JWT = jwt;
2036
+ if (door?.baseUrl && jwt) {
2037
+ extra.OPENAI_BASE_URL = door.baseUrl;
2038
+ extra.OPENAI_API_KEY = jwt;
2039
+ }
2040
+ return { ...process.env, ...extra };
2041
+ }
2042
+ function completeInferenceHeaders(event, opts) {
2043
+ const headers = {
2044
+ "content-type": "application/json"
2045
+ };
2046
+ if (opts.agentId) headers["X-ACN-Agent-Id"] = opts.agentId;
2047
+ const chat = event.chat;
2048
+ if (chat?.hop_id) headers["X-ACN-Hop-Id"] = chat.hop_id;
2049
+ if (chat?.inference_path) headers["X-ACN-Inference-Path"] = chat.inference_path;
2050
+ if (chat?.host_inference_url) {
2051
+ headers["X-ACN-Host-Inference-Url"] = chat.host_inference_url;
2052
+ }
2053
+ return headers;
2054
+ }
1814
2055
  async function completeViaHttp(event, opts, deps) {
1815
2056
  const fetchFn = deps.fetchFn ?? fetch;
1816
2057
  const timeoutMs = opts.completeTimeoutMs ?? DEFAULT_COMPLETE_TIMEOUT_MS;
@@ -1819,7 +2060,7 @@ async function completeViaHttp(event, opts, deps) {
1819
2060
  try {
1820
2061
  const res = await fetchFn(opts.completeUrl, {
1821
2062
  method: "POST",
1822
- headers: { "content-type": "application/json" },
2063
+ headers: completeInferenceHeaders(event, opts),
1823
2064
  body: JSON.stringify(event),
1824
2065
  signal: controller.signal
1825
2066
  });
@@ -1844,13 +2085,16 @@ async function completeViaHttp(event, opts, deps) {
1844
2085
  clearTimeout(timer);
1845
2086
  }
1846
2087
  }
1847
- function completeViaExec(event, opts, deps) {
2088
+ function spawnCompleteExec(event, opts, deps, jwt, door) {
1848
2089
  const spawnFn = deps.spawnFn ?? import_child_process.spawn;
1849
2090
  const timeoutMs = opts.completeTimeoutMs ?? DEFAULT_COMPLETE_TIMEOUT_MS;
1850
2091
  const body = Buffer.from(JSON.stringify(event), "utf-8");
1851
2092
  return new Promise((resolve) => {
1852
2093
  let settled = false;
1853
- const child = spawnFn(opts.completeExec, { shell: true });
2094
+ const child = spawnFn(opts.completeExec, {
2095
+ shell: true,
2096
+ env: completeInferenceEnv(event, opts, jwt, door)
2097
+ });
1854
2098
  const stdout = [];
1855
2099
  const stderr = [];
1856
2100
  const finish = (result) => {
@@ -1889,6 +2133,44 @@ function completeViaExec(event, opts, deps) {
1889
2133
  child.stdin?.end(body);
1890
2134
  });
1891
2135
  }
2136
+ async function completeViaExec(event, opts, deps, jwt) {
2137
+ let door = null;
2138
+ const logFn = deps.logFn ?? ((line) => console.error(line));
2139
+ try {
2140
+ if (shouldOpenOfficialDoor({
2141
+ inferencePath: event.chat?.inference_path,
2142
+ hopId: event.chat?.hop_id,
2143
+ hostInferenceUrl: event.chat?.host_inference_url,
2144
+ jwt
2145
+ })) {
2146
+ try {
2147
+ door = await startOfficialHopDoor({
2148
+ hostInferenceUrl: event.chat.host_inference_url,
2149
+ hopId: event.chat.hop_id,
2150
+ agentId: opts.agentId,
2151
+ jwt,
2152
+ fetchFn: deps.fetchFn
2153
+ });
2154
+ } catch {
2155
+ door = null;
2156
+ }
2157
+ if (door) {
2158
+ logFn(
2159
+ `[acn listen] official_door chat_id=${event.chat.chat_id} base=${door.baseUrl}`
2160
+ );
2161
+ } else {
2162
+ logFn(
2163
+ `[acn listen] official_door_skipped chat_id=${event.chat.chat_id}`
2164
+ );
2165
+ }
2166
+ }
2167
+ return await spawnCompleteExec(event, opts, deps, jwt, door);
2168
+ } finally {
2169
+ if (door) {
2170
+ await door.close().catch(() => void 0);
2171
+ }
2172
+ }
2173
+ }
1892
2174
  async function postWriteback(event, complete, opts, deps) {
1893
2175
  const chat = event.chat;
1894
2176
  if (!chat) return { ok: false, reason: "no_chat_envelope" };
@@ -1926,6 +2208,24 @@ async function postWriteback(event, complete, opts, deps) {
1926
2208
  if (complete.usage.model_id) {
1927
2209
  usageBody.model_id = complete.usage.model_id;
1928
2210
  }
2211
+ if (complete.usage.reasoning_tokens != null) {
2212
+ usageBody.reasoning_tokens = complete.usage.reasoning_tokens;
2213
+ }
2214
+ if (complete.usage.cache_read_tokens != null) {
2215
+ usageBody.cache_read_tokens = complete.usage.cache_read_tokens;
2216
+ }
2217
+ if (complete.usage.cache_write_tokens != null) {
2218
+ usageBody.cache_write_tokens = complete.usage.cache_write_tokens;
2219
+ }
2220
+ if (complete.usage.total_tokens != null) {
2221
+ usageBody.total_tokens = complete.usage.total_tokens;
2222
+ }
2223
+ if (complete.usage.duration_ms != null) {
2224
+ usageBody.duration_ms = complete.usage.duration_ms;
2225
+ }
2226
+ if (complete.usage.provider) {
2227
+ usageBody.provider = complete.usage.provider;
2228
+ }
1929
2229
  body.usage = usageBody;
1930
2230
  } else if (complete.modelId) {
1931
2231
  body.usage = { model_id: complete.modelId };
@@ -1989,7 +2289,12 @@ async function postWriteback(event, complete, opts, deps) {
1989
2289
  async function handleChatWriteback(event, opts, deps = {}) {
1990
2290
  const logFn = deps.logFn ?? ((line) => console.error(line));
1991
2291
  if (!event.chat) return { ok: false, reason: "no_chat_envelope" };
1992
- const completed = opts.completeUrl ? await completeViaHttp(event, opts, deps) : await completeViaExec(event, opts, deps);
2292
+ let jwt = null;
2293
+ if (event.chat.inference_path === "official" && opts.completeExec) {
2294
+ const minted = await mintAgentJwt(opts, deps.fetchFn ?? fetch);
2295
+ if (minted.ok) jwt = minted.token;
2296
+ }
2297
+ const completed = opts.completeUrl ? await completeViaHttp(event, opts, deps) : await completeViaExec(event, opts, deps, jwt);
1993
2298
  if (!completed.ok) {
1994
2299
  logFn(
1995
2300
  `[acn listen] chat_complete_failed chat_id=${event.chat.chat_id} message_id=${event.message_id} reason=${completed.reason}`
@@ -2214,7 +2519,7 @@ function formatWakeFailed(event, reason) {
2214
2519
  function formatDeduped(event) {
2215
2520
  return `[acn listen] deduped key=${dedupeKey(event)}`;
2216
2521
  }
2217
- function dispatchLocalReceiver(correlationId, bodyText, opts, dedupeStore, send, deps = {}) {
2522
+ function dispatchLocalReceiver(correlationId, bodyText, opts, dedupeStore, send2, deps = {}) {
2218
2523
  const logFn = deps.logFn ?? ((line) => console.error(line));
2219
2524
  const result = processIncomingRequest(
2220
2525
  correlationId,
@@ -2223,7 +2528,7 @@ function dispatchLocalReceiver(correlationId, bodyText, opts, dedupeStore, send,
2223
2528
  dedupeStore,
2224
2529
  deps
2225
2530
  );
2226
- send(result.response);
2531
+ send2(result.response);
2227
2532
  if (result.dedupeHit && result.event) {
2228
2533
  logFn(formatDeduped(result.event));
2229
2534
  return;
@@ -2284,7 +2589,7 @@ function errorResponse(id, status, detail) {
2284
2589
  body: JSON.stringify({ error: detail })
2285
2590
  };
2286
2591
  }
2287
- async function dispatchA2aRequest(frame, opts, send, deps = {}) {
2592
+ async function dispatchA2aRequest(frame, opts, send2, deps = {}) {
2288
2593
  const bodyBuf = decodeBody(frame);
2289
2594
  try {
2290
2595
  if (opts.runtime) {
@@ -2294,7 +2599,7 @@ async function dispatchA2aRequest(frame, opts, send, deps = {}) {
2294
2599
  bodyBuf.toString("utf-8"),
2295
2600
  opts.runtime,
2296
2601
  store,
2297
- send,
2602
+ send2,
2298
2603
  {
2299
2604
  fetchFn: deps.fetchFn,
2300
2605
  spawnFn: deps.spawnFn,
@@ -2304,17 +2609,17 @@ async function dispatchA2aRequest(frame, opts, send, deps = {}) {
2304
2609
  return;
2305
2610
  }
2306
2611
  if (opts.forward) {
2307
- await forwardToHttp(frame, bodyBuf, opts.forward, deps.fetchFn ?? fetch, send);
2612
+ await forwardToHttp(frame, bodyBuf, opts.forward, deps.fetchFn ?? fetch, send2);
2308
2613
  return;
2309
2614
  }
2310
2615
  if (opts.exec) {
2311
- send(await runExec(frame, bodyBuf, opts.exec, deps.spawnFn ?? import_child_process3.spawn));
2616
+ send2(await runExec(frame, bodyBuf, opts.exec, deps.spawnFn ?? import_child_process3.spawn));
2312
2617
  return;
2313
2618
  }
2314
- send(errorResponse(frame.id, 500, "no handler configured"));
2619
+ send2(errorResponse(frame.id, 500, "no handler configured"));
2315
2620
  } catch (err) {
2316
2621
  const msg = err instanceof Error ? err.message : String(err);
2317
- send(errorResponse(frame.id, 502, `handler failed: ${msg}`));
2622
+ send2(errorResponse(frame.id, 502, `handler failed: ${msg}`));
2318
2623
  }
2319
2624
  }
2320
2625
  function buildForwardHeaders(frame) {
@@ -2324,7 +2629,7 @@ function buildForwardHeaders(frame) {
2324
2629
  }
2325
2630
  return headers;
2326
2631
  }
2327
- async function forwardToHttp(frame, bodyBuf, base, fetchFn, send) {
2632
+ async function forwardToHttp(frame, bodyBuf, base, fetchFn, send2) {
2328
2633
  const suffix = frame.path && frame.path !== "/" ? "/" + frame.path.replace(/^\//, "") : "";
2329
2634
  const targetUrl = base.replace(/\/$/, "") + suffix;
2330
2635
  const method = (frame.method ?? "POST").toUpperCase();
@@ -2342,7 +2647,7 @@ async function forwardToHttp(frame, bodyBuf, base, fetchFn, send) {
2342
2647
  const { done, value } = await reader.read();
2343
2648
  if (done) break;
2344
2649
  if (value && value.length > 0) {
2345
- send({
2650
+ send2({
2346
2651
  type: "a2a_stream_chunk",
2347
2652
  id: frame.id,
2348
2653
  seq: seq++,
@@ -2351,17 +2656,17 @@ async function forwardToHttp(frame, bodyBuf, base, fetchFn, send) {
2351
2656
  });
2352
2657
  }
2353
2658
  }
2354
- send({ type: "a2a_stream_end", id: frame.id, status: res.status });
2659
+ send2({ type: "a2a_stream_end", id: frame.id, status: res.status });
2355
2660
  } catch (err) {
2356
2661
  const msg = err instanceof Error ? err.message : String(err);
2357
- send({ type: "a2a_stream_end", id: frame.id, error: msg });
2662
+ send2({ type: "a2a_stream_end", id: frame.id, error: msg });
2358
2663
  } finally {
2359
2664
  reader.releaseLock();
2360
2665
  }
2361
2666
  return;
2362
2667
  }
2363
2668
  const respText = await res.text();
2364
- send({
2669
+ send2({
2365
2670
  type: "a2a_response",
2366
2671
  id: frame.id,
2367
2672
  status: res.status,
@@ -2472,12 +2777,12 @@ function runListener(cfg) {
2472
2777
  if (!frame || typeof frame !== "object") return;
2473
2778
  const f = frame;
2474
2779
  if (f.type === "a2a_request" && typeof f.id === "string") {
2475
- const send = (out) => {
2780
+ const send2 = (out) => {
2476
2781
  if (ws.readyState === import_ws.default.OPEN) {
2477
2782
  ws.send(JSON.stringify(out));
2478
2783
  }
2479
2784
  };
2480
- void dispatchA2aRequest(f, cfg, send, { dedupeStore });
2785
+ void dispatchA2aRequest(f, cfg, send2, { dedupeStore });
2481
2786
  }
2482
2787
  });
2483
2788
  ws.on("close", (code, reason) => {
@@ -2526,7 +2831,7 @@ function validateListenHandlerFlags(opts) {
2526
2831
  });
2527
2832
  }
2528
2833
  function listenCommand() {
2529
- const cmd = new import_commander10.Command("listen").description(
2834
+ const cmd = new import_commander11.Command("listen").description(
2530
2835
  "Hold an outbound connection to ACN and answer relayed A2A requests in real time (ADR-0012 Mode B). Prefer --runtime for production; --forward/--exec remain as compatibility tunnels."
2531
2836
  ).option(
2532
2837
  "--runtime <id>",
@@ -2704,7 +3009,7 @@ function listenCommand() {
2704
3009
  }
2705
3010
 
2706
3011
  // src/commands/delivery.ts
2707
- var import_commander11 = require("commander");
3012
+ var import_commander12 = require("commander");
2708
3013
  var DELIVERY_DESC = {
2709
3014
  direct: "direct (Mode A) \u2014 ACN dials your public A2A endpoint over HTTP",
2710
3015
  relay: "relay (Mode B) \u2014 hold an outbound WebSocket with `acn listen`; no public URL",
@@ -2743,7 +3048,7 @@ function formatDelivery(d) {
2743
3048
  return lines.join("\n");
2744
3049
  }
2745
3050
  function deliveryCommand() {
2746
- const cmd = new import_commander11.Command("delivery").description(
3051
+ const cmd = new import_commander12.Command("delivery").description(
2747
3052
  "Inbound delivery transport (Mode A direct / Mode B relay). Orthogonal to reception policy (`acn inbox mode`)."
2748
3053
  );
2749
3054
  cmd.command("get").description("Show derived delivery transport (direct | relay | none)").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
@@ -2804,7 +3109,7 @@ function deliveryCommand() {
2804
3109
  }
2805
3110
 
2806
3111
  // src/commands/session.ts
2807
- var import_commander12 = require("commander");
3112
+ var import_commander13 = require("commander");
2808
3113
  function requireAgentId4() {
2809
3114
  const config = loadConfig();
2810
3115
  if (!config.api_key) {
@@ -2849,7 +3154,7 @@ function formatEntry2(s, index) {
2849
3154
  return lines.join("\n");
2850
3155
  }
2851
3156
  function sessionCommand() {
2852
- const cmd = new import_commander12.Command("session").description(
3157
+ const cmd = new import_commander13.Command("session").description(
2853
3158
  "Real-time session layer: bidirectional channel between two agents"
2854
3159
  );
2855
3160
  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(
@@ -2927,7 +3232,7 @@ ${formatEntry2(res)}`);
2927
3232
  }
2928
3233
 
2929
3234
  // src/commands/subnet.ts
2930
- var import_commander13 = require("commander");
3235
+ var import_commander14 = require("commander");
2931
3236
  function requireAgentId5() {
2932
3237
  const config = loadConfig();
2933
3238
  if (!config.api_key) {
@@ -2940,7 +3245,7 @@ function requireAgentId5() {
2940
3245
  }
2941
3246
  return config.agent_id;
2942
3247
  }
2943
- function requireApiKey() {
3248
+ function requireApiKey2() {
2944
3249
  const config = loadConfig();
2945
3250
  if (!config.api_key) {
2946
3251
  console.error("No API key found. Run `acn join` first or `acn config set api-key <key>`.");
@@ -3015,7 +3320,7 @@ function formatSubnet(s, index) {
3015
3320
  return lines.join("\n");
3016
3321
  }
3017
3322
  function subnetCommand() {
3018
- const cmd = new import_commander13.Command("subnet").description("Manage ACN subnets");
3323
+ const cmd = new import_commander14.Command("subnet").description("Manage ACN subnets");
3019
3324
  cmd.command("list").description(
3020
3325
  "List subnets. Without --all/--parent shows only subnets you have joined."
3021
3326
  ).option("--all", "Show all public subnets on ACN (not just your own)").option(
@@ -3232,7 +3537,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3232
3537
  handleError(err);
3233
3538
  }
3234
3539
  });
3235
- const requests = new import_commander13.Command("requests").description(
3540
+ const requests = new import_commander14.Command("requests").description(
3236
3541
  "Manage join-requests for a subnet (ADR-0004)"
3237
3542
  );
3238
3543
  requests.command("list <subnet_id>").description(
@@ -3246,7 +3551,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3246
3551
  "join_request"
3247
3552
  ).option("--limit <n>", "Page size (1-500, default 100)", "100").option("--offset <n>", "Page offset (default 0)", "0").action(
3248
3553
  async (subnetId, opts) => {
3249
- requireApiKey();
3554
+ requireApiKey2();
3250
3555
  const params = {};
3251
3556
  if (opts.status) params.status = opts.status;
3252
3557
  if (opts.kind) params.kind = opts.kind;
@@ -3312,7 +3617,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3312
3617
  });
3313
3618
  requests.command("approve <subnet_id>").description("Owner-only: approve a pending join_request (CAS pending \u2192 approved).").requiredOption("--request-id <rid>", "Join request ID to approve").option("--note <text>", "Optional audit note (\u2264500 chars)").action(
3314
3619
  async (subnetId, opts) => {
3315
- requireApiKey();
3620
+ requireApiKey2();
3316
3621
  const body = {};
3317
3622
  if (opts.note !== void 0) body.note = opts.note;
3318
3623
  try {
@@ -3331,7 +3636,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3331
3636
  );
3332
3637
  requests.command("reject <subnet_id>").description("Owner-only: reject a pending join_request (CAS pending \u2192 rejected).").requiredOption("--request-id <rid>", "Join request ID to reject").option("--note <text>", "Optional audit note (\u2264500 chars)").action(
3333
3638
  async (subnetId, opts) => {
3334
- requireApiKey();
3639
+ requireApiKey2();
3335
3640
  const body = {};
3336
3641
  if (opts.note !== void 0) body.note = opts.note;
3337
3642
  try {
@@ -3352,7 +3657,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3352
3657
  "Applicant-only: withdraw your own pending join_request (CAS pending \u2192 withdrawn)."
3353
3658
  ).requiredOption("--request-id <rid>", "Your join request ID").option("--note <text>", "Optional audit note (\u2264500 chars)").action(
3354
3659
  async (subnetId, opts) => {
3355
- requireApiKey();
3660
+ requireApiKey2();
3356
3661
  const body = {};
3357
3662
  if (opts.note !== void 0) body.note = opts.note;
3358
3663
  try {
@@ -3374,14 +3679,14 @@ ${JSON.stringify(res.agents, null, 2)}`);
3374
3679
  }
3375
3680
  );
3376
3681
  cmd.addCommand(requests);
3377
- const invitations = new import_commander13.Command("invitations").description(
3682
+ const invitations = new import_commander14.Command("invitations").description(
3378
3683
  "Manage invitations on a subnet (ADR-0004)"
3379
3684
  );
3380
3685
  invitations.command("send <subnet_id>").description(
3381
3686
  "Owner-only: invite an agent to a subnet. Auto-merges with a target's pending join_request (collapses to auto-approval)."
3382
3687
  ).requiredOption("--agent-id <aid>", "Agent ID to invite").option("--note <text>", "Optional audit note (\u2264500 chars)").action(
3383
3688
  async (subnetId, opts) => {
3384
- requireApiKey();
3689
+ requireApiKey2();
3385
3690
  const body = { agent_id: opts.agentId };
3386
3691
  if (opts.note !== void 0) body.note = opts.note;
3387
3692
  try {
@@ -3400,7 +3705,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3400
3705
  "Filter by status: pending | approved | rejected | withdrawn"
3401
3706
  ).option("--limit <n>", "Page size (1-500, default 100)", "100").option("--offset <n>", "Page offset (default 0)", "0").action(
3402
3707
  async (subnetId, opts) => {
3403
- requireApiKey();
3708
+ requireApiKey2();
3404
3709
  const params = {};
3405
3710
  if (opts.status) params.status = opts.status;
3406
3711
  if (opts.limit) params.limit = opts.limit;
@@ -3453,7 +3758,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3453
3758
  "Invitee-only: accept a pending invitation (CAS pending \u2192 approved). Side effect: you join the subnet."
3454
3759
  ).requiredOption("--invitation-id <iid>", "Invitation ID to accept").option("--note <text>", "Optional audit note (\u2264500 chars)").action(
3455
3760
  async (subnetId, opts) => {
3456
- requireApiKey();
3761
+ requireApiKey2();
3457
3762
  const body = {};
3458
3763
  if (opts.note !== void 0) body.note = opts.note;
3459
3764
  try {
@@ -3474,7 +3779,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3474
3779
  "Invitee-only: reject a pending invitation (CAS pending \u2192 rejected). No membership change."
3475
3780
  ).requiredOption("--invitation-id <iid>", "Invitation ID to reject").option("--note <text>", "Optional audit note (\u2264500 chars)").action(
3476
3781
  async (subnetId, opts) => {
3477
- requireApiKey();
3782
+ requireApiKey2();
3478
3783
  const body = {};
3479
3784
  if (opts.note !== void 0) body.note = opts.note;
3480
3785
  try {
@@ -3495,7 +3800,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3495
3800
  "Owner-only: cancel a pending invitation (CAS pending \u2192 withdrawn)."
3496
3801
  ).requiredOption("--invitation-id <iid>", "Invitation ID to cancel").action(
3497
3802
  async (subnetId, opts) => {
3498
- requireApiKey();
3803
+ requireApiKey2();
3499
3804
  try {
3500
3805
  const res = await acnDelete(
3501
3806
  `/subnets/${subnetId}/invitations/${opts.invitationId}`
@@ -3510,12 +3815,12 @@ ${JSON.stringify(res.agents, null, 2)}`);
3510
3815
  }
3511
3816
  );
3512
3817
  cmd.addCommand(invitations);
3513
- const allowlist = new import_commander13.Command("allowlist").description(
3818
+ const allowlist = new import_commander14.Command("allowlist").description(
3514
3819
  "Manage a subnet allowlist (ADR-0004)"
3515
3820
  );
3516
3821
  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(
3517
3822
  async (subnetId, opts) => {
3518
- requireApiKey();
3823
+ requireApiKey2();
3519
3824
  const params = {};
3520
3825
  if (opts.limit) params.limit = opts.limit;
3521
3826
  if (opts.offset) params.offset = opts.offset;
@@ -3544,7 +3849,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3544
3849
  "Owner-only: pre-authorise an agent on the subnet allowlist. 409 ALREADY_ON_ALLOWLIST on duplicate."
3545
3850
  ).requiredOption("--agent-id <aid>", "Agent ID to add").action(
3546
3851
  async (subnetId, opts) => {
3547
- requireApiKey();
3852
+ requireApiKey2();
3548
3853
  try {
3549
3854
  const res = await acnPost(
3550
3855
  `/subnets/${subnetId}/allowlist`,
@@ -3563,7 +3868,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3563
3868
  "Owner-only: remove an agent from the subnet allowlist. Idempotent (204 even if missing)."
3564
3869
  ).requiredOption("--agent-id <aid>", "Agent ID to remove").action(
3565
3870
  async (subnetId, opts) => {
3566
- requireApiKey();
3871
+ requireApiKey2();
3567
3872
  try {
3568
3873
  await acnDelete(
3569
3874
  `/subnets/${subnetId}/allowlist/${opts.agentId}`
@@ -3578,7 +3883,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3578
3883
  }
3579
3884
  );
3580
3885
  cmd.addCommand(allowlist);
3581
- const harness = new import_commander13.Command("harness").description("Manage Org Harness webhook for a subnet");
3886
+ const harness = new import_commander14.Command("harness").description("Manage Org Harness webhook for a subnet");
3582
3887
  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) => {
3583
3888
  const config = loadConfig();
3584
3889
  if (!config.api_key) {
@@ -3621,7 +3926,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
3621
3926
  }
3622
3927
 
3623
3928
  // src/commands/org.ts
3624
- var import_commander14 = require("commander");
3929
+ var import_commander15 = require("commander");
3625
3930
  function formatOrg(o) {
3626
3931
  const lines = [
3627
3932
  ` ID : ${o.org_id}`,
@@ -3638,7 +3943,7 @@ function formatOrg(o) {
3638
3943
  return lines.join("\n");
3639
3944
  }
3640
3945
  function orgCommand() {
3641
- const cmd = new import_commander14.Command("org").description("Manage ACN organisations (Org Harness)");
3946
+ const cmd = new import_commander15.Command("org").description("Manage ACN organisations (Org Harness)");
3642
3947
  cmd.command("create").description("Create an Org (binds/creates a subnet fence)").requiredOption("--name <name>", "Display name").option("--steward <agent_id>", "Steward agent (required for human JWT callers)").option("--subnet <slug>", "Bind existing subnet slug (must be owned by steward)").option("--join-policy <policy>", "open | approval", "open").option("--private", "Private subnet fence", false).option("--harness-url <url>", "Register Org Harness webhook on the fence subnet").option("--harness-secret <secret>", "HMAC secret for harness webhook").action(
3643
3948
  async (opts) => {
3644
3949
  try {
@@ -3906,7 +4211,7 @@ function orgCommand() {
3906
4211
  }
3907
4212
 
3908
4213
  // src/commands/follow.ts
3909
- var import_commander15 = require("commander");
4214
+ var import_commander16 = require("commander");
3910
4215
  function requireAgentId6() {
3911
4216
  const config = loadConfig();
3912
4217
  if (!config.api_key) {
@@ -3929,7 +4234,7 @@ function formatAgent2(a, i) {
3929
4234
  ].join("\n");
3930
4235
  }
3931
4236
  function followCommand() {
3932
- const cmd = new import_commander15.Command("follow").description("Follow/unfollow agents and inspect follow graph");
4237
+ const cmd = new import_commander16.Command("follow").description("Follow/unfollow agents and inspect follow graph");
3933
4238
  cmd.command("add <target_id>").description("Follow another agent").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (targetId, opts) => {
3934
4239
  const agentId = opts.agentId ?? requireAgentId6();
3935
4240
  try {
@@ -4020,7 +4325,7 @@ function followCommand() {
4020
4325
  }
4021
4326
 
4022
4327
  // src/commands/wallet.ts
4023
- var import_commander16 = require("commander");
4328
+ var import_commander17 = require("commander");
4024
4329
  function requireAgentId7() {
4025
4330
  const config = loadConfig();
4026
4331
  if (!config.api_key) {
@@ -4063,7 +4368,7 @@ async function showWalletInfo(opts) {
4063
4368
  }
4064
4369
  }
4065
4370
  function walletCommand() {
4066
- const cmd = new import_commander16.Command("wallet").description("View and manage agent's wallet & payment info");
4371
+ const cmd = new import_commander17.Command("wallet").description("View and manage agent's wallet & payment info");
4067
4372
  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);
4068
4373
  cmd.command("set-capability").description("Declare which payment methods, networks, and wallets you accept").requiredOption(
4069
4374
  "--methods <csv>",
@@ -4242,7 +4547,7 @@ function walletCommand() {
4242
4547
  }
4243
4548
 
4244
4549
  // src/commands/pay.ts
4245
- var import_commander17 = require("commander");
4550
+ var import_commander18 = require("commander");
4246
4551
  function requireAgentId8() {
4247
4552
  const config = loadConfig();
4248
4553
  if (!config.api_key) {
@@ -4256,8 +4561,8 @@ function requireAgentId8() {
4256
4561
  return config.agent_id;
4257
4562
  }
4258
4563
  function payCommand() {
4259
- const cmd = new import_commander17.Command("pay").description("Manage payment tasks between agents");
4260
- const createCmd = new import_commander17.Command("create").description("Create a payment task to another agent");
4564
+ const cmd = new import_commander18.Command("pay").description("Manage payment tasks between agents");
4565
+ const createCmd = new import_commander18.Command("create").description("Create a payment task to another agent");
4261
4566
  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(
4262
4567
  async (opts) => {
4263
4568
  const fromAgent = requireAgentId8();
@@ -4303,7 +4608,7 @@ function payCommand() {
4303
4608
  }
4304
4609
  }
4305
4610
  );
4306
- const confirmCmd = new import_commander17.Command("confirm").description(
4611
+ const confirmCmd = new import_commander18.Command("confirm").description(
4307
4612
  "Confirm an external payment has been made (buyer only)"
4308
4613
  );
4309
4614
  confirmCmd.requiredOption("--task-id <id>", "Payment task ID to confirm").requiredOption(
@@ -4325,7 +4630,7 @@ function payCommand() {
4325
4630
  handleError(err);
4326
4631
  }
4327
4632
  });
4328
- const statusCmd = new import_commander17.Command("status").description(
4633
+ const statusCmd = new import_commander18.Command("status").description(
4329
4634
  "Show payment tasks for the authenticated agent"
4330
4635
  );
4331
4636
  statusCmd.option("--status <s>", "Filter by status (e.g. created, payment_confirmed)").option("--limit <n>", "Max results (default 50)", "50").action(async (opts) => {
@@ -4348,7 +4653,7 @@ function payCommand() {
4348
4653
 
4349
4654
  // src/index.ts
4350
4655
  var { version } = require_package();
4351
- var program = new import_commander18.Command();
4656
+ var program = new import_commander19.Command();
4352
4657
  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) => {
4353
4658
  const opts = thisCommand.opts();
4354
4659
  if (opts.json) setJsonMode(true);
@@ -4360,6 +4665,7 @@ program.addCommand(rotateKeyCommand());
4360
4665
  program.addCommand(agentsCommand());
4361
4666
  program.addCommand(tasksCommand());
4362
4667
  program.addCommand(messageCommand());
4668
+ program.addCommand(invokeCommand());
4363
4669
  program.addCommand(notifyCommand());
4364
4670
  program.addCommand(inboxCommand());
4365
4671
  program.addCommand(listenCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acnlabs/acn-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.7",
4
4
  "description": "Official CLI for ACN (Agent Collaboration Network) \u2014 zero-integration agent access",
5
5
  "main": "dist/index.js",
6
6
  "bin": {