@acnlabs/acn-cli 0.13.2 → 0.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +336 -46
- package/package.json +1 -1
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: "0.13.
|
|
34
|
+
version: "0.13.3",
|
|
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
|
|
90
|
+
var import_commander18 = require("commander");
|
|
91
91
|
|
|
92
92
|
// src/output.ts
|
|
93
93
|
var jsonMode = false;
|
|
@@ -1620,9 +1620,108 @@ function listenCommand() {
|
|
|
1620
1620
|
return cmd;
|
|
1621
1621
|
}
|
|
1622
1622
|
|
|
1623
|
-
// src/commands/
|
|
1623
|
+
// src/commands/delivery.ts
|
|
1624
1624
|
var import_commander11 = require("commander");
|
|
1625
|
+
var DELIVERY_DESC = {
|
|
1626
|
+
direct: "direct (Mode A) \u2014 ACN dials your public A2A endpoint over HTTP",
|
|
1627
|
+
relay: "relay (Mode B) \u2014 hold an outbound WebSocket with `acn listen`; no public URL",
|
|
1628
|
+
none: "none \u2014 pull/reject only (communication_policy is manifest or closed; not Mode A/B)"
|
|
1629
|
+
};
|
|
1625
1630
|
function requireAgentId3() {
|
|
1631
|
+
const config = loadConfig();
|
|
1632
|
+
if (!config.api_key) {
|
|
1633
|
+
console.error(
|
|
1634
|
+
"No API key found. Run `acn join` first or `acn config set api-key <key>`."
|
|
1635
|
+
);
|
|
1636
|
+
process.exit(1);
|
|
1637
|
+
}
|
|
1638
|
+
if (!config.agent_id) {
|
|
1639
|
+
console.error(
|
|
1640
|
+
"No agent ID found. Run `acn join` first or `acn config set agent-id <id>`."
|
|
1641
|
+
);
|
|
1642
|
+
process.exit(1);
|
|
1643
|
+
}
|
|
1644
|
+
return config.agent_id;
|
|
1645
|
+
}
|
|
1646
|
+
function formatDelivery(d) {
|
|
1647
|
+
const lines = [
|
|
1648
|
+
`Delivery : ${DELIVERY_DESC[d.delivery] ?? d.delivery}`,
|
|
1649
|
+
`Policy : ${d.communication_mode ?? "?"} (reception \u2014 not the same as delivery)`,
|
|
1650
|
+
`Endpoint : ${d.endpoint ?? "(none)"}`
|
|
1651
|
+
];
|
|
1652
|
+
if (d.a2a_handshake_ok === false) {
|
|
1653
|
+
lines.push("A2A probe: false \u2014 URL reachable but not JSON-RPC; fix the path");
|
|
1654
|
+
} else if (d.a2a_handshake_ok === true) {
|
|
1655
|
+
lines.push("A2A probe: ok");
|
|
1656
|
+
}
|
|
1657
|
+
if (d.next_step_hint) {
|
|
1658
|
+
lines.push("", d.next_step_hint);
|
|
1659
|
+
}
|
|
1660
|
+
return lines.join("\n");
|
|
1661
|
+
}
|
|
1662
|
+
function deliveryCommand() {
|
|
1663
|
+
const cmd = new import_commander11.Command("delivery").description(
|
|
1664
|
+
"Inbound delivery transport (Mode A direct / Mode B relay). Orthogonal to reception policy (`acn inbox mode`)."
|
|
1665
|
+
);
|
|
1666
|
+
cmd.command("get").description("Show derived delivery transport (direct | relay | none)").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
|
|
1667
|
+
const agentId = opts.agentId ?? requireAgentId3();
|
|
1668
|
+
try {
|
|
1669
|
+
const res = await acnGet(`/agents/${agentId}/delivery`);
|
|
1670
|
+
output(res, formatDelivery(res));
|
|
1671
|
+
} catch (err) {
|
|
1672
|
+
handleError(err);
|
|
1673
|
+
}
|
|
1674
|
+
});
|
|
1675
|
+
cmd.command("set <transport>").description(
|
|
1676
|
+
"Switch delivery without re-registering: relay (Mode B) or direct (Mode A). Requires push reception policy (open / allowlist)."
|
|
1677
|
+
).option(
|
|
1678
|
+
"-e, --endpoint <url>",
|
|
1679
|
+
"Required for direct: public A2A JSON-RPC URL (e.g. https://host/a2a)"
|
|
1680
|
+
).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(
|
|
1681
|
+
async (transport, opts) => {
|
|
1682
|
+
const agentId = opts.agentId ?? requireAgentId3();
|
|
1683
|
+
const normalized = transport.trim().toLowerCase();
|
|
1684
|
+
if (normalized !== "relay" && normalized !== "direct") {
|
|
1685
|
+
console.error(
|
|
1686
|
+
`Unknown transport "${transport}". Use: relay | direct`
|
|
1687
|
+
);
|
|
1688
|
+
process.exit(1);
|
|
1689
|
+
}
|
|
1690
|
+
if (normalized === "direct" && !opts.endpoint) {
|
|
1691
|
+
console.error(
|
|
1692
|
+
"direct requires --endpoint <url> (full A2A path, e.g. https://host/a2a)."
|
|
1693
|
+
);
|
|
1694
|
+
process.exit(1);
|
|
1695
|
+
}
|
|
1696
|
+
if (normalized === "relay" && opts.endpoint) {
|
|
1697
|
+
console.error(
|
|
1698
|
+
"relay must not include --endpoint (clear the public URL; use `acn listen`)."
|
|
1699
|
+
);
|
|
1700
|
+
process.exit(1);
|
|
1701
|
+
}
|
|
1702
|
+
const body = normalized === "relay" ? { delivery: "relay" } : { delivery: "direct", endpoint: opts.endpoint };
|
|
1703
|
+
try {
|
|
1704
|
+
const res = await acnPatch(
|
|
1705
|
+
`/agents/${agentId}/delivery`,
|
|
1706
|
+
body
|
|
1707
|
+
);
|
|
1708
|
+
const followUp = res.delivery === "relay" ? [
|
|
1709
|
+
"",
|
|
1710
|
+
"Next: keep a local A2A handler up, then:",
|
|
1711
|
+
" acn listen --forward http://localhost:PORT"
|
|
1712
|
+
] : [];
|
|
1713
|
+
output(res, [formatDelivery(res), ...followUp].join("\n"));
|
|
1714
|
+
} catch (err) {
|
|
1715
|
+
handleError(err);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
);
|
|
1719
|
+
return cmd;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// src/commands/session.ts
|
|
1723
|
+
var import_commander12 = require("commander");
|
|
1724
|
+
function requireAgentId4() {
|
|
1626
1725
|
const config = loadConfig();
|
|
1627
1726
|
if (!config.api_key) {
|
|
1628
1727
|
console.error("No API key found. Run `acn join` first or `acn config set api-key <key>`.");
|
|
@@ -1666,12 +1765,12 @@ function formatEntry2(s, index) {
|
|
|
1666
1765
|
return lines.join("\n");
|
|
1667
1766
|
}
|
|
1668
1767
|
function sessionCommand() {
|
|
1669
|
-
const cmd = new
|
|
1768
|
+
const cmd = new import_commander12.Command("session").description(
|
|
1670
1769
|
"Real-time session layer: bidirectional channel between two agents"
|
|
1671
1770
|
);
|
|
1672
1771
|
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(
|
|
1673
1772
|
async (targetId, opts) => {
|
|
1674
|
-
|
|
1773
|
+
requireAgentId4();
|
|
1675
1774
|
try {
|
|
1676
1775
|
const body = {};
|
|
1677
1776
|
if (opts.ttlSeconds !== void 0) body.ttl_seconds = opts.ttlSeconds;
|
|
@@ -1692,7 +1791,7 @@ ${formatEntry2(res)}`
|
|
|
1692
1791
|
}
|
|
1693
1792
|
);
|
|
1694
1793
|
cmd.command("accept <session_id>").description("Accept a pending session invitation (invitee only)").action(async (sessionId) => {
|
|
1695
|
-
|
|
1794
|
+
requireAgentId4();
|
|
1696
1795
|
try {
|
|
1697
1796
|
const res = await acnPost(`/sessions/${sessionId}/accept`);
|
|
1698
1797
|
output(res, `Session accepted.
|
|
@@ -1702,7 +1801,7 @@ ${formatEntry2(res)}`);
|
|
|
1702
1801
|
}
|
|
1703
1802
|
});
|
|
1704
1803
|
cmd.command("reject <session_id>").description("Reject a pending session invitation (invitee only)").action(async (sessionId) => {
|
|
1705
|
-
|
|
1804
|
+
requireAgentId4();
|
|
1706
1805
|
try {
|
|
1707
1806
|
const res = await acnPost(`/sessions/${sessionId}/reject`);
|
|
1708
1807
|
output(res, `Session rejected.
|
|
@@ -1712,7 +1811,7 @@ ${formatEntry2(res)}`);
|
|
|
1712
1811
|
}
|
|
1713
1812
|
});
|
|
1714
1813
|
cmd.command("close <session_id>").description("Close an active session (either party may close)").action(async (sessionId) => {
|
|
1715
|
-
|
|
1814
|
+
requireAgentId4();
|
|
1716
1815
|
try {
|
|
1717
1816
|
const res = await acnDelete(`/sessions/${sessionId}`);
|
|
1718
1817
|
output(res, `Session closed.
|
|
@@ -1722,7 +1821,7 @@ ${formatEntry2(res)}`);
|
|
|
1722
1821
|
}
|
|
1723
1822
|
});
|
|
1724
1823
|
cmd.command("pending").description("List pending session invitations addressed to you").action(async () => {
|
|
1725
|
-
|
|
1824
|
+
requireAgentId4();
|
|
1726
1825
|
try {
|
|
1727
1826
|
const res = await acnGet("/sessions/pending");
|
|
1728
1827
|
const sessions = res.sessions ?? [];
|
|
@@ -1744,8 +1843,8 @@ ${formatEntry2(res)}`);
|
|
|
1744
1843
|
}
|
|
1745
1844
|
|
|
1746
1845
|
// src/commands/subnet.ts
|
|
1747
|
-
var
|
|
1748
|
-
function
|
|
1846
|
+
var import_commander13 = require("commander");
|
|
1847
|
+
function requireAgentId5() {
|
|
1749
1848
|
const config = loadConfig();
|
|
1750
1849
|
if (!config.api_key) {
|
|
1751
1850
|
console.error("No API key found. Run `acn join` first or `acn config set api-key <key>`.");
|
|
@@ -1832,7 +1931,7 @@ function formatSubnet(s, index) {
|
|
|
1832
1931
|
return lines.join("\n");
|
|
1833
1932
|
}
|
|
1834
1933
|
function subnetCommand() {
|
|
1835
|
-
const cmd = new
|
|
1934
|
+
const cmd = new import_commander13.Command("subnet").description("Manage ACN subnets");
|
|
1836
1935
|
cmd.command("list").description(
|
|
1837
1936
|
"List subnets. Without --all/--parent shows only subnets you have joined."
|
|
1838
1937
|
).option("--all", "Show all public subnets on ACN (not just your own)").option(
|
|
@@ -1871,7 +1970,7 @@ function subnetCommand() {
|
|
|
1871
1970
|
` + subnets.map((s, i) => formatSubnet(s, i)).join("\n\n")
|
|
1872
1971
|
);
|
|
1873
1972
|
} else {
|
|
1874
|
-
const agentId = opts.agentId ??
|
|
1973
|
+
const agentId = opts.agentId ?? requireAgentId5();
|
|
1875
1974
|
const res = await acnGet(
|
|
1876
1975
|
`/subnets/${agentId}/subnets`
|
|
1877
1976
|
);
|
|
@@ -1910,7 +2009,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
1910
2009
|
cmd.command("join <subnet_id>").description(
|
|
1911
2010
|
"Join a subnet. ADR-0004: branches on response shape (open/allowlist/auto-invite/pending)."
|
|
1912
2011
|
).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (subnetId, opts) => {
|
|
1913
|
-
const agentId = opts.agentId ??
|
|
2012
|
+
const agentId = opts.agentId ?? requireAgentId5();
|
|
1914
2013
|
try {
|
|
1915
2014
|
const res = await acnPost(
|
|
1916
2015
|
`/agents/${agentId}/subnets/${subnetId}`
|
|
@@ -1921,7 +2020,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
1921
2020
|
}
|
|
1922
2021
|
});
|
|
1923
2022
|
cmd.command("leave <subnet_id>").description("Leave a subnet").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (subnetId, opts) => {
|
|
1924
|
-
const agentId = opts.agentId ??
|
|
2023
|
+
const agentId = opts.agentId ?? requireAgentId5();
|
|
1925
2024
|
try {
|
|
1926
2025
|
const res = await acnDelete(
|
|
1927
2026
|
`/agents/${agentId}/subnets/${subnetId}`
|
|
@@ -2049,7 +2148,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
2049
2148
|
handleError(err);
|
|
2050
2149
|
}
|
|
2051
2150
|
});
|
|
2052
|
-
const requests = new
|
|
2151
|
+
const requests = new import_commander13.Command("requests").description(
|
|
2053
2152
|
"Manage join-requests for a subnet (ADR-0004)"
|
|
2054
2153
|
);
|
|
2055
2154
|
requests.command("list <subnet_id>").description(
|
|
@@ -2093,7 +2192,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
2093
2192
|
requests.command("pending").description(
|
|
2094
2193
|
"Owner-side convenience: list pending join_requests across every subnet you own. Client-side aggregation \u2014 issues N+1 calls (one per owned subnet)."
|
|
2095
2194
|
).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
|
|
2096
|
-
const agentId = opts.agentId ??
|
|
2195
|
+
const agentId = opts.agentId ?? requireAgentId5();
|
|
2097
2196
|
try {
|
|
2098
2197
|
const subs = await acnGet(`/agents/${agentId}/subnets`);
|
|
2099
2198
|
const subnetIds = subs.subnets ?? [];
|
|
@@ -2191,7 +2290,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
2191
2290
|
}
|
|
2192
2291
|
);
|
|
2193
2292
|
cmd.addCommand(requests);
|
|
2194
|
-
const invitations = new
|
|
2293
|
+
const invitations = new import_commander13.Command("invitations").description(
|
|
2195
2294
|
"Manage invitations on a subnet (ADR-0004)"
|
|
2196
2295
|
);
|
|
2197
2296
|
invitations.command("send <subnet_id>").description(
|
|
@@ -2246,7 +2345,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
2246
2345
|
invitations.command("pending").description(
|
|
2247
2346
|
"Invitee view: list pending invitations addressed to you across all subnets (backed by GET /agents/{aid}/subnet-invitations)."
|
|
2248
2347
|
).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
|
|
2249
|
-
const agentId = opts.agentId ??
|
|
2348
|
+
const agentId = opts.agentId ?? requireAgentId5();
|
|
2250
2349
|
try {
|
|
2251
2350
|
const res = await acnGet(
|
|
2252
2351
|
`/agents/${agentId}/subnet-invitations`
|
|
@@ -2327,7 +2426,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
2327
2426
|
}
|
|
2328
2427
|
);
|
|
2329
2428
|
cmd.addCommand(invitations);
|
|
2330
|
-
const allowlist = new
|
|
2429
|
+
const allowlist = new import_commander13.Command("allowlist").description(
|
|
2331
2430
|
"Manage a subnet allowlist (ADR-0004)"
|
|
2332
2431
|
);
|
|
2333
2432
|
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(
|
|
@@ -2395,7 +2494,7 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
2395
2494
|
}
|
|
2396
2495
|
);
|
|
2397
2496
|
cmd.addCommand(allowlist);
|
|
2398
|
-
const harness = new
|
|
2497
|
+
const harness = new import_commander13.Command("harness").description("Manage Org Harness webhook for a subnet");
|
|
2399
2498
|
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) => {
|
|
2400
2499
|
const config = loadConfig();
|
|
2401
2500
|
if (!config.api_key) {
|
|
@@ -2437,9 +2536,198 @@ ${JSON.stringify(res.agents, null, 2)}`);
|
|
|
2437
2536
|
return cmd;
|
|
2438
2537
|
}
|
|
2439
2538
|
|
|
2539
|
+
// src/commands/org.ts
|
|
2540
|
+
var import_commander14 = require("commander");
|
|
2541
|
+
function formatOrg(o) {
|
|
2542
|
+
const lines = [
|
|
2543
|
+
` ID : ${o.org_id}`,
|
|
2544
|
+
` Name : ${o.display_name}`,
|
|
2545
|
+
` Status : ${o.status ?? "\u2014"}`,
|
|
2546
|
+
` Owner : ${o.owner?.kind ?? "none"}${o.owner?.subject ? ` (${o.owner.subject})` : ""}`,
|
|
2547
|
+
` Steward : ${o.steward_agent_id ?? "\u2014"}`,
|
|
2548
|
+
` Subnet : ${o.fencing?.subnet_id ?? o.subnet_id ?? "\u2014"}`
|
|
2549
|
+
];
|
|
2550
|
+
if (o.fencing?.join_policy) lines.push(` Join : ${o.fencing.join_policy}`);
|
|
2551
|
+
if (o.harness_webhook?.registered) {
|
|
2552
|
+
lines.push(` Harness : ${o.harness_webhook.url ?? "(registered)"}`);
|
|
2553
|
+
}
|
|
2554
|
+
return lines.join("\n");
|
|
2555
|
+
}
|
|
2556
|
+
function orgCommand() {
|
|
2557
|
+
const cmd = new import_commander14.Command("org").description("Manage ACN organisations (Org Harness)");
|
|
2558
|
+
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(
|
|
2559
|
+
async (opts) => {
|
|
2560
|
+
try {
|
|
2561
|
+
const body = {
|
|
2562
|
+
display_name: opts.name,
|
|
2563
|
+
is_private: Boolean(opts.private),
|
|
2564
|
+
join_policy: opts.joinPolicy ?? "open"
|
|
2565
|
+
};
|
|
2566
|
+
if (opts.steward) body.steward_agent_id = opts.steward;
|
|
2567
|
+
if (opts.subnet) body.subnet_id = opts.subnet;
|
|
2568
|
+
if (opts.harnessUrl) body.harness_url = opts.harnessUrl;
|
|
2569
|
+
if (opts.harnessSecret) body.harness_secret = opts.harnessSecret;
|
|
2570
|
+
const org = await acnPost("/orgs", body);
|
|
2571
|
+
output(org, formatOrg(org));
|
|
2572
|
+
} catch (err) {
|
|
2573
|
+
handleError(err);
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
);
|
|
2577
|
+
cmd.command("show <orgId>").description("Show Org details").action(async (orgId) => {
|
|
2578
|
+
try {
|
|
2579
|
+
const org = await acnGet(`/orgs/${orgId}`);
|
|
2580
|
+
output(org, formatOrg(org));
|
|
2581
|
+
} catch (err) {
|
|
2582
|
+
handleError(err);
|
|
2583
|
+
}
|
|
2584
|
+
});
|
|
2585
|
+
cmd.command("update <orgId>").description("Update Org charter / plugins / display name").option("--name <name>", "New display name").option("--charter <json>", "Charter JSON object").option("--plugins <json>", "Plugins JSON object (merged)").action(
|
|
2586
|
+
async (orgId, opts) => {
|
|
2587
|
+
try {
|
|
2588
|
+
const body = {};
|
|
2589
|
+
if (opts.name) body.display_name = opts.name;
|
|
2590
|
+
if (opts.charter) body.charter = JSON.parse(opts.charter);
|
|
2591
|
+
if (opts.plugins) body.plugins = JSON.parse(opts.plugins);
|
|
2592
|
+
const org = await acnPatch(`/orgs/${orgId}`, body);
|
|
2593
|
+
output(org, formatOrg(org));
|
|
2594
|
+
} catch (err) {
|
|
2595
|
+
handleError(err);
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
);
|
|
2599
|
+
const members = cmd.command("members").description("Manage Org members");
|
|
2600
|
+
members.command("list <orgId>").description("List active members (marks degraded vs subnet fence)").action(async (orgId) => {
|
|
2601
|
+
try {
|
|
2602
|
+
const res = await acnGet(`/orgs/${orgId}/members`);
|
|
2603
|
+
const text = (res.members ?? []).map((m) => {
|
|
2604
|
+
const flags = [];
|
|
2605
|
+
if (m.acn?.degraded) flags.push("degraded");
|
|
2606
|
+
if (m.acn && !m.acn.subnet_member) flags.push("not-in-subnet");
|
|
2607
|
+
const flagStr = flags.length ? ` [${flags.join(",")}]` : "";
|
|
2608
|
+
return ` ${m.agent_id} role=${m.role} status=${m.status}${flagStr}`;
|
|
2609
|
+
}).join("\n");
|
|
2610
|
+
const header = res.degraded_count || res.fence_missing ? ` (degraded=${res.degraded_count} fence_missing=${res.fence_missing})
|
|
2611
|
+
` : "";
|
|
2612
|
+
output(res, header + (text || " (no members)"));
|
|
2613
|
+
} catch (err) {
|
|
2614
|
+
handleError(err);
|
|
2615
|
+
}
|
|
2616
|
+
});
|
|
2617
|
+
members.command("add <orgId> <agentId>").description("Add an agent member").option("--role <role>", "Member role", "worker").action(async (orgId, agentId, opts) => {
|
|
2618
|
+
try {
|
|
2619
|
+
const m = await acnPost(`/orgs/${orgId}/members`, {
|
|
2620
|
+
agent_id: agentId,
|
|
2621
|
+
role: opts.role
|
|
2622
|
+
});
|
|
2623
|
+
output(m, `Added ${m.agent_id} as ${m.role}`);
|
|
2624
|
+
} catch (err) {
|
|
2625
|
+
handleError(err);
|
|
2626
|
+
}
|
|
2627
|
+
});
|
|
2628
|
+
members.command("remove <orgId> <agentId>").description("Remove an agent member").action(async (orgId, agentId) => {
|
|
2629
|
+
try {
|
|
2630
|
+
const m = await acnDelete(`/orgs/${orgId}/members/${agentId}`);
|
|
2631
|
+
output(m, `Removed ${m.agent_id}`);
|
|
2632
|
+
} catch (err) {
|
|
2633
|
+
handleError(err);
|
|
2634
|
+
}
|
|
2635
|
+
});
|
|
2636
|
+
cmd.command("claim <orgId>").description("Claim ownership of an unclaimed Org (created_by only)").option("--as <kind>", "human | agent").option("--subject <id>", "Owner subject (defaults to caller)").action(async (orgId, opts) => {
|
|
2637
|
+
try {
|
|
2638
|
+
const body = {};
|
|
2639
|
+
if (opts.as) body.owner_kind = opts.as;
|
|
2640
|
+
if (opts.subject) body.owner_subject = opts.subject;
|
|
2641
|
+
const org = await acnPost(`/orgs/${orgId}/claim`, body);
|
|
2642
|
+
output(org, formatOrg(org));
|
|
2643
|
+
} catch (err) {
|
|
2644
|
+
handleError(err);
|
|
2645
|
+
}
|
|
2646
|
+
});
|
|
2647
|
+
cmd.command("transfer <orgId>").description("Transfer Org ownership").requiredOption("--kind <kind>", "human | agent").requiredOption("--subject <id>", "New owner subject").action(async (orgId, opts) => {
|
|
2648
|
+
try {
|
|
2649
|
+
const org = await acnPost(`/orgs/${orgId}/transfer`, {
|
|
2650
|
+
new_owner_kind: opts.kind,
|
|
2651
|
+
new_owner_subject: opts.subject
|
|
2652
|
+
});
|
|
2653
|
+
output(org, formatOrg(org));
|
|
2654
|
+
} catch (err) {
|
|
2655
|
+
handleError(err);
|
|
2656
|
+
}
|
|
2657
|
+
});
|
|
2658
|
+
cmd.command("release <orgId>").description("Release Org ownership back to none").action(async (orgId) => {
|
|
2659
|
+
try {
|
|
2660
|
+
const org = await acnPost(`/orgs/${orgId}/release`, {});
|
|
2661
|
+
output(org, formatOrg(org));
|
|
2662
|
+
} catch (err) {
|
|
2663
|
+
handleError(err);
|
|
2664
|
+
}
|
|
2665
|
+
});
|
|
2666
|
+
cmd.command("dissolve <orgId>").description("Dissolve an Org (owner or created_by when unclaimed)").action(async (orgId) => {
|
|
2667
|
+
try {
|
|
2668
|
+
const org = await acnPost(`/orgs/${orgId}/dissolve`, {});
|
|
2669
|
+
output(org, formatOrg(org));
|
|
2670
|
+
} catch (err) {
|
|
2671
|
+
handleError(err);
|
|
2672
|
+
}
|
|
2673
|
+
});
|
|
2674
|
+
const work = cmd.command("work").description("Minimal Org work queue");
|
|
2675
|
+
work.command("list <orgId>").description("List work items").option("--open", "Only open (todo / in_progress)", false).action(async (orgId, opts) => {
|
|
2676
|
+
try {
|
|
2677
|
+
const q = opts.open ? "?open_only=true" : "";
|
|
2678
|
+
const res = await acnGet(
|
|
2679
|
+
`/orgs/${orgId}/work${q}`
|
|
2680
|
+
);
|
|
2681
|
+
const text = (res.work ?? []).map(
|
|
2682
|
+
(w) => ` ${w.work_id} [${w.status}] ${w.title}` + (w.assignee_agent_id ? ` \u2192 ${w.assignee_agent_id}` : "")
|
|
2683
|
+
).join("\n");
|
|
2684
|
+
output(res, text || " (no work)");
|
|
2685
|
+
} catch (err) {
|
|
2686
|
+
handleError(err);
|
|
2687
|
+
}
|
|
2688
|
+
});
|
|
2689
|
+
work.command("create <orgId>").description("Create a work item").requiredOption("--title <title>", "Work title").option("--assignee <agent_id>", "Assignee agent").action(async (orgId, opts) => {
|
|
2690
|
+
try {
|
|
2691
|
+
const body = { title: opts.title };
|
|
2692
|
+
if (opts.assignee) body.assignee_agent_id = opts.assignee;
|
|
2693
|
+
const w = await acnPost(`/orgs/${orgId}/work`, body);
|
|
2694
|
+
output(w, `Created ${w.work_id}: ${w.title}`);
|
|
2695
|
+
} catch (err) {
|
|
2696
|
+
handleError(err);
|
|
2697
|
+
}
|
|
2698
|
+
});
|
|
2699
|
+
work.command("update <orgId> <workId>").description("Update work status").requiredOption("--status <status>", "todo | in_progress | done | cancelled").option("--assignee <agent_id>", "Assignee agent").action(
|
|
2700
|
+
async (orgId, workId, opts) => {
|
|
2701
|
+
try {
|
|
2702
|
+
const body = { status: opts.status };
|
|
2703
|
+
if (opts.assignee) body.assignee_agent_id = opts.assignee;
|
|
2704
|
+
const w = await acnPatch(
|
|
2705
|
+
`/orgs/${orgId}/work/${workId}`,
|
|
2706
|
+
body
|
|
2707
|
+
);
|
|
2708
|
+
output(w, `Updated ${w.work_id} \u2192 ${w.status}`);
|
|
2709
|
+
} catch (err) {
|
|
2710
|
+
handleError(err);
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
);
|
|
2714
|
+
cmd.command("tick <orgId>").description("Thin Loop tick (lists open work, emits org.loop_tick)").action(async (orgId) => {
|
|
2715
|
+
try {
|
|
2716
|
+
const res = await acnPost(
|
|
2717
|
+
`/orgs/${orgId}/loop/tick`,
|
|
2718
|
+
{}
|
|
2719
|
+
);
|
|
2720
|
+
output(res, `Loop tick: ${res.open_count} open work item(s)`);
|
|
2721
|
+
} catch (err) {
|
|
2722
|
+
handleError(err);
|
|
2723
|
+
}
|
|
2724
|
+
});
|
|
2725
|
+
return cmd;
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2440
2728
|
// src/commands/follow.ts
|
|
2441
|
-
var
|
|
2442
|
-
function
|
|
2729
|
+
var import_commander15 = require("commander");
|
|
2730
|
+
function requireAgentId6() {
|
|
2443
2731
|
const config = loadConfig();
|
|
2444
2732
|
if (!config.api_key) {
|
|
2445
2733
|
console.error("No API key found. Run `acn join` first or `acn config set api-key <key>`.");
|
|
@@ -2461,9 +2749,9 @@ function formatAgent2(a, i) {
|
|
|
2461
2749
|
].join("\n");
|
|
2462
2750
|
}
|
|
2463
2751
|
function followCommand() {
|
|
2464
|
-
const cmd = new
|
|
2752
|
+
const cmd = new import_commander15.Command("follow").description("Follow/unfollow agents and inspect follow graph");
|
|
2465
2753
|
cmd.command("add <target_id>").description("Follow another agent").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (targetId, opts) => {
|
|
2466
|
-
const agentId = opts.agentId ??
|
|
2754
|
+
const agentId = opts.agentId ?? requireAgentId6();
|
|
2467
2755
|
try {
|
|
2468
2756
|
const res = await acnPost(
|
|
2469
2757
|
`/agents/${agentId}/follows/${targetId}`
|
|
@@ -2475,7 +2763,7 @@ function followCommand() {
|
|
|
2475
2763
|
}
|
|
2476
2764
|
});
|
|
2477
2765
|
cmd.command("remove <target_id>").description("Unfollow an agent").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (targetId, opts) => {
|
|
2478
|
-
const agentId = opts.agentId ??
|
|
2766
|
+
const agentId = opts.agentId ?? requireAgentId6();
|
|
2479
2767
|
try {
|
|
2480
2768
|
const res = await acnDelete(
|
|
2481
2769
|
`/agents/${agentId}/follows/${targetId}`
|
|
@@ -2487,7 +2775,7 @@ function followCommand() {
|
|
|
2487
2775
|
}
|
|
2488
2776
|
});
|
|
2489
2777
|
cmd.command("list").description("List agents you follow").option("--limit <n>", "Max results", parseInt).option("--offset <n>", "Pagination offset", parseInt).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
|
|
2490
|
-
const agentId = opts.agentId ??
|
|
2778
|
+
const agentId = opts.agentId ?? requireAgentId6();
|
|
2491
2779
|
try {
|
|
2492
2780
|
const params = {};
|
|
2493
2781
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -2512,7 +2800,7 @@ function followCommand() {
|
|
|
2512
2800
|
}
|
|
2513
2801
|
});
|
|
2514
2802
|
cmd.command("followers").description("List agents that follow you").option("--limit <n>", "Max results", parseInt).option("--offset <n>", "Pagination offset", parseInt).option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
|
|
2515
|
-
const agentId = opts.agentId ??
|
|
2803
|
+
const agentId = opts.agentId ?? requireAgentId6();
|
|
2516
2804
|
try {
|
|
2517
2805
|
const params = {};
|
|
2518
2806
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -2537,7 +2825,7 @@ function followCommand() {
|
|
|
2537
2825
|
}
|
|
2538
2826
|
});
|
|
2539
2827
|
cmd.command("check <target_id>").description("Check whether you are following a specific agent").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (targetId, opts) => {
|
|
2540
|
-
const agentId = opts.agentId ??
|
|
2828
|
+
const agentId = opts.agentId ?? requireAgentId6();
|
|
2541
2829
|
try {
|
|
2542
2830
|
const res = await acnGet(
|
|
2543
2831
|
`/agents/${agentId}/follows/${targetId}`
|
|
@@ -2552,8 +2840,8 @@ function followCommand() {
|
|
|
2552
2840
|
}
|
|
2553
2841
|
|
|
2554
2842
|
// src/commands/wallet.ts
|
|
2555
|
-
var
|
|
2556
|
-
function
|
|
2843
|
+
var import_commander16 = require("commander");
|
|
2844
|
+
function requireAgentId7() {
|
|
2557
2845
|
const config = loadConfig();
|
|
2558
2846
|
if (!config.api_key) {
|
|
2559
2847
|
console.error("No API key found. Run `acn join` first or `acn config set api-key <key>`.");
|
|
@@ -2569,7 +2857,7 @@ function parseCsv(value) {
|
|
|
2569
2857
|
return value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
2570
2858
|
}
|
|
2571
2859
|
async function showWalletInfo(opts) {
|
|
2572
|
-
const agentId = opts.agentId ??
|
|
2860
|
+
const agentId = opts.agentId ?? requireAgentId7();
|
|
2573
2861
|
try {
|
|
2574
2862
|
const res = await acnGet(`/agents/${agentId}/wallets`);
|
|
2575
2863
|
const lines = [`Agent : ${res.agent_id}`];
|
|
@@ -2595,7 +2883,7 @@ async function showWalletInfo(opts) {
|
|
|
2595
2883
|
}
|
|
2596
2884
|
}
|
|
2597
2885
|
function walletCommand() {
|
|
2598
|
-
const cmd = new
|
|
2886
|
+
const cmd = new import_commander16.Command("wallet").description("View and manage agent's wallet & payment info");
|
|
2599
2887
|
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);
|
|
2600
2888
|
cmd.command("set-capability").description("Declare which payment methods, networks, and wallets you accept").requiredOption(
|
|
2601
2889
|
"--methods <csv>",
|
|
@@ -2605,7 +2893,7 @@ function walletCommand() {
|
|
|
2605
2893
|
`Wallet addresses by network, JSON, e.g. '{"ethereum":"0x..."}'`
|
|
2606
2894
|
).option("--no-accepts", "Disable accepting payments (default: enabled)").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(
|
|
2607
2895
|
async (opts) => {
|
|
2608
|
-
const agentId = opts.agentId ??
|
|
2896
|
+
const agentId = opts.agentId ?? requireAgentId7();
|
|
2609
2897
|
let walletMap = {};
|
|
2610
2898
|
if (opts.wallets) {
|
|
2611
2899
|
try {
|
|
@@ -2640,7 +2928,7 @@ function walletCommand() {
|
|
|
2640
2928
|
);
|
|
2641
2929
|
cmd.command("set-pricing").description("Set OpenAI-style per-million-token pricing for your agent (USD)").requiredOption("--input <usd>", "USD per 1M input tokens").requiredOption("--output <usd>", "USD per 1M output tokens").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(
|
|
2642
2930
|
async (opts) => {
|
|
2643
|
-
const agentId = opts.agentId ??
|
|
2931
|
+
const agentId = opts.agentId ?? requireAgentId7();
|
|
2644
2932
|
const inputPrice = Number(opts.input);
|
|
2645
2933
|
const outputPrice = Number(opts.output);
|
|
2646
2934
|
if (!Number.isFinite(inputPrice) || inputPrice < 0) {
|
|
@@ -2668,7 +2956,7 @@ function walletCommand() {
|
|
|
2668
2956
|
}
|
|
2669
2957
|
);
|
|
2670
2958
|
cmd.command("tasks").description("List the payment tasks the current agent is involved in").option("--status <s>", "Filter by status (e.g. created, payment_confirmed, task_completed)").option("--limit <n>", "Max number of tasks to return (default 50)").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
|
|
2671
|
-
const agentId = opts.agentId ??
|
|
2959
|
+
const agentId = opts.agentId ?? requireAgentId7();
|
|
2672
2960
|
const params = {};
|
|
2673
2961
|
if (opts.status) params.status = opts.status;
|
|
2674
2962
|
if (opts.limit !== void 0) {
|
|
@@ -2708,7 +2996,7 @@ function walletCommand() {
|
|
|
2708
2996
|
}
|
|
2709
2997
|
});
|
|
2710
2998
|
cmd.command("stats").description("Show the current agent's payment statistics").option("-i, --agent-id <id>", "Agent ID (defaults to config)").action(async (opts) => {
|
|
2711
|
-
const agentId = opts.agentId ??
|
|
2999
|
+
const agentId = opts.agentId ?? requireAgentId7();
|
|
2712
3000
|
try {
|
|
2713
3001
|
const res = await acnGet(`/payments/stats/${agentId}`);
|
|
2714
3002
|
const lines = [`Stats for ${agentId}:`];
|
|
@@ -2774,8 +3062,8 @@ function walletCommand() {
|
|
|
2774
3062
|
}
|
|
2775
3063
|
|
|
2776
3064
|
// src/commands/pay.ts
|
|
2777
|
-
var
|
|
2778
|
-
function
|
|
3065
|
+
var import_commander17 = require("commander");
|
|
3066
|
+
function requireAgentId8() {
|
|
2779
3067
|
const config = loadConfig();
|
|
2780
3068
|
if (!config.api_key) {
|
|
2781
3069
|
console.error("No API key found. Run `acn join` first or `acn config set api-key <key>`.");
|
|
@@ -2788,11 +3076,11 @@ function requireAgentId7() {
|
|
|
2788
3076
|
return config.agent_id;
|
|
2789
3077
|
}
|
|
2790
3078
|
function payCommand() {
|
|
2791
|
-
const cmd = new
|
|
2792
|
-
const createCmd = new
|
|
3079
|
+
const cmd = new import_commander17.Command("pay").description("Manage payment tasks between agents");
|
|
3080
|
+
const createCmd = new import_commander17.Command("create").description("Create a payment task to another agent");
|
|
2793
3081
|
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(
|
|
2794
3082
|
async (opts) => {
|
|
2795
|
-
const fromAgent =
|
|
3083
|
+
const fromAgent = requireAgentId8();
|
|
2796
3084
|
const amount = Number(opts.amount);
|
|
2797
3085
|
if (!Number.isFinite(amount) || amount <= 0) {
|
|
2798
3086
|
console.error("--amount must be a positive number.");
|
|
@@ -2835,7 +3123,7 @@ function payCommand() {
|
|
|
2835
3123
|
}
|
|
2836
3124
|
}
|
|
2837
3125
|
);
|
|
2838
|
-
const confirmCmd = new
|
|
3126
|
+
const confirmCmd = new import_commander17.Command("confirm").description(
|
|
2839
3127
|
"Confirm an external payment has been made (buyer only)"
|
|
2840
3128
|
);
|
|
2841
3129
|
confirmCmd.requiredOption("--task-id <id>", "Payment task ID to confirm").requiredOption(
|
|
@@ -2857,11 +3145,11 @@ function payCommand() {
|
|
|
2857
3145
|
handleError(err);
|
|
2858
3146
|
}
|
|
2859
3147
|
});
|
|
2860
|
-
const statusCmd = new
|
|
3148
|
+
const statusCmd = new import_commander17.Command("status").description(
|
|
2861
3149
|
"Show payment tasks for the authenticated agent"
|
|
2862
3150
|
);
|
|
2863
3151
|
statusCmd.option("--status <s>", "Filter by status (e.g. created, payment_confirmed)").option("--limit <n>", "Max results (default 50)", "50").action(async (opts) => {
|
|
2864
|
-
const agentId =
|
|
3152
|
+
const agentId = requireAgentId8();
|
|
2865
3153
|
try {
|
|
2866
3154
|
const res = await acnGet(
|
|
2867
3155
|
`/payments/tasks/agent/${agentId}`,
|
|
@@ -2880,7 +3168,7 @@ function payCommand() {
|
|
|
2880
3168
|
|
|
2881
3169
|
// src/index.ts
|
|
2882
3170
|
var { version } = require_package();
|
|
2883
|
-
var program = new
|
|
3171
|
+
var program = new import_commander18.Command();
|
|
2884
3172
|
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) => {
|
|
2885
3173
|
const opts = thisCommand.opts();
|
|
2886
3174
|
if (opts.json) setJsonMode(true);
|
|
@@ -2895,8 +3183,10 @@ program.addCommand(messageCommand());
|
|
|
2895
3183
|
program.addCommand(notifyCommand());
|
|
2896
3184
|
program.addCommand(inboxCommand());
|
|
2897
3185
|
program.addCommand(listenCommand());
|
|
3186
|
+
program.addCommand(deliveryCommand());
|
|
2898
3187
|
program.addCommand(sessionCommand());
|
|
2899
3188
|
program.addCommand(subnetCommand());
|
|
3189
|
+
program.addCommand(orgCommand());
|
|
2900
3190
|
program.addCommand(followCommand());
|
|
2901
3191
|
program.addCommand(walletCommand());
|
|
2902
3192
|
program.addCommand(payCommand());
|