@acnlabs/acn-cli 1.0.11 → 1.0.12
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 +240 -23
- 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: "1.0.
|
|
34
|
+
version: "1.0.12",
|
|
35
35
|
description: "Official CLI for ACN (Agent Collaboration Network) \u2014 zero-integration agent access",
|
|
36
36
|
main: "dist/index.js",
|
|
37
37
|
bin: {
|
|
@@ -1761,6 +1761,144 @@ function canCompleteOfficialHop(opts) {
|
|
|
1761
1761
|
opts.inferencePath === "official" && opts.hopId?.trim() && asHostInferenceUrl(opts.hostInferenceUrl) && opts.jwt?.trim()
|
|
1762
1762
|
);
|
|
1763
1763
|
}
|
|
1764
|
+
function readBody(req) {
|
|
1765
|
+
return new Promise((resolve, reject) => {
|
|
1766
|
+
const chunks = [];
|
|
1767
|
+
req.on("data", (c) => chunks.push(Buffer.from(c)));
|
|
1768
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
1769
|
+
req.on("error", reject);
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
function send(res, status, body, contentType = "application/json") {
|
|
1773
|
+
res.writeHead(status, {
|
|
1774
|
+
"content-type": contentType,
|
|
1775
|
+
"content-length": String(body.length)
|
|
1776
|
+
});
|
|
1777
|
+
res.end(body);
|
|
1778
|
+
}
|
|
1779
|
+
function isSseContentType(contentType) {
|
|
1780
|
+
return contentType.toLowerCase().includes("text/event-stream");
|
|
1781
|
+
}
|
|
1782
|
+
async function pipeWebStream(body, res) {
|
|
1783
|
+
const reader = body.getReader();
|
|
1784
|
+
try {
|
|
1785
|
+
while (true) {
|
|
1786
|
+
const { done, value } = await reader.read();
|
|
1787
|
+
if (done) break;
|
|
1788
|
+
if (!value?.length) continue;
|
|
1789
|
+
const ok = res.write(Buffer.from(value));
|
|
1790
|
+
if (!ok) {
|
|
1791
|
+
await new Promise((resolve) => res.once("drain", resolve));
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
res.end();
|
|
1795
|
+
} catch (err) {
|
|
1796
|
+
if (!res.writableEnded) res.destroy(err instanceof Error ? err : void 0);
|
|
1797
|
+
} finally {
|
|
1798
|
+
try {
|
|
1799
|
+
reader.releaseLock();
|
|
1800
|
+
} catch {
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
async function handleDoorRequest(req, res, opts) {
|
|
1805
|
+
const path = (req.url ?? "").split("?")[0];
|
|
1806
|
+
if (req.method !== "POST" || path !== "/v1/chat/completions" && path !== "/chat/completions") {
|
|
1807
|
+
send(res, 404, Buffer.from('{"error":"not_found"}'));
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
let payload;
|
|
1811
|
+
try {
|
|
1812
|
+
const raw = await readBody(req);
|
|
1813
|
+
payload = JSON.parse(raw.length ? raw.toString("utf-8") : "{}");
|
|
1814
|
+
} catch {
|
|
1815
|
+
send(res, 400, Buffer.from('{"error":"invalid_json"}'));
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1819
|
+
send(res, 400, Buffer.from('{"error":"invalid_json"}'));
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
const body = { ...payload };
|
|
1823
|
+
delete body.agent_id;
|
|
1824
|
+
body.hop_id = opts.hopId;
|
|
1825
|
+
const headers = {
|
|
1826
|
+
authorization: `Bearer ${opts.jwt}`,
|
|
1827
|
+
"content-type": "application/json",
|
|
1828
|
+
"X-Hop-Id": opts.hopId
|
|
1829
|
+
};
|
|
1830
|
+
if (opts.agentId) headers["X-Agent-Id"] = opts.agentId;
|
|
1831
|
+
try {
|
|
1832
|
+
const upstream = await opts.fetchFn(opts.upstream, {
|
|
1833
|
+
method: "POST",
|
|
1834
|
+
headers,
|
|
1835
|
+
body: JSON.stringify(body)
|
|
1836
|
+
});
|
|
1837
|
+
const ct = upstream.headers.get("content-type") || "application/json";
|
|
1838
|
+
const sse = isSseContentType(ct) && upstream.body != null;
|
|
1839
|
+
const streamOk = body.stream === true && upstream.body != null && upstream.status < 400;
|
|
1840
|
+
if (sse || streamOk) {
|
|
1841
|
+
res.writeHead(upstream.status, {
|
|
1842
|
+
"content-type": isSseContentType(ct) ? ct : "text/event-stream",
|
|
1843
|
+
"cache-control": "no-cache",
|
|
1844
|
+
connection: "keep-alive",
|
|
1845
|
+
"x-accel-buffering": "no"
|
|
1846
|
+
});
|
|
1847
|
+
await pipeWebStream(upstream.body, res);
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
const out = Buffer.from(await upstream.arrayBuffer());
|
|
1851
|
+
send(res, upstream.status, out, ct);
|
|
1852
|
+
} catch (err) {
|
|
1853
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1854
|
+
send(
|
|
1855
|
+
res,
|
|
1856
|
+
502,
|
|
1857
|
+
Buffer.from(JSON.stringify({ error: `upstream_unreachable:${msg.slice(0, 120)}` }))
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
function closeServer(server) {
|
|
1862
|
+
return new Promise((resolve) => {
|
|
1863
|
+
server.closeAllConnections?.();
|
|
1864
|
+
server.close(() => resolve());
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
async function startOfficialHopDoor(opts) {
|
|
1868
|
+
const dest = asHostInferenceUrl(opts.hostInferenceUrl);
|
|
1869
|
+
const hopId = opts.hopId.trim();
|
|
1870
|
+
const jwt = opts.jwt.trim();
|
|
1871
|
+
if (!dest || !hopId || !jwt) return null;
|
|
1872
|
+
const fetchFn = opts.fetchFn ?? fetch;
|
|
1873
|
+
const upstream = `${dest}/chat/completions`;
|
|
1874
|
+
const server = import_node_http.default.createServer((req, res) => {
|
|
1875
|
+
void handleDoorRequest(req, res, {
|
|
1876
|
+
upstream,
|
|
1877
|
+
hopId,
|
|
1878
|
+
agentId: opts.agentId,
|
|
1879
|
+
jwt,
|
|
1880
|
+
fetchFn
|
|
1881
|
+
});
|
|
1882
|
+
});
|
|
1883
|
+
try {
|
|
1884
|
+
await new Promise((resolve, reject) => {
|
|
1885
|
+
server.once("error", reject);
|
|
1886
|
+
server.listen(0, "127.0.0.1", () => resolve());
|
|
1887
|
+
});
|
|
1888
|
+
} catch {
|
|
1889
|
+
return null;
|
|
1890
|
+
}
|
|
1891
|
+
const addr = server.address();
|
|
1892
|
+
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
1893
|
+
if (!port) {
|
|
1894
|
+
await closeServer(server);
|
|
1895
|
+
return null;
|
|
1896
|
+
}
|
|
1897
|
+
return {
|
|
1898
|
+
baseUrl: `http://127.0.0.1:${port}/v1`,
|
|
1899
|
+
close: () => closeServer(server)
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1764
1902
|
|
|
1765
1903
|
// src/commands/chat-writeback.ts
|
|
1766
1904
|
var DEFAULT_COMPLETE_TIMEOUT_MS = 12e4;
|
|
@@ -1976,7 +2114,7 @@ function completeInferenceEnv(event, opts, jwt, door) {
|
|
|
1976
2114
|
}
|
|
1977
2115
|
return { ...process.env, ...extra };
|
|
1978
2116
|
}
|
|
1979
|
-
function completeInferenceHeaders(event, opts) {
|
|
2117
|
+
function completeInferenceHeaders(event, opts, jwt, door) {
|
|
1980
2118
|
const headers = {
|
|
1981
2119
|
"content-type": "application/json"
|
|
1982
2120
|
};
|
|
@@ -1987,9 +2125,14 @@ function completeInferenceHeaders(event, opts) {
|
|
|
1987
2125
|
if (chat?.host_inference_url) {
|
|
1988
2126
|
headers["X-ACN-Host-Inference-Url"] = chat.host_inference_url;
|
|
1989
2127
|
}
|
|
2128
|
+
if (jwt) headers["X-ACN-Agent-Jwt"] = jwt;
|
|
2129
|
+
if (door?.baseUrl && jwt) {
|
|
2130
|
+
headers["X-ACN-OpenAI-Base-Url"] = door.baseUrl;
|
|
2131
|
+
headers["X-ACN-OpenAI-Api-Key"] = jwt;
|
|
2132
|
+
}
|
|
1990
2133
|
return headers;
|
|
1991
2134
|
}
|
|
1992
|
-
async function completeViaHttp(event, opts, deps) {
|
|
2135
|
+
async function completeViaHttp(event, opts, deps, jwt, door) {
|
|
1993
2136
|
const fetchFn = deps.fetchFn ?? fetch;
|
|
1994
2137
|
const timeoutMs = opts.completeTimeoutMs ?? DEFAULT_COMPLETE_TIMEOUT_MS;
|
|
1995
2138
|
const controller = new AbortController();
|
|
@@ -1997,7 +2140,7 @@ async function completeViaHttp(event, opts, deps) {
|
|
|
1997
2140
|
try {
|
|
1998
2141
|
const res = await fetchFn(opts.completeUrl, {
|
|
1999
2142
|
method: "POST",
|
|
2000
|
-
headers: completeInferenceHeaders(event, opts),
|
|
2143
|
+
headers: completeInferenceHeaders(event, opts, jwt, door),
|
|
2001
2144
|
body: JSON.stringify(event),
|
|
2002
2145
|
signal: controller.signal
|
|
2003
2146
|
});
|
|
@@ -2085,6 +2228,9 @@ function officialCompleteFailureContent(reason, model) {
|
|
|
2085
2228
|
if (mid && !officialV0SupportsModel(mid)) {
|
|
2086
2229
|
return `Official v0 is a single completion and cannot run thinking/reasoning models (${mid}). Switch to a chat model such as kimi-k2.5.`;
|
|
2087
2230
|
}
|
|
2231
|
+
if (reason === "official_host_unseen") {
|
|
2232
|
+
return "Official hop failed: Host did not see this hop. Complete must call OPENAI_BASE_URL (Host), not a BYO / TokenHub key.";
|
|
2233
|
+
}
|
|
2088
2234
|
return `Official hop failed (${reason}). Try kimi or another chat model.`;
|
|
2089
2235
|
}
|
|
2090
2236
|
async function completeOfficialViaHost(event, opts, deps, jwt) {
|
|
@@ -2153,6 +2299,73 @@ async function completeOfficialViaHost(event, opts, deps, jwt) {
|
|
|
2153
2299
|
clearTimeout(timer);
|
|
2154
2300
|
}
|
|
2155
2301
|
}
|
|
2302
|
+
async function loadOfficialHostMeter(event, opts, deps, jwt) {
|
|
2303
|
+
const chat = event.chat;
|
|
2304
|
+
const base = asHostInferenceUrl(chat?.host_inference_url);
|
|
2305
|
+
const hopId = chat?.hop_id?.trim();
|
|
2306
|
+
if (!base || !hopId) return { ok: false, reason: "official_complete_skipped" };
|
|
2307
|
+
const fetchFn = deps.fetchFn ?? fetch;
|
|
2308
|
+
try {
|
|
2309
|
+
const res = await fetchFn(`${base}/hops/${encodeURIComponent(hopId)}`, {
|
|
2310
|
+
headers: {
|
|
2311
|
+
authorization: `Bearer ${jwt}`,
|
|
2312
|
+
"X-Hop-Id": hopId,
|
|
2313
|
+
"X-Agent-Id": opts.agentId
|
|
2314
|
+
}
|
|
2315
|
+
});
|
|
2316
|
+
if (res.status < 200 || res.status >= 300) {
|
|
2317
|
+
return { ok: false, reason: `official_meter_http_${res.status}` };
|
|
2318
|
+
}
|
|
2319
|
+
let payload;
|
|
2320
|
+
try {
|
|
2321
|
+
payload = JSON.parse(await res.text());
|
|
2322
|
+
} catch {
|
|
2323
|
+
return { ok: false, reason: "official_meter_invalid_json" };
|
|
2324
|
+
}
|
|
2325
|
+
return { ok: true, seen: payload.seen === true };
|
|
2326
|
+
} catch (err) {
|
|
2327
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2328
|
+
return { ok: false, reason: `official_meter_unreachable:${msg.slice(0, 80)}` };
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
async function completeOfficialViaAgent(event, opts, deps, jwt) {
|
|
2332
|
+
const chat = event.chat;
|
|
2333
|
+
if (!chat) return { ok: false, reason: "no_chat_envelope" };
|
|
2334
|
+
if (!canCompleteOfficialHop({
|
|
2335
|
+
inferencePath: chat.inference_path,
|
|
2336
|
+
hopId: chat.hop_id,
|
|
2337
|
+
hostInferenceUrl: chat.host_inference_url,
|
|
2338
|
+
jwt
|
|
2339
|
+
})) {
|
|
2340
|
+
return { ok: false, reason: "official_complete_skipped" };
|
|
2341
|
+
}
|
|
2342
|
+
const model = chat.requested_model?.trim();
|
|
2343
|
+
if (model && !officialV0SupportsModel(model)) {
|
|
2344
|
+
return { ok: false, reason: "official_complete_unsupported_model" };
|
|
2345
|
+
}
|
|
2346
|
+
const logFn = deps.logFn ?? ((line) => console.error(line));
|
|
2347
|
+
logFn(
|
|
2348
|
+
`[acn listen] official_complete_via_agent chat_id=${chat.chat_id}` + (model ? ` model=${model}` : "")
|
|
2349
|
+
);
|
|
2350
|
+
const door = await startOfficialHopDoor({
|
|
2351
|
+
hostInferenceUrl: chat.host_inference_url,
|
|
2352
|
+
hopId: chat.hop_id,
|
|
2353
|
+
agentId: opts.agentId,
|
|
2354
|
+
jwt,
|
|
2355
|
+
fetchFn: deps.fetchFn
|
|
2356
|
+
});
|
|
2357
|
+
if (!door) return { ok: false, reason: "official_door_failed" };
|
|
2358
|
+
try {
|
|
2359
|
+
const completed = opts.completeUrl ? await completeViaHttp(event, opts, deps, jwt, door) : await spawnCompleteExec(event, opts, deps, jwt, door);
|
|
2360
|
+
if (!completed.ok) return completed;
|
|
2361
|
+
const meter = await loadOfficialHostMeter(event, opts, deps, jwt);
|
|
2362
|
+
if (!meter.ok) return meter;
|
|
2363
|
+
if (!meter.seen) return { ok: false, reason: "official_host_unseen" };
|
|
2364
|
+
return { ok: true, result: { content: completed.result.content } };
|
|
2365
|
+
} finally {
|
|
2366
|
+
await door.close();
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2156
2369
|
async function completeViaExec(event, opts, deps, jwt) {
|
|
2157
2370
|
return spawnCompleteExec(event, opts, deps, jwt);
|
|
2158
2371
|
}
|
|
@@ -2299,7 +2512,11 @@ async function handleChatWriteback(event, opts, deps = {}) {
|
|
|
2299
2512
|
}
|
|
2300
2513
|
let completed;
|
|
2301
2514
|
if (event.chat.inference_path === "official") {
|
|
2302
|
-
|
|
2515
|
+
if (opts.completeUrl || opts.completeExec) {
|
|
2516
|
+
completed = await completeOfficialViaAgent(event, opts, deps, jwt);
|
|
2517
|
+
} else {
|
|
2518
|
+
completed = await completeOfficialViaHost(event, opts, deps, jwt);
|
|
2519
|
+
}
|
|
2303
2520
|
} else if (opts.completeUrl) {
|
|
2304
2521
|
completed = await completeViaHttp(event, opts, deps);
|
|
2305
2522
|
} else if (opts.completeExec) {
|
|
@@ -2545,7 +2762,7 @@ function formatWakeFailed(event, reason) {
|
|
|
2545
2762
|
function formatDeduped(event) {
|
|
2546
2763
|
return `[acn listen] deduped key=${dedupeKey(event)}`;
|
|
2547
2764
|
}
|
|
2548
|
-
function dispatchLocalReceiver(correlationId, bodyText, opts, dedupeStore,
|
|
2765
|
+
function dispatchLocalReceiver(correlationId, bodyText, opts, dedupeStore, send2, deps = {}) {
|
|
2549
2766
|
const logFn = deps.logFn ?? ((line) => console.error(line));
|
|
2550
2767
|
const result = processIncomingRequest(
|
|
2551
2768
|
correlationId,
|
|
@@ -2554,7 +2771,7 @@ function dispatchLocalReceiver(correlationId, bodyText, opts, dedupeStore, send,
|
|
|
2554
2771
|
dedupeStore,
|
|
2555
2772
|
deps
|
|
2556
2773
|
);
|
|
2557
|
-
|
|
2774
|
+
send2(result.response);
|
|
2558
2775
|
if (result.dedupeHit && result.event) {
|
|
2559
2776
|
logFn(formatDeduped(result.event));
|
|
2560
2777
|
return;
|
|
@@ -2615,7 +2832,7 @@ function errorResponse(id, status, detail) {
|
|
|
2615
2832
|
body: JSON.stringify({ error: detail })
|
|
2616
2833
|
};
|
|
2617
2834
|
}
|
|
2618
|
-
async function dispatchA2aRequest(frame, opts,
|
|
2835
|
+
async function dispatchA2aRequest(frame, opts, send2, deps = {}) {
|
|
2619
2836
|
const bodyBuf = decodeBody(frame);
|
|
2620
2837
|
try {
|
|
2621
2838
|
if (opts.runtime) {
|
|
@@ -2625,7 +2842,7 @@ async function dispatchA2aRequest(frame, opts, send, deps = {}) {
|
|
|
2625
2842
|
bodyBuf.toString("utf-8"),
|
|
2626
2843
|
opts.runtime,
|
|
2627
2844
|
store,
|
|
2628
|
-
|
|
2845
|
+
send2,
|
|
2629
2846
|
{
|
|
2630
2847
|
fetchFn: deps.fetchFn,
|
|
2631
2848
|
spawnFn: deps.spawnFn,
|
|
@@ -2635,17 +2852,17 @@ async function dispatchA2aRequest(frame, opts, send, deps = {}) {
|
|
|
2635
2852
|
return;
|
|
2636
2853
|
}
|
|
2637
2854
|
if (opts.forward) {
|
|
2638
|
-
await forwardToHttp(frame, bodyBuf, opts.forward, deps.fetchFn ?? fetch,
|
|
2855
|
+
await forwardToHttp(frame, bodyBuf, opts.forward, deps.fetchFn ?? fetch, send2);
|
|
2639
2856
|
return;
|
|
2640
2857
|
}
|
|
2641
2858
|
if (opts.exec) {
|
|
2642
|
-
|
|
2859
|
+
send2(await runExec(frame, bodyBuf, opts.exec, deps.spawnFn ?? import_child_process3.spawn));
|
|
2643
2860
|
return;
|
|
2644
2861
|
}
|
|
2645
|
-
|
|
2862
|
+
send2(errorResponse(frame.id, 500, "no handler configured"));
|
|
2646
2863
|
} catch (err) {
|
|
2647
2864
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2648
|
-
|
|
2865
|
+
send2(errorResponse(frame.id, 502, `handler failed: ${msg}`));
|
|
2649
2866
|
}
|
|
2650
2867
|
}
|
|
2651
2868
|
function buildForwardHeaders(frame) {
|
|
@@ -2655,7 +2872,7 @@ function buildForwardHeaders(frame) {
|
|
|
2655
2872
|
}
|
|
2656
2873
|
return headers;
|
|
2657
2874
|
}
|
|
2658
|
-
async function forwardToHttp(frame, bodyBuf, base, fetchFn,
|
|
2875
|
+
async function forwardToHttp(frame, bodyBuf, base, fetchFn, send2) {
|
|
2659
2876
|
const suffix = frame.path && frame.path !== "/" ? "/" + frame.path.replace(/^\//, "") : "";
|
|
2660
2877
|
const targetUrl = base.replace(/\/$/, "") + suffix;
|
|
2661
2878
|
const method = (frame.method ?? "POST").toUpperCase();
|
|
@@ -2673,7 +2890,7 @@ async function forwardToHttp(frame, bodyBuf, base, fetchFn, send) {
|
|
|
2673
2890
|
const { done, value } = await reader.read();
|
|
2674
2891
|
if (done) break;
|
|
2675
2892
|
if (value && value.length > 0) {
|
|
2676
|
-
|
|
2893
|
+
send2({
|
|
2677
2894
|
type: "a2a_stream_chunk",
|
|
2678
2895
|
id: frame.id,
|
|
2679
2896
|
seq: seq++,
|
|
@@ -2682,17 +2899,17 @@ async function forwardToHttp(frame, bodyBuf, base, fetchFn, send) {
|
|
|
2682
2899
|
});
|
|
2683
2900
|
}
|
|
2684
2901
|
}
|
|
2685
|
-
|
|
2902
|
+
send2({ type: "a2a_stream_end", id: frame.id, status: res.status });
|
|
2686
2903
|
} catch (err) {
|
|
2687
2904
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2688
|
-
|
|
2905
|
+
send2({ type: "a2a_stream_end", id: frame.id, error: msg });
|
|
2689
2906
|
} finally {
|
|
2690
2907
|
reader.releaseLock();
|
|
2691
2908
|
}
|
|
2692
2909
|
return;
|
|
2693
2910
|
}
|
|
2694
2911
|
const respText = await res.text();
|
|
2695
|
-
|
|
2912
|
+
send2({
|
|
2696
2913
|
type: "a2a_response",
|
|
2697
2914
|
id: frame.id,
|
|
2698
2915
|
status: res.status,
|
|
@@ -2803,12 +3020,12 @@ function runListener(cfg) {
|
|
|
2803
3020
|
if (!frame || typeof frame !== "object") return;
|
|
2804
3021
|
const f = frame;
|
|
2805
3022
|
if (f.type === "a2a_request" && typeof f.id === "string") {
|
|
2806
|
-
const
|
|
3023
|
+
const send2 = (out) => {
|
|
2807
3024
|
if (ws.readyState === import_ws.default.OPEN) {
|
|
2808
3025
|
ws.send(JSON.stringify(out));
|
|
2809
3026
|
}
|
|
2810
3027
|
};
|
|
2811
|
-
void dispatchA2aRequest(f, cfg,
|
|
3028
|
+
void dispatchA2aRequest(f, cfg, send2, { dedupeStore });
|
|
2812
3029
|
}
|
|
2813
3030
|
});
|
|
2814
3031
|
ws.on("close", (code, reason) => {
|
|
@@ -2891,13 +3108,13 @@ function listenCommand() {
|
|
|
2891
3108
|
"Deprecated/ignored: writeback now mints ACN agent JWT from api-key"
|
|
2892
3109
|
).option(
|
|
2893
3110
|
"--chat-complete-url <url>",
|
|
2894
|
-
"
|
|
3111
|
+
"Complete URL (optional if official-only; mutually exclusive with --chat-complete-exec). Official hops open a Host door and require a Host invoice."
|
|
2895
3112
|
).option(
|
|
2896
3113
|
"--chat-complete-exec <cmd>",
|
|
2897
|
-
'
|
|
3114
|
+
'Complete exec (optional if official-only): stdin event \u2192 stdout {"content"}. Official hops with this flag open a Host door and require a Host invoice.'
|
|
2898
3115
|
).option(
|
|
2899
3116
|
"--chat-complete-timeout <ms>",
|
|
2900
|
-
`Complete timeout in ms (official default ${DEFAULT_OFFICIAL_COMPLETE_TIMEOUT_MS}; BYO default ${DEFAULT_COMPLETE_TIMEOUT_MS})`
|
|
3117
|
+
`Complete timeout in ms (CLI-owned official default ${DEFAULT_OFFICIAL_COMPLETE_TIMEOUT_MS}; agent/BYO default ${DEFAULT_COMPLETE_TIMEOUT_MS})`
|
|
2901
3118
|
).option("-i, --agent-id <id>", "Agent ID (defaults to config)").option(
|
|
2902
3119
|
"-m, --model <modelId>",
|
|
2903
3120
|
"Declare runtime model (Host Catalog id) on connect + every 15m via REST heartbeat (self-reported; env: ACN_PREFERRED_MODEL)"
|