@evident-ai/cli 3.1.1-dev.b860956 → 3.1.1-dev.bf45828
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/README.md +10 -4
- package/dist/index.js +156 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ Options:
|
|
|
85
85
|
|
|
86
86
|
- `-a, --agent [id]` — Runner ID to connect to. Optional when `EVIDENT_AGENT_KEY`
|
|
87
87
|
is set (the runner is then resolved automatically from the key).
|
|
88
|
+
- `--runner [id]` — Alias for `--agent` (preferred name; wins if both are given).
|
|
88
89
|
- `-p, --port <port>` — OpenCode port (default: `4096`).
|
|
89
90
|
- `--log-level <level>` — Log verbosity: `debug | info | warn | error` (default:
|
|
90
91
|
`info`). Env: `EVIDENT_LOG_LEVEL`.
|
|
@@ -105,15 +106,18 @@ targets the **production** Evident platform by default.
|
|
|
105
106
|
|
|
106
107
|
## Environment variables
|
|
107
108
|
|
|
108
|
-
- `
|
|
109
|
-
that runner and resolves the runner ID automatically, so `--agent`
|
|
110
|
-
required. Ideal for CI/CD.
|
|
109
|
+
- `EVIDENT_RUNNER_KEY` — A runner key. When set, `evident run` authenticates as
|
|
110
|
+
that runner and resolves the runner ID automatically, so `--runner`/`--agent`
|
|
111
|
+
is not required. Ideal for CI/CD. Preferred name; wins over `EVIDENT_AGENT_KEY`
|
|
112
|
+
if both are set.
|
|
113
|
+
- `EVIDENT_AGENT_KEY` — Alias for `EVIDENT_RUNNER_KEY` (still fully supported).
|
|
111
114
|
- `EVIDENT_TOKEN` — A user token used for authentication (alternative to a
|
|
112
115
|
keychain login from `evident login`).
|
|
113
116
|
- `EVIDENT_API_URL` — Override the API base URL (equivalent to `--endpoint`).
|
|
114
117
|
- `EVIDENT_TUNNEL_URL` — Override the tunnel relay URL (equivalent to `--tunnel`).
|
|
115
118
|
|
|
116
|
-
Authentication precedence for `run`: `EVIDENT_AGENT_KEY`
|
|
119
|
+
Authentication precedence for `run`: `EVIDENT_RUNNER_KEY`/`EVIDENT_AGENT_KEY`
|
|
120
|
+
(tied; `EVIDENT_RUNNER_KEY` wins if both are set) → `EVIDENT_TOKEN` →
|
|
117
121
|
credentials stored by `evident login`. For the URL flags, an explicit
|
|
118
122
|
`--endpoint` / `--tunnel` flag wins over the matching environment variable, which
|
|
119
123
|
in turn overrides the production default.
|
|
@@ -150,6 +154,8 @@ For CI or unattended use, set `EVIDENT_AGENT_KEY` and omit `--agent`:
|
|
|
150
154
|
EVIDENT_AGENT_KEY=<agent-key> evident run --idle-timeout 30
|
|
151
155
|
```
|
|
152
156
|
|
|
157
|
+
(`EVIDENT_RUNNER_KEY` is equivalent and the preferred name — use whichever you like.)
|
|
158
|
+
|
|
153
159
|
## How it works
|
|
154
160
|
|
|
155
161
|
```
|
package/dist/index.js
CHANGED
|
@@ -645,14 +645,27 @@ var EventTypes = {
|
|
|
645
645
|
// CLI lifecycle
|
|
646
646
|
CLI_STARTED: "cli.started",
|
|
647
647
|
CLI_COMMAND: "cli.command",
|
|
648
|
-
CLI_ERROR: "cli.error"
|
|
648
|
+
CLI_ERROR: "cli.error",
|
|
649
|
+
// Deprecation telemetry (#412) — usage of the old `--agent`/`EVIDENT_AGENT_KEY`
|
|
650
|
+
// names instead of the preferred `--runner`/`EVIDENT_RUNNER_KEY` (#409).
|
|
651
|
+
DEPRECATED_AGENT_FLAG_USED: "cli.deprecated_agent_flag_used",
|
|
652
|
+
DEPRECATED_AGENT_KEY_ENV_USED: "cli.deprecated_agent_key_env_used"
|
|
649
653
|
};
|
|
650
654
|
|
|
651
655
|
// src/lib/auth.ts
|
|
652
656
|
async function getAuthCredentials() {
|
|
657
|
+
const runnerKey = process.env.EVIDENT_RUNNER_KEY;
|
|
653
658
|
const agentKey = process.env.EVIDENT_AGENT_KEY;
|
|
659
|
+
if (runnerKey) {
|
|
660
|
+
return {
|
|
661
|
+
token: runnerKey,
|
|
662
|
+
authType: "agent_key",
|
|
663
|
+
keySource: "runner_key",
|
|
664
|
+
notice: agentKey ? "Both EVIDENT_RUNNER_KEY and EVIDENT_AGENT_KEY are set; using EVIDENT_RUNNER_KEY." : void 0
|
|
665
|
+
};
|
|
666
|
+
}
|
|
654
667
|
if (agentKey) {
|
|
655
|
-
return { token: agentKey, authType: "agent_key" };
|
|
668
|
+
return { token: agentKey, authType: "agent_key", keySource: "agent_key" };
|
|
656
669
|
}
|
|
657
670
|
const userToken = process.env.EVIDENT_TOKEN;
|
|
658
671
|
if (userToken) {
|
|
@@ -1370,6 +1383,72 @@ function findLastAssistantReplyFor(messages, userMessageId) {
|
|
|
1370
1383
|
}
|
|
1371
1384
|
return lastOk ?? last;
|
|
1372
1385
|
}
|
|
1386
|
+
function messageUsage(messages, userMessageId) {
|
|
1387
|
+
if (!messages || messages.length === 0) return null;
|
|
1388
|
+
const byParentAll = messages.filter(
|
|
1389
|
+
(m) => roleOf(m) === "assistant" && parentIdOf(m) === userMessageId
|
|
1390
|
+
);
|
|
1391
|
+
const byParentNonErrored = byParentAll.filter((m) => errorOf(m) == null);
|
|
1392
|
+
const byParent = byParentNonErrored.length > 0 ? byParentNonErrored : byParentAll;
|
|
1393
|
+
let correlated;
|
|
1394
|
+
if (byParent.length > 0) {
|
|
1395
|
+
correlated = byParent;
|
|
1396
|
+
} else {
|
|
1397
|
+
const reply = findAssistantReplyAfter(messages, userMessageId);
|
|
1398
|
+
correlated = reply ? [reply] : [];
|
|
1399
|
+
}
|
|
1400
|
+
if (correlated.length === 0) return null;
|
|
1401
|
+
let sawAnyUsage = false;
|
|
1402
|
+
let inputSum = 0;
|
|
1403
|
+
let outputSum = 0;
|
|
1404
|
+
let reasoningSum = 0;
|
|
1405
|
+
let cacheReadSum = 0;
|
|
1406
|
+
let cacheWriteSum = 0;
|
|
1407
|
+
let costSum = 0;
|
|
1408
|
+
let sawCost = false;
|
|
1409
|
+
let modelId = null;
|
|
1410
|
+
let providerId = null;
|
|
1411
|
+
for (const m of correlated) {
|
|
1412
|
+
const info = m.info;
|
|
1413
|
+
if (!info) continue;
|
|
1414
|
+
const tokens = info.tokens;
|
|
1415
|
+
if (tokens) {
|
|
1416
|
+
sawAnyUsage = true;
|
|
1417
|
+
inputSum += tokens.input ?? 0;
|
|
1418
|
+
outputSum += tokens.output ?? 0;
|
|
1419
|
+
reasoningSum += tokens.reasoning ?? 0;
|
|
1420
|
+
cacheReadSum += tokens.cache?.read ?? 0;
|
|
1421
|
+
cacheWriteSum += tokens.cache?.write ?? 0;
|
|
1422
|
+
}
|
|
1423
|
+
if (typeof info.cost === "number") {
|
|
1424
|
+
sawAnyUsage = true;
|
|
1425
|
+
sawCost = true;
|
|
1426
|
+
costSum += info.cost;
|
|
1427
|
+
}
|
|
1428
|
+
if (typeof info.modelID === "string") {
|
|
1429
|
+
sawAnyUsage = true;
|
|
1430
|
+
modelId = info.modelID;
|
|
1431
|
+
}
|
|
1432
|
+
if (typeof info.providerID === "string") {
|
|
1433
|
+
sawAnyUsage = true;
|
|
1434
|
+
providerId = info.providerID;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
if (!sawAnyUsage) return null;
|
|
1438
|
+
return {
|
|
1439
|
+
usage_provider_id: providerId,
|
|
1440
|
+
usage_model_id: modelId,
|
|
1441
|
+
usage_tokens_input: inputSum,
|
|
1442
|
+
usage_tokens_output: outputSum,
|
|
1443
|
+
usage_tokens_reasoning: reasoningSum,
|
|
1444
|
+
usage_tokens_cache_read: cacheReadSum,
|
|
1445
|
+
usage_tokens_cache_write: cacheWriteSum,
|
|
1446
|
+
// NULL means "OpenCode never reported a cost" (never inferred from
|
|
1447
|
+
// tokens) — distinct from a genuine 0-cost turn, which would set
|
|
1448
|
+
// `sawCost` true with `costSum === 0`.
|
|
1449
|
+
usage_cost_usd: sawCost ? costSum : null
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1373
1452
|
function messageRunState(messages, userMessageId) {
|
|
1374
1453
|
if (!messages || messages.length === 0) return "unknown";
|
|
1375
1454
|
const hasUser = messages.some((m) => idOf(m) === userMessageId);
|
|
@@ -1716,7 +1795,6 @@ function connectTunnel(options) {
|
|
|
1716
1795
|
onConnected,
|
|
1717
1796
|
onDisconnected,
|
|
1718
1797
|
onError,
|
|
1719
|
-
onRequest,
|
|
1720
1798
|
onResponse,
|
|
1721
1799
|
onInfo,
|
|
1722
1800
|
onDrainPing
|
|
@@ -1729,18 +1807,8 @@ function connectTunnel(options) {
|
|
|
1729
1807
|
Authorization: authHeader
|
|
1730
1808
|
}
|
|
1731
1809
|
});
|
|
1732
|
-
const streamStartTimes = /* @__PURE__ */ new Map();
|
|
1733
1810
|
const forwarder = new StreamForwarder(ws, port, {
|
|
1734
|
-
|
|
1735
|
-
if (path === TUNNEL_DRAIN_PING_PATH) return;
|
|
1736
|
-
streamStartTimes.set(sid, Date.now());
|
|
1737
|
-
onRequest?.(method, path, sid);
|
|
1738
|
-
},
|
|
1739
|
-
onHead: (sid, status) => {
|
|
1740
|
-
const startedAt = streamStartTimes.get(sid);
|
|
1741
|
-
streamStartTimes.delete(sid);
|
|
1742
|
-
onResponse?.(status, startedAt ? Date.now() - startedAt : 0, sid);
|
|
1743
|
-
},
|
|
1811
|
+
onHead: () => onResponse?.(),
|
|
1744
1812
|
onDrainPing: () => onDrainPing?.()
|
|
1745
1813
|
});
|
|
1746
1814
|
const connectionTimeout = setTimeout(() => {
|
|
@@ -1816,7 +1884,6 @@ function connectTunnel(options) {
|
|
|
1816
1884
|
ws.on("close", (code, reason) => {
|
|
1817
1885
|
const reasonStr = reason.toString() || upgradeRejection || (code === 1006 ? "abnormal closure" : "No reason provided");
|
|
1818
1886
|
forwarder.abortAll();
|
|
1819
|
-
streamStartTimes.clear();
|
|
1820
1887
|
onDisconnected?.(code, reasonStr);
|
|
1821
1888
|
});
|
|
1822
1889
|
});
|
|
@@ -2445,7 +2512,7 @@ var ChannelDriver = class {
|
|
|
2445
2512
|
}
|
|
2446
2513
|
/**
|
|
2447
2514
|
* Fetch ONE inbound image's bytes through Evident's WI-6 endpoint
|
|
2448
|
-
* (`GET {apiUrl}/
|
|
2515
|
+
* (`GET {apiUrl}/runners/{agentId}/attachments/{messageId}/{index}`) using the
|
|
2449
2516
|
* existing authenticated fetch, and base64-encode into a
|
|
2450
2517
|
* `data:<mime>;base64,<…>` URL for the opencode `file` part's `url`.
|
|
2451
2518
|
*
|
|
@@ -2458,7 +2525,7 @@ var ChannelDriver = class {
|
|
|
2458
2525
|
async fetchAttachmentDataUrl(messageId, index, mime) {
|
|
2459
2526
|
try {
|
|
2460
2527
|
const res = await this.fetchImpl(
|
|
2461
|
-
`${this.apiUrl}/
|
|
2528
|
+
`${this.apiUrl}/runners/${this.agentId}/attachments/${messageId}/${index}`,
|
|
2462
2529
|
{ headers: { Authorization: this.getAuthHeader() } }
|
|
2463
2530
|
);
|
|
2464
2531
|
if (!res.ok) {
|
|
@@ -2790,13 +2857,15 @@ var ChannelDriver = class {
|
|
|
2790
2857
|
message_id: inFlight.evidentMessageId
|
|
2791
2858
|
});
|
|
2792
2859
|
const title = await this.resolveSessionTitle(sessionId, watcher.conv.id);
|
|
2860
|
+
const usage = messageUsage(messages, inFlight.opencodeMessageId);
|
|
2793
2861
|
try {
|
|
2794
2862
|
await this.markDone(
|
|
2795
2863
|
conv.id,
|
|
2796
2864
|
inFlight.evidentMessageId,
|
|
2797
2865
|
sessionId,
|
|
2798
2866
|
inFlight.opencodeMessageId,
|
|
2799
|
-
title
|
|
2867
|
+
title,
|
|
2868
|
+
usage
|
|
2800
2869
|
);
|
|
2801
2870
|
} catch (err) {
|
|
2802
2871
|
if (err instanceof ChannelAuthError) throw err;
|
|
@@ -2843,8 +2912,9 @@ var ChannelDriver = class {
|
|
|
2843
2912
|
conversation_id: conv.id,
|
|
2844
2913
|
message_id: inFlight.evidentMessageId
|
|
2845
2914
|
});
|
|
2915
|
+
const usage = messageUsage(messages, inFlight.opencodeMessageId);
|
|
2846
2916
|
try {
|
|
2847
|
-
await this.markFailed(conv.id, inFlight.evidentMessageId, sessionId, error2);
|
|
2917
|
+
await this.markFailed(conv.id, inFlight.evidentMessageId, sessionId, error2, usage);
|
|
2848
2918
|
} catch (err) {
|
|
2849
2919
|
if (err instanceof ChannelAuthError) throw err;
|
|
2850
2920
|
if (err instanceof ChannelTerminalError) {
|
|
@@ -3081,7 +3151,8 @@ var ChannelDriver = class {
|
|
|
3081
3151
|
});
|
|
3082
3152
|
try {
|
|
3083
3153
|
const title = await this.resolveSessionTitle(sessionId, row.conversation_id);
|
|
3084
|
-
|
|
3154
|
+
const usage = messageUsage(messages, ocId ?? "");
|
|
3155
|
+
await this.markDone(row.conversation_id, row.id, sessionId, ocId, title, usage);
|
|
3085
3156
|
} catch (err) {
|
|
3086
3157
|
if (err instanceof ChannelAuthError) throw err;
|
|
3087
3158
|
if (err instanceof ChannelTerminalError) {
|
|
@@ -3109,6 +3180,7 @@ var ChannelDriver = class {
|
|
|
3109
3180
|
}
|
|
3110
3181
|
if (state === "failed") {
|
|
3111
3182
|
const error2 = messageError(messages, ocId ?? "") ?? void 0;
|
|
3183
|
+
const usage = messageUsage(messages, ocId ?? "");
|
|
3112
3184
|
this.log({
|
|
3113
3185
|
level: "error",
|
|
3114
3186
|
message: `Re-adopt: message ${row.id.slice(0, 8)} errored while unwatched \u2014 marking failed: ${error2 ?? "(no error text)"}`,
|
|
@@ -3116,7 +3188,7 @@ var ChannelDriver = class {
|
|
|
3116
3188
|
message_id: row.id
|
|
3117
3189
|
});
|
|
3118
3190
|
try {
|
|
3119
|
-
await this.markFailed(row.conversation_id, row.id, sessionId, error2);
|
|
3191
|
+
await this.markFailed(row.conversation_id, row.id, sessionId, error2, usage);
|
|
3120
3192
|
} catch (err) {
|
|
3121
3193
|
if (err instanceof ChannelAuthError) throw err;
|
|
3122
3194
|
if (err instanceof ChannelTerminalError) {
|
|
@@ -3719,7 +3791,7 @@ var ChannelDriver = class {
|
|
|
3719
3791
|
// Evident API calls (combinedAuth thread routes)
|
|
3720
3792
|
async getPendingConversations() {
|
|
3721
3793
|
const res = await this.fetchImpl(
|
|
3722
|
-
`${this.apiUrl}/
|
|
3794
|
+
`${this.apiUrl}/runners/${this.agentId}/conversations/pending`,
|
|
3723
3795
|
{
|
|
3724
3796
|
headers: { Authorization: this.getAuthHeader() }
|
|
3725
3797
|
}
|
|
@@ -3737,7 +3809,7 @@ var ChannelDriver = class {
|
|
|
3737
3809
|
}
|
|
3738
3810
|
async getPendingMessages(conversationId) {
|
|
3739
3811
|
const res = await this.fetchImpl(
|
|
3740
|
-
`${this.apiUrl}/
|
|
3812
|
+
`${this.apiUrl}/runners/${this.agentId}/threads/${conversationId}/messages?status=pending`,
|
|
3741
3813
|
{ headers: { Authorization: this.getAuthHeader() } }
|
|
3742
3814
|
);
|
|
3743
3815
|
this.assertAuth(res, "fetching pending messages");
|
|
@@ -3761,7 +3833,7 @@ var ChannelDriver = class {
|
|
|
3761
3833
|
*/
|
|
3762
3834
|
async getProcessingMessages() {
|
|
3763
3835
|
const res = await this.fetchImpl(
|
|
3764
|
-
`${this.apiUrl}/
|
|
3836
|
+
`${this.apiUrl}/runners/${this.agentId}/conversations/processing`,
|
|
3765
3837
|
{ headers: { Authorization: this.getAuthHeader() } }
|
|
3766
3838
|
);
|
|
3767
3839
|
this.assertAuth(res, "fetching processing messages");
|
|
@@ -3798,7 +3870,7 @@ var ChannelDriver = class {
|
|
|
3798
3870
|
*/
|
|
3799
3871
|
async markProcessing(conversationId, messageId, sessionId, opencodeMessageId, title) {
|
|
3800
3872
|
const res = await this.fetchImpl(
|
|
3801
|
-
`${this.apiUrl}/
|
|
3873
|
+
`${this.apiUrl}/runners/${this.agentId}/threads/${conversationId}/messages/${messageId}`,
|
|
3802
3874
|
{
|
|
3803
3875
|
method: "PATCH",
|
|
3804
3876
|
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
@@ -3845,9 +3917,9 @@ var ChannelDriver = class {
|
|
|
3845
3917
|
* watcher retries next tick within the
|
|
3846
3918
|
* deadline, Finding 4).
|
|
3847
3919
|
*/
|
|
3848
|
-
async markDone(conversationId, messageId, sessionId, opencodeMessageId, title) {
|
|
3920
|
+
async markDone(conversationId, messageId, sessionId, opencodeMessageId, title, usage) {
|
|
3849
3921
|
const res = await this.fetchImpl(
|
|
3850
|
-
`${this.apiUrl}/
|
|
3922
|
+
`${this.apiUrl}/runners/${this.agentId}/threads/${conversationId}/messages/${messageId}`,
|
|
3851
3923
|
{
|
|
3852
3924
|
method: "PATCH",
|
|
3853
3925
|
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
@@ -3855,7 +3927,8 @@ var ChannelDriver = class {
|
|
|
3855
3927
|
status: "done",
|
|
3856
3928
|
opencode_session_id: sessionId,
|
|
3857
3929
|
...opencodeMessageId ? { opencode_message_id: opencodeMessageId } : {},
|
|
3858
|
-
...title ? { title } : {}
|
|
3930
|
+
...title ? { title } : {},
|
|
3931
|
+
...usage ? usage : {}
|
|
3859
3932
|
})
|
|
3860
3933
|
}
|
|
3861
3934
|
);
|
|
@@ -3873,14 +3946,15 @@ var ChannelDriver = class {
|
|
|
3873
3946
|
* OpenCode turn sends `{status:'failed', opencode_session_id, error}` so the
|
|
3874
3947
|
* failure reason reaches the channel.
|
|
3875
3948
|
*/
|
|
3876
|
-
async markFailed(conversationId, messageId, sessionId, error2) {
|
|
3949
|
+
async markFailed(conversationId, messageId, sessionId, error2, usage) {
|
|
3877
3950
|
const body = { status: "failed" };
|
|
3878
3951
|
if (sessionId !== void 0) body.opencode_session_id = sessionId;
|
|
3879
3952
|
if (error2 !== void 0) body.error = error2;
|
|
3953
|
+
if (usage) Object.assign(body, usage);
|
|
3880
3954
|
await this.callWithRetry(
|
|
3881
3955
|
"marking message as failed",
|
|
3882
3956
|
() => this.fetchImpl(
|
|
3883
|
-
`${this.apiUrl}/
|
|
3957
|
+
`${this.apiUrl}/runners/${this.agentId}/threads/${conversationId}/messages/${messageId}`,
|
|
3884
3958
|
{
|
|
3885
3959
|
method: "PATCH",
|
|
3886
3960
|
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
@@ -3907,7 +3981,7 @@ var ChannelDriver = class {
|
|
|
3907
3981
|
async postSignal(conversationId, messageId, signal, extra) {
|
|
3908
3982
|
try {
|
|
3909
3983
|
const res = await this.fetchImpl(
|
|
3910
|
-
`${this.apiUrl}/
|
|
3984
|
+
`${this.apiUrl}/runners/${this.agentId}/threads/${conversationId}/messages/${messageId}/signal`,
|
|
3911
3985
|
{
|
|
3912
3986
|
method: "POST",
|
|
3913
3987
|
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
@@ -3936,7 +4010,7 @@ var ChannelDriver = class {
|
|
|
3936
4010
|
}
|
|
3937
4011
|
async persistSession(conversationId, sessionId) {
|
|
3938
4012
|
const res = await this.fetchImpl(
|
|
3939
|
-
`${this.apiUrl}/
|
|
4013
|
+
`${this.apiUrl}/runners/${this.agentId}/threads/${conversationId}`,
|
|
3940
4014
|
{
|
|
3941
4015
|
method: "PATCH",
|
|
3942
4016
|
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
@@ -3962,7 +4036,7 @@ var ChannelDriver = class {
|
|
|
3962
4036
|
await this.callWithRetry(
|
|
3963
4037
|
"reporting interactive event",
|
|
3964
4038
|
() => this.fetchImpl(
|
|
3965
|
-
`${this.apiUrl}/
|
|
4039
|
+
`${this.apiUrl}/runners/${this.agentId}/threads/${conversationId}/interactive-event`,
|
|
3966
4040
|
{
|
|
3967
4041
|
method: "POST",
|
|
3968
4042
|
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
@@ -4205,7 +4279,7 @@ async function resolveAgentIdFromKey(authHeader) {
|
|
|
4205
4279
|
async function notifyAgentDisconnected(agentId, authHeader) {
|
|
4206
4280
|
const apiUrl = getApiUrlConfig();
|
|
4207
4281
|
try {
|
|
4208
|
-
const response = await fetch(`${apiUrl}/
|
|
4282
|
+
const response = await fetch(`${apiUrl}/runners/${agentId}/disconnect`, {
|
|
4209
4283
|
method: "POST",
|
|
4210
4284
|
headers: { Authorization: authHeader }
|
|
4211
4285
|
});
|
|
@@ -4224,7 +4298,7 @@ async function notifyAgentDisconnected(agentId, authHeader) {
|
|
|
4224
4298
|
async function getAgentInfo(agentId, authHeader) {
|
|
4225
4299
|
const apiUrl = getApiUrlConfig();
|
|
4226
4300
|
try {
|
|
4227
|
-
const response = await fetch(`${apiUrl}/
|
|
4301
|
+
const response = await fetch(`${apiUrl}/runners/${agentId}`, {
|
|
4228
4302
|
headers: { Authorization: authHeader }
|
|
4229
4303
|
});
|
|
4230
4304
|
if (response.status === 401) {
|
|
@@ -4611,7 +4685,7 @@ async function run(options) {
|
|
|
4611
4685
|
return;
|
|
4612
4686
|
}
|
|
4613
4687
|
const state = {
|
|
4614
|
-
agentId: options.agent || "",
|
|
4688
|
+
agentId: options.runner || options.agent || "",
|
|
4615
4689
|
agentName: null,
|
|
4616
4690
|
port: options.port ?? 4096,
|
|
4617
4691
|
conversationFilter: options.conversation ?? null,
|
|
@@ -4633,6 +4707,19 @@ async function run(options) {
|
|
|
4633
4707
|
sessionCleanupTimers: [],
|
|
4634
4708
|
authHeader: ""
|
|
4635
4709
|
};
|
|
4710
|
+
if (!options.runner && options.agent) {
|
|
4711
|
+
telemetry.info(
|
|
4712
|
+
EventTypes.DEPRECATED_AGENT_FLAG_USED,
|
|
4713
|
+
"Deprecated --agent flag used instead of --runner",
|
|
4714
|
+
{ command: "run" },
|
|
4715
|
+
state.agentId
|
|
4716
|
+
);
|
|
4717
|
+
const agentFlagNotice = "--agent is deprecated, use --runner instead; will be removed in a future release.";
|
|
4718
|
+
log2(state, agentFlagNotice, "warn");
|
|
4719
|
+
if (state.interactive && !state.json) {
|
|
4720
|
+
logActivity(state, { type: "info", level: "warn", message: agentFlagNotice });
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4636
4723
|
if (state.idleTimeout === null && (process.env.GITHUB_ACTIONS || process.env.CI)) {
|
|
4637
4724
|
log2(
|
|
4638
4725
|
state,
|
|
@@ -4661,7 +4748,9 @@ async function run(options) {
|
|
|
4661
4748
|
if (!interactive) {
|
|
4662
4749
|
printError("Authentication required");
|
|
4663
4750
|
blank();
|
|
4664
|
-
console.log(
|
|
4751
|
+
console.log(
|
|
4752
|
+
chalk6.dim("Set EVIDENT_RUNNER_KEY (or EVIDENT_AGENT_KEY) environment variable for CI")
|
|
4753
|
+
);
|
|
4665
4754
|
console.log(chalk6.dim("Or run `evident login` for interactive authentication"));
|
|
4666
4755
|
blank();
|
|
4667
4756
|
process.exit(1);
|
|
@@ -4675,6 +4764,25 @@ async function run(options) {
|
|
|
4675
4764
|
);
|
|
4676
4765
|
}
|
|
4677
4766
|
state.authHeader = getAuthHeader(credentials2);
|
|
4767
|
+
if (credentials2.notice) {
|
|
4768
|
+
log2(state, credentials2.notice, "warn");
|
|
4769
|
+
if (state.interactive && !state.json) {
|
|
4770
|
+
logActivity(state, { type: "info", level: "warn", message: credentials2.notice });
|
|
4771
|
+
}
|
|
4772
|
+
}
|
|
4773
|
+
if (credentials2.keySource === "agent_key") {
|
|
4774
|
+
telemetry.info(
|
|
4775
|
+
EventTypes.DEPRECATED_AGENT_KEY_ENV_USED,
|
|
4776
|
+
"Deprecated EVIDENT_AGENT_KEY env var used instead of EVIDENT_RUNNER_KEY",
|
|
4777
|
+
{ command: "run" },
|
|
4778
|
+
state.agentId
|
|
4779
|
+
);
|
|
4780
|
+
const agentKeyNotice = "EVIDENT_AGENT_KEY is deprecated, use EVIDENT_RUNNER_KEY instead; will be removed in a future release.";
|
|
4781
|
+
log2(state, agentKeyNotice, "warn");
|
|
4782
|
+
if (state.interactive && !state.json) {
|
|
4783
|
+
logActivity(state, { type: "info", level: "warn", message: agentKeyNotice });
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4678
4786
|
if (!state.agentId) {
|
|
4679
4787
|
if (credentials2.authType === "agent_key") {
|
|
4680
4788
|
const resolved = await resolveAgentIdFromKey(state.authHeader);
|
|
@@ -4692,9 +4800,15 @@ async function run(options) {
|
|
|
4692
4800
|
process.exit(1);
|
|
4693
4801
|
}
|
|
4694
4802
|
} else {
|
|
4695
|
-
printError(
|
|
4803
|
+
printError(
|
|
4804
|
+
"--runner (or --agent) is required when not using EVIDENT_RUNNER_KEY or EVIDENT_AGENT_KEY"
|
|
4805
|
+
);
|
|
4696
4806
|
blank();
|
|
4697
|
-
console.log(
|
|
4807
|
+
console.log(
|
|
4808
|
+
chalk6.dim(
|
|
4809
|
+
"Either provide --runner/--agent <id> or set EVIDENT_RUNNER_KEY/EVIDENT_AGENT_KEY"
|
|
4810
|
+
)
|
|
4811
|
+
);
|
|
4698
4812
|
blank();
|
|
4699
4813
|
process.exit(1);
|
|
4700
4814
|
}
|
|
@@ -4909,7 +5023,7 @@ async function run(options) {
|
|
|
4909
5023
|
}
|
|
4910
5024
|
telemetry.error(EventTypes.CLI_ERROR, `Run command failed: ${message}`, {
|
|
4911
5025
|
command: "run",
|
|
4912
|
-
agentId: options.agent
|
|
5026
|
+
agentId: options.runner || options.agent
|
|
4913
5027
|
});
|
|
4914
5028
|
await shutdownTelemetry();
|
|
4915
5029
|
process.exit(1);
|
|
@@ -4934,7 +5048,7 @@ program.name("evident").description("Run OpenCode locally and connect it to Evid
|
|
|
4934
5048
|
program.command("login").description("Authenticate with Evident").option("--token", "Use token-based authentication (for CI/CD)").option("--no-browser", "Do not open the browser automatically").action(login);
|
|
4935
5049
|
program.command("logout").description("Remove stored credentials for the current endpoint").option("--all", "Remove stored credentials for all endpoints").action((options) => logout({ all: options.all }));
|
|
4936
5050
|
program.command("whoami").description("Show the currently logged in user").action(whoami);
|
|
4937
|
-
program.command("run").description("Connect to Evident and process messages").option("-a, --agent [id]", "Runner ID to connect to (optional when EVIDENT_AGENT_KEY is set)").option("-p, --port <port>", "OpenCode port (default: 4096)", "4096").option(
|
|
5051
|
+
program.command("run").description("Connect to Evident and process messages").option("-a, --agent [id]", "Runner ID to connect to (optional when EVIDENT_AGENT_KEY is set)").option("--runner [id]", "Alias for --agent (preferred name; wins if both are given)").option("-p, --port <port>", "OpenCode port (default: 4096)", "4096").option(
|
|
4938
5052
|
"--log-level <level>",
|
|
4939
5053
|
"Log verbosity: debug | info | warn | error (default: info). Env: EVIDENT_LOG_LEVEL"
|
|
4940
5054
|
).option("-v, --verbose", "Alias for --log-level debug (ignored if --log-level is set)").option("-c, --conversation <id>", "Process only this specific conversation").option("--idle-timeout <seconds>", "Exit after N seconds idle").option("--json", "Output in JSON format").option(
|
|
@@ -4950,6 +5064,7 @@ program.command("run").description("Connect to Evident and process messages").op
|
|
|
4950
5064
|
(options) => {
|
|
4951
5065
|
run({
|
|
4952
5066
|
agent: options.agent,
|
|
5067
|
+
runner: options.runner,
|
|
4953
5068
|
port: parseInt(options.port, 10),
|
|
4954
5069
|
// Raw string — validation/precedence is single-sourced in run.ts's
|
|
4955
5070
|
// resolveLogLevel (flag > -v > EVIDENT_LOG_LEVEL > info).
|