@evident-ai/cli 3.0.1-dev.f0063e2 → 3.0.1-dev.f1d0273
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 +92 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -470,6 +470,12 @@ import chalk6 from "chalk";
|
|
|
470
470
|
import ora3 from "ora";
|
|
471
471
|
import { select as select3 } from "@inquirer/prompts";
|
|
472
472
|
|
|
473
|
+
// ../../packages/types/src/opencode/index.ts
|
|
474
|
+
function opencodeMessageIdFor(queuedMessageId) {
|
|
475
|
+
const sanitized = queuedMessageId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
476
|
+
return `msg_${sanitized}`;
|
|
477
|
+
}
|
|
478
|
+
|
|
473
479
|
// ../../packages/types/src/telemetry/index.ts
|
|
474
480
|
var TelemetryEventTypes = {
|
|
475
481
|
// Agent activity events (shown in web UI activity log)
|
|
@@ -484,6 +490,29 @@ var TelemetryEventTypes = {
|
|
|
484
490
|
var MAX_FRAME_BYTES = 256 * 1024;
|
|
485
491
|
var TUNNEL_DRAIN_PING_PATH = "/__evident/drain";
|
|
486
492
|
|
|
493
|
+
// ../../packages/types/src/logging/index.ts
|
|
494
|
+
var CORRELATION_ID_HEADER = "x-evident-correlation-id";
|
|
495
|
+
function log(level, event, fields) {
|
|
496
|
+
const method = level === "debug" ? "log" : level;
|
|
497
|
+
try {
|
|
498
|
+
console[method]("[evident]", JSON.stringify({ level, event, ...fields }));
|
|
499
|
+
} catch (err) {
|
|
500
|
+
console.error(
|
|
501
|
+
"[evident] log_serialize_failed",
|
|
502
|
+
event,
|
|
503
|
+
err instanceof Error ? err.message : String(err)
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function stripQuery(url) {
|
|
508
|
+
try {
|
|
509
|
+
return new URL(url).pathname;
|
|
510
|
+
} catch {
|
|
511
|
+
const q = url.indexOf("?");
|
|
512
|
+
return q === -1 ? url : url.slice(0, q);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
487
516
|
// src/lib/telemetry.ts
|
|
488
517
|
var CLI_VERSION = process.env.npm_package_version || "unknown";
|
|
489
518
|
var eventBuffer = [];
|
|
@@ -1023,6 +1052,12 @@ function parentIdOf(m) {
|
|
|
1023
1052
|
const infoParent = m.info?.parentID;
|
|
1024
1053
|
return typeof infoParent === "string" ? infoParent : void 0;
|
|
1025
1054
|
}
|
|
1055
|
+
function finishOf(m) {
|
|
1056
|
+
if (!m || typeof m !== "object") return void 0;
|
|
1057
|
+
if (typeof m.finish === "string") return m.finish;
|
|
1058
|
+
const infoFinish = m.info?.finish;
|
|
1059
|
+
return typeof infoFinish === "string" ? infoFinish : void 0;
|
|
1060
|
+
}
|
|
1026
1061
|
async function createOpenCodeSession(port, directory) {
|
|
1027
1062
|
const url = new URL(`${opencodeBase(port)}/session`);
|
|
1028
1063
|
if (directory && directory.trim()) {
|
|
@@ -1080,19 +1115,36 @@ function findAssistantReplyAfter(messages, userMessageId) {
|
|
|
1080
1115
|
}
|
|
1081
1116
|
return null;
|
|
1082
1117
|
}
|
|
1118
|
+
function findLastAssistantReplyFor(messages, userMessageId) {
|
|
1119
|
+
if (!messages || messages.length === 0) return null;
|
|
1120
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1121
|
+
const m = messages[i];
|
|
1122
|
+
if (roleOf(m) === "assistant" && parentIdOf(m) === userMessageId) return m;
|
|
1123
|
+
}
|
|
1124
|
+
const userIndex = messages.findIndex((m) => idOf(m) === userMessageId);
|
|
1125
|
+
if (userIndex === -1) return null;
|
|
1126
|
+
let last = null;
|
|
1127
|
+
for (let i = userIndex + 1; i < messages.length; i++) {
|
|
1128
|
+
const role = roleOf(messages[i]);
|
|
1129
|
+
if (role === "user") break;
|
|
1130
|
+
if (role === "assistant") last = messages[i];
|
|
1131
|
+
}
|
|
1132
|
+
return last;
|
|
1133
|
+
}
|
|
1083
1134
|
function messageRunState(messages, userMessageId) {
|
|
1084
1135
|
if (!messages || messages.length === 0) return "unknown";
|
|
1085
1136
|
const hasUser = messages.some((m) => idOf(m) === userMessageId);
|
|
1086
|
-
const reply =
|
|
1137
|
+
const reply = findLastAssistantReplyFor(messages, userMessageId);
|
|
1087
1138
|
if (!hasUser) {
|
|
1088
1139
|
if (!reply) return "unknown";
|
|
1089
1140
|
}
|
|
1090
1141
|
if (!reply) return "queued";
|
|
1091
|
-
|
|
1142
|
+
if (completedOf(reply) == null) return "running";
|
|
1143
|
+
if (finishOf(reply) === "tool-calls") return "running";
|
|
1144
|
+
return "done";
|
|
1092
1145
|
}
|
|
1093
|
-
function
|
|
1094
|
-
|
|
1095
|
-
return `msg_${sanitized}`;
|
|
1146
|
+
function opencodeMessageIdFor2(queuedMessageId) {
|
|
1147
|
+
return opencodeMessageIdFor(queuedMessageId);
|
|
1096
1148
|
}
|
|
1097
1149
|
|
|
1098
1150
|
// src/lib/tunnel/connection.ts
|
|
@@ -1163,12 +1215,20 @@ var StreamForwarder = class {
|
|
|
1163
1215
|
}
|
|
1164
1216
|
async handleOpen(frame) {
|
|
1165
1217
|
const { sid, method, path, headers, has_body } = frame;
|
|
1218
|
+
const correlationId = headers?.[CORRELATION_ID_HEADER];
|
|
1219
|
+
const startedAt = Date.now();
|
|
1166
1220
|
if (path === TUNNEL_DRAIN_PING_PATH) {
|
|
1167
1221
|
this.callbacks.onDrainPing?.();
|
|
1168
1222
|
this.send({ type: "head", sid, status: 204, headers: {} });
|
|
1169
1223
|
this.send({ type: "res_end", sid });
|
|
1170
1224
|
return;
|
|
1171
1225
|
}
|
|
1226
|
+
log("info", "agent_request", {
|
|
1227
|
+
correlation_id: correlationId,
|
|
1228
|
+
sid,
|
|
1229
|
+
method,
|
|
1230
|
+
path: stripQuery(path)
|
|
1231
|
+
});
|
|
1172
1232
|
const ac = new AbortController();
|
|
1173
1233
|
let bodyPromise;
|
|
1174
1234
|
let pushBody;
|
|
@@ -1215,6 +1275,12 @@ var StreamForwarder = class {
|
|
|
1215
1275
|
if (!STRIP_RES.has(key.toLowerCase())) resHeaders[key] = value;
|
|
1216
1276
|
});
|
|
1217
1277
|
this.send({ type: "head", sid, status: upstream.status, headers: resHeaders });
|
|
1278
|
+
log("info", "agent_response", {
|
|
1279
|
+
correlation_id: correlationId,
|
|
1280
|
+
sid,
|
|
1281
|
+
status: upstream.status,
|
|
1282
|
+
duration_ms: Date.now() - startedAt
|
|
1283
|
+
});
|
|
1218
1284
|
this.callbacks.onHead?.(sid, upstream.status);
|
|
1219
1285
|
try {
|
|
1220
1286
|
if (upstream.body) {
|
|
@@ -1645,11 +1711,13 @@ var ChannelDriver = class {
|
|
|
1645
1711
|
const sessionId = await this.ensureSession(conv);
|
|
1646
1712
|
const messages = await this.getPendingMessages(conv.id);
|
|
1647
1713
|
let dispatched = 0;
|
|
1714
|
+
let skippedAlreadyDispatched = 0;
|
|
1648
1715
|
for (const message of messages) {
|
|
1649
1716
|
if (this.dispatched.has(message.id)) {
|
|
1717
|
+
skippedAlreadyDispatched += 1;
|
|
1650
1718
|
continue;
|
|
1651
1719
|
}
|
|
1652
|
-
const opencodeMessageId =
|
|
1720
|
+
const opencodeMessageId = opencodeMessageIdFor2(message.id);
|
|
1653
1721
|
const options = {
|
|
1654
1722
|
agent: message.opencode_agent ?? void 0,
|
|
1655
1723
|
model: message.opencode_model ?? void 0
|
|
@@ -1679,6 +1747,13 @@ var ChannelDriver = class {
|
|
|
1679
1747
|
this.registerInFlight(conv, sessionId, message, opencodeMessageId);
|
|
1680
1748
|
dispatched += 1;
|
|
1681
1749
|
}
|
|
1750
|
+
if (messages.length > 0 && dispatched === 0 && skippedAlreadyDispatched === messages.length) {
|
|
1751
|
+
this.log({
|
|
1752
|
+
level: "error",
|
|
1753
|
+
message: `Conversation ${conv.id.slice(0, 8)} has ${messages.length} pending message(s) but ALL are already marked dispatched locally (in-flight set: ${this.dispatched.size}) \u2014 none sent to OpenCode this tick. If this repeats, a message may be stuck acknowledged-but-never-dispatched (its watcher never settled).`,
|
|
1754
|
+
conversation_id: conv.id
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1682
1757
|
this.ensureWatcherRunning(sessionId);
|
|
1683
1758
|
return dispatched;
|
|
1684
1759
|
}
|
|
@@ -2497,7 +2572,7 @@ async function getAgentInfo(agentId, authHeader) {
|
|
|
2497
2572
|
// src/commands/run.ts
|
|
2498
2573
|
var MAX_ACTIVITY_LOG_ENTRIES = 10;
|
|
2499
2574
|
var CHANNEL_POLL_INTERVAL_MS = Number(process.env.EVIDENT_CHANNEL_POLL_INTERVAL_MS) || 2e3;
|
|
2500
|
-
function
|
|
2575
|
+
function log2(state, message, isError = false) {
|
|
2501
2576
|
if (state.json) {
|
|
2502
2577
|
console.log(
|
|
2503
2578
|
JSON.stringify({
|
|
@@ -2522,9 +2597,9 @@ function logActivity(state, entry) {
|
|
|
2522
2597
|
}
|
|
2523
2598
|
if (!state.interactive) {
|
|
2524
2599
|
if (entry.type === "error") {
|
|
2525
|
-
|
|
2600
|
+
log2(state, entry.error ?? "Unknown error", true);
|
|
2526
2601
|
} else if (entry.type === "info" && entry.message) {
|
|
2527
|
-
|
|
2602
|
+
log2(state, entry.message);
|
|
2528
2603
|
}
|
|
2529
2604
|
}
|
|
2530
2605
|
}
|
|
@@ -2671,7 +2746,7 @@ async function cleanup(state) {
|
|
|
2671
2746
|
logActivity(state, { type: "info", message: "Stopped OpenCode process" });
|
|
2672
2747
|
displayStatus(state);
|
|
2673
2748
|
} else {
|
|
2674
|
-
|
|
2749
|
+
log2(state, "Stopped OpenCode process");
|
|
2675
2750
|
}
|
|
2676
2751
|
state.opencodeProcess = null;
|
|
2677
2752
|
}
|
|
@@ -2697,7 +2772,7 @@ async function run(options) {
|
|
|
2697
2772
|
authHeader: ""
|
|
2698
2773
|
};
|
|
2699
2774
|
if (state.idleTimeout === null && (process.env.GITHUB_ACTIONS || process.env.CI)) {
|
|
2700
|
-
|
|
2775
|
+
log2(
|
|
2701
2776
|
state,
|
|
2702
2777
|
"Warning: No --idle-timeout set in CI environment. The runner will poll indefinitely until the job times out. Consider adding --idle-timeout 30 to avoid wasting runner minutes.",
|
|
2703
2778
|
false
|
|
@@ -2708,7 +2783,7 @@ async function run(options) {
|
|
|
2708
2783
|
logActivity(state, { type: "info", message: "Shutting down..." });
|
|
2709
2784
|
displayStatus(state);
|
|
2710
2785
|
} else {
|
|
2711
|
-
|
|
2786
|
+
log2(state, "Shutting down...");
|
|
2712
2787
|
}
|
|
2713
2788
|
await cleanup(state);
|
|
2714
2789
|
await shutdownTelemetry();
|
|
@@ -2741,7 +2816,7 @@ async function run(options) {
|
|
|
2741
2816
|
const resolved = await resolveAgentIdFromKey(state.authHeader);
|
|
2742
2817
|
if (resolved.agent_id) {
|
|
2743
2818
|
state.agentId = resolved.agent_id;
|
|
2744
|
-
|
|
2819
|
+
log2(state, `Resolved agent ID from key: ${state.agentId}`);
|
|
2745
2820
|
if (state.interactive && !state.json) {
|
|
2746
2821
|
logActivity(state, {
|
|
2747
2822
|
type: "info",
|
|
@@ -2804,7 +2879,7 @@ async function run(options) {
|
|
|
2804
2879
|
port: state.port,
|
|
2805
2880
|
interactive: state.interactive,
|
|
2806
2881
|
agentId: state.agentId,
|
|
2807
|
-
log: (message) =>
|
|
2882
|
+
log: (message) => log2(state, message)
|
|
2808
2883
|
});
|
|
2809
2884
|
state.port = oc.port;
|
|
2810
2885
|
state.opencodeProcess = oc.process;
|
|
@@ -2814,7 +2889,7 @@ async function run(options) {
|
|
|
2814
2889
|
ocSpinner?.succeed(`OpenCode running on port ${state.port}${version}`);
|
|
2815
2890
|
const versionWarning = buildOpenCodeVersionWarning(state.opencodeVersion);
|
|
2816
2891
|
if (versionWarning) {
|
|
2817
|
-
|
|
2892
|
+
log2(state, versionWarning, false);
|
|
2818
2893
|
if (state.interactive && !state.json) {
|
|
2819
2894
|
logActivity(state, { type: "info", message: versionWarning });
|
|
2820
2895
|
}
|
|
@@ -2924,7 +2999,7 @@ async function run(options) {
|
|
|
2924
2999
|
throw error2;
|
|
2925
3000
|
}
|
|
2926
3001
|
if (!interactive || state.json) {
|
|
2927
|
-
|
|
3002
|
+
log2(state, "Driving channel messages...");
|
|
2928
3003
|
}
|
|
2929
3004
|
await driveChannels(state, channelDriver);
|
|
2930
3005
|
await cleanup(state);
|
|
@@ -2936,7 +3011,7 @@ async function run(options) {
|
|
|
2936
3011
|
})
|
|
2937
3012
|
);
|
|
2938
3013
|
} else if (!interactive) {
|
|
2939
|
-
|
|
3014
|
+
log2(state, `Completed. Processed ${state.messageCount} message(s).`);
|
|
2940
3015
|
}
|
|
2941
3016
|
await shutdownTelemetry();
|
|
2942
3017
|
process.exit(0);
|