@acnlabs/acn-cli 0.14.2 → 1.0.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.
- package/dist/index.js +54 -15
- 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.
|
|
34
|
+
version: "1.0.0",
|
|
35
35
|
description: "Official CLI for ACN (Agent Collaboration Network) \u2014 zero-integration agent access",
|
|
36
36
|
main: "dist/index.js",
|
|
37
37
|
bin: {
|
|
@@ -1560,7 +1560,7 @@ function validateChatWritebackOptions(opts) {
|
|
|
1560
1560
|
const hasUrl = Boolean(opts.chatCompleteUrl?.trim());
|
|
1561
1561
|
const hasExec = Boolean(opts.chatCompleteExec?.trim());
|
|
1562
1562
|
if (hasUrl === hasExec) {
|
|
1563
|
-
return '--chat-writeback requires exactly one of --chat-complete-url or --chat-complete-exec (host returns JSON {"content":"..."}).';
|
|
1563
|
+
return '--chat-writeback requires exactly one of --chat-complete-url or --chat-complete-exec (host returns JSON {"content":"..."} and optional usage).';
|
|
1564
1564
|
}
|
|
1565
1565
|
return null;
|
|
1566
1566
|
}
|
|
@@ -1594,6 +1594,39 @@ function extractContent(payload) {
|
|
|
1594
1594
|
}
|
|
1595
1595
|
return null;
|
|
1596
1596
|
}
|
|
1597
|
+
function asNonNegInt(v) {
|
|
1598
|
+
if (typeof v === "number" && Number.isFinite(v) && v >= 0) {
|
|
1599
|
+
return Math.floor(v);
|
|
1600
|
+
}
|
|
1601
|
+
if (typeof v === "string" && v.trim() !== "") {
|
|
1602
|
+
const n = Number(v);
|
|
1603
|
+
if (Number.isFinite(n) && n >= 0) return Math.floor(n);
|
|
1604
|
+
}
|
|
1605
|
+
return null;
|
|
1606
|
+
}
|
|
1607
|
+
function extractUsage(payload) {
|
|
1608
|
+
const rec = asRecord2(payload);
|
|
1609
|
+
if (!rec) return void 0;
|
|
1610
|
+
const usageRec = asRecord2(rec.usage) ?? rec;
|
|
1611
|
+
const input = asNonNegInt(usageRec.input_tokens) ?? asNonNegInt(usageRec.prompt_tokens);
|
|
1612
|
+
const output2 = asNonNegInt(usageRec.output_tokens) ?? asNonNegInt(usageRec.completion_tokens);
|
|
1613
|
+
if (input === null && output2 === null) return void 0;
|
|
1614
|
+
const out = {
|
|
1615
|
+
input_tokens: input ?? 0,
|
|
1616
|
+
output_tokens: output2 ?? 0
|
|
1617
|
+
};
|
|
1618
|
+
const ms = usageRec.meter_source;
|
|
1619
|
+
if (ms === "peer_self" || ms === "gateway" || ms === "runtime_attested" || ms === "protocol") {
|
|
1620
|
+
out.meter_source = ms;
|
|
1621
|
+
}
|
|
1622
|
+
return out;
|
|
1623
|
+
}
|
|
1624
|
+
function parseCompletePayload(payload) {
|
|
1625
|
+
const content = extractContent(payload);
|
|
1626
|
+
if (!content) return { ok: false, reason: "complete_missing_content" };
|
|
1627
|
+
const usage = extractUsage(payload);
|
|
1628
|
+
return { ok: true, result: usage ? { content, usage } : { content } };
|
|
1629
|
+
}
|
|
1597
1630
|
async function mintAgentJwt(opts, fetchFn = fetch) {
|
|
1598
1631
|
const now = Math.floor(Date.now() / 1e3);
|
|
1599
1632
|
if (cachedJwt && cachedJwt.agentId === opts.agentId && cachedJwt.expEpochSec > now + 60) {
|
|
@@ -1661,9 +1694,7 @@ async function completeViaHttp(event, opts, deps) {
|
|
|
1661
1694
|
} catch {
|
|
1662
1695
|
return { ok: false, reason: "complete_invalid_json" };
|
|
1663
1696
|
}
|
|
1664
|
-
|
|
1665
|
-
if (!content) return { ok: false, reason: "complete_missing_content" };
|
|
1666
|
-
return { ok: true, content };
|
|
1697
|
+
return parseCompletePayload(parsed);
|
|
1667
1698
|
} catch (err) {
|
|
1668
1699
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1669
1700
|
if (controller.signal.aborted || /abort|timeout/i.test(msg)) {
|
|
@@ -1711,12 +1742,7 @@ function completeViaExec(event, opts, deps) {
|
|
|
1711
1742
|
const text = Buffer.concat(stdout).toString("utf-8").trim();
|
|
1712
1743
|
try {
|
|
1713
1744
|
const parsed = JSON.parse(text);
|
|
1714
|
-
|
|
1715
|
-
if (!content) {
|
|
1716
|
-
finish({ ok: false, reason: "complete_missing_content" });
|
|
1717
|
-
return;
|
|
1718
|
-
}
|
|
1719
|
-
finish({ ok: true, content });
|
|
1745
|
+
finish(parseCompletePayload(parsed));
|
|
1720
1746
|
} catch {
|
|
1721
1747
|
finish({ ok: false, reason: "complete_invalid_json" });
|
|
1722
1748
|
}
|
|
@@ -1724,7 +1750,7 @@ function completeViaExec(event, opts, deps) {
|
|
|
1724
1750
|
child.stdin?.end(body);
|
|
1725
1751
|
});
|
|
1726
1752
|
}
|
|
1727
|
-
async function postWriteback(event,
|
|
1753
|
+
async function postWriteback(event, complete, opts, deps) {
|
|
1728
1754
|
const chat = event.chat;
|
|
1729
1755
|
if (!chat) return { ok: false, reason: "no_chat_envelope" };
|
|
1730
1756
|
if (!isAllowedChatReplyPath(chat.chat_id, chat.reply_path)) {
|
|
@@ -1747,6 +1773,18 @@ async function postWriteback(event, content, opts, deps) {
|
|
|
1747
1773
|
return { ok: false, reason: "reply_url_origin_mismatch" };
|
|
1748
1774
|
}
|
|
1749
1775
|
const timeoutMs = opts.writebackTimeoutMs ?? DEFAULT_WRITEBACK_TIMEOUT_MS;
|
|
1776
|
+
const replyToId = chat.gateway_message_id ?? event.message_id;
|
|
1777
|
+
const body = {
|
|
1778
|
+
content: complete.content,
|
|
1779
|
+
reply_to_id: replyToId
|
|
1780
|
+
};
|
|
1781
|
+
if (complete.usage) {
|
|
1782
|
+
body.usage = {
|
|
1783
|
+
input_tokens: complete.usage.input_tokens,
|
|
1784
|
+
output_tokens: complete.usage.output_tokens,
|
|
1785
|
+
meter_source: complete.usage.meter_source ?? "peer_self"
|
|
1786
|
+
};
|
|
1787
|
+
}
|
|
1750
1788
|
const postOnce = async (token) => {
|
|
1751
1789
|
const controller = new AbortController();
|
|
1752
1790
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -1757,7 +1795,7 @@ async function postWriteback(event, content, opts, deps) {
|
|
|
1757
1795
|
"content-type": "application/json",
|
|
1758
1796
|
Authorization: `Bearer ${token}`
|
|
1759
1797
|
},
|
|
1760
|
-
body: JSON.stringify(
|
|
1798
|
+
body: JSON.stringify(body),
|
|
1761
1799
|
signal: controller.signal
|
|
1762
1800
|
});
|
|
1763
1801
|
if (res.status === 200 || res.status === 201) {
|
|
@@ -1813,15 +1851,16 @@ async function handleChatWriteback(event, opts, deps = {}) {
|
|
|
1813
1851
|
);
|
|
1814
1852
|
return { ok: false, reason: completed.reason };
|
|
1815
1853
|
}
|
|
1816
|
-
const written = await postWriteback(event, completed.
|
|
1854
|
+
const written = await postWriteback(event, completed.result, opts, deps);
|
|
1817
1855
|
if (!written.ok) {
|
|
1818
1856
|
logFn(
|
|
1819
1857
|
`[acn listen] chat_writeback_failed chat_id=${event.chat.chat_id} message_id=${event.message_id} reason=${written.reason}`
|
|
1820
1858
|
);
|
|
1821
1859
|
return written;
|
|
1822
1860
|
}
|
|
1861
|
+
const usageNote = completed.result.usage ? ` usage_in=${completed.result.usage.input_tokens} usage_out=${completed.result.usage.output_tokens}` : "";
|
|
1823
1862
|
logFn(
|
|
1824
|
-
`[acn listen] chat_writeback_ok chat_id=${event.chat.chat_id} message_id=${event.message_id} http=${written.httpStatus}`
|
|
1863
|
+
`[acn listen] chat_writeback_ok chat_id=${event.chat.chat_id} message_id=${event.message_id} http=${written.httpStatus}${usageNote}`
|
|
1825
1864
|
);
|
|
1826
1865
|
return written;
|
|
1827
1866
|
}
|