@evident-ai/cli 3.0.1-dev.fa376ba → 3.0.1-dev.fbf2c4d
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 +1 -3
- package/dist/index.js +60 -123
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,9 +86,7 @@ Options:
|
|
|
86
86
|
- `-a, --agent [id]` — Agent ID to connect to. Optional when `EVIDENT_AGENT_KEY`
|
|
87
87
|
is set (the agent is then resolved automatically from the key).
|
|
88
88
|
- `-p, --port <port>` — OpenCode port (default: `4096`).
|
|
89
|
-
-
|
|
90
|
-
`info`). Env: `EVIDENT_LOG_LEVEL`.
|
|
91
|
-
- `-v, --verbose` — Alias for `--log-level debug` (an explicit `--log-level` wins).
|
|
89
|
+
- `-v, --verbose` — Show detailed request/response information.
|
|
92
90
|
- `-c, --conversation <id>` — Process only this specific conversation.
|
|
93
91
|
- `--idle-timeout <seconds>` — Exit after N seconds with no pending work (useful
|
|
94
92
|
in CI to avoid polling indefinitely).
|
package/dist/index.js
CHANGED
|
@@ -1811,12 +1811,6 @@ function messageIdOf(m) {
|
|
|
1811
1811
|
const infoId = m.info?.id;
|
|
1812
1812
|
return typeof infoId === "string" ? infoId : void 0;
|
|
1813
1813
|
}
|
|
1814
|
-
var LOG_LEVELS = {
|
|
1815
|
-
debug: 0,
|
|
1816
|
-
info: 1,
|
|
1817
|
-
warn: 2,
|
|
1818
|
-
error: 3
|
|
1819
|
-
};
|
|
1820
1814
|
var DEFAULT_RETRY_POLICY = {
|
|
1821
1815
|
maxAttempts: 6,
|
|
1822
1816
|
baseDelayMs: 500,
|
|
@@ -2199,7 +2193,7 @@ var ChannelDriver = class {
|
|
|
2199
2193
|
if (await sessionExists(this.port, sessionId) === false) {
|
|
2200
2194
|
this.sessions.delete(conv.id);
|
|
2201
2195
|
this.log({
|
|
2202
|
-
level: "
|
|
2196
|
+
level: "info",
|
|
2203
2197
|
message: `Message ${message.id.slice(0, 8)} dispatch hit a session (${sessionId.slice(0, 8)}) that was deleted mid-dispatch (cleanup race) \u2014 deferring this and later messages for conversation ${conv.id.slice(0, 8)} to the next tick (recreated then, in order). Already-dispatched turns keep their watcher.`,
|
|
2204
2198
|
conversation_id: conv.id,
|
|
2205
2199
|
message_id: message.id
|
|
@@ -2218,7 +2212,7 @@ var ChannelDriver = class {
|
|
|
2218
2212
|
}
|
|
2219
2213
|
if (opencodeMessageId === null) {
|
|
2220
2214
|
this.log({
|
|
2221
|
-
level: "
|
|
2215
|
+
level: "error",
|
|
2222
2216
|
message: `Message ${message.id.slice(0, 8)} dispatched but its opencode id could not be read back \u2014 leaving un-tracked to retry next tick`,
|
|
2223
2217
|
conversation_id: conv.id,
|
|
2224
2218
|
message_id: message.id
|
|
@@ -2232,7 +2226,7 @@ var ChannelDriver = class {
|
|
|
2232
2226
|
}
|
|
2233
2227
|
if (messages.length > 0 && dispatched === 0 && skippedAlreadyDispatched === messages.length) {
|
|
2234
2228
|
this.log({
|
|
2235
|
-
level: "
|
|
2229
|
+
level: "error",
|
|
2236
2230
|
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).`,
|
|
2237
2231
|
conversation_id: conv.id
|
|
2238
2232
|
});
|
|
@@ -2246,7 +2240,7 @@ var ChannelDriver = class {
|
|
|
2246
2240
|
const exists = await sessionExists(this.port, bound);
|
|
2247
2241
|
if (exists === false) {
|
|
2248
2242
|
this.log({
|
|
2249
|
-
level: "
|
|
2243
|
+
level: "info",
|
|
2250
2244
|
message: `OpenCode session ${bound} for conversation ${conv.id.slice(0, 8)} no longer exists (deleted or DB reset) \u2014 creating a fresh session and rebinding.`,
|
|
2251
2245
|
conversation_id: conv.id
|
|
2252
2246
|
});
|
|
@@ -2281,7 +2275,7 @@ var ChannelDriver = class {
|
|
|
2281
2275
|
this.opencodeDirectory = await getOpenCodeDirectory(this.port);
|
|
2282
2276
|
if (!this.opencodeDirectory) {
|
|
2283
2277
|
this.log({
|
|
2284
|
-
level: "
|
|
2278
|
+
level: "info",
|
|
2285
2279
|
message: "Could not determine opencode directory (GET /path) \u2014 new sessions may not appear in opencode web"
|
|
2286
2280
|
});
|
|
2287
2281
|
}
|
|
@@ -2559,7 +2553,7 @@ var ChannelDriver = class {
|
|
|
2559
2553
|
} catch (err) {
|
|
2560
2554
|
if (err instanceof ChannelAuthError) throw err;
|
|
2561
2555
|
this.log({
|
|
2562
|
-
level: "
|
|
2556
|
+
level: "error",
|
|
2563
2557
|
message: `Failed to mark message ${inFlight.evidentMessageId.slice(0, 8)} processing (will retry next tick): ${err instanceof Error ? err.message : String(err)}`,
|
|
2564
2558
|
conversation_id: conv.id,
|
|
2565
2559
|
message_id: inFlight.evidentMessageId
|
|
@@ -2569,7 +2563,7 @@ var ChannelDriver = class {
|
|
|
2569
2563
|
inFlight.started = true;
|
|
2570
2564
|
if (!claimed) {
|
|
2571
2565
|
this.log({
|
|
2572
|
-
level: "
|
|
2566
|
+
level: "info",
|
|
2573
2567
|
message: `Message ${inFlight.evidentMessageId.slice(0, 8)} already marked processing \u2014 continuing`,
|
|
2574
2568
|
conversation_id: conv.id,
|
|
2575
2569
|
message_id: inFlight.evidentMessageId
|
|
@@ -2598,7 +2592,7 @@ var ChannelDriver = class {
|
|
|
2598
2592
|
if (err instanceof ChannelAuthError) throw err;
|
|
2599
2593
|
if (err instanceof ChannelTerminalError) {
|
|
2600
2594
|
this.log({
|
|
2601
|
-
level: "
|
|
2595
|
+
level: "error",
|
|
2602
2596
|
message: `Failed to mark message ${inFlight.evidentMessageId.slice(0, 8)} done (terminal HTTP ${err.status}) \u2014 leaving for the cron safety net: ${err.message}`,
|
|
2603
2597
|
conversation_id: conv.id,
|
|
2604
2598
|
message_id: inFlight.evidentMessageId
|
|
@@ -2608,7 +2602,7 @@ var ChannelDriver = class {
|
|
|
2608
2602
|
}
|
|
2609
2603
|
if (this.now() >= inFlight.deadline) {
|
|
2610
2604
|
this.log({
|
|
2611
|
-
level: "
|
|
2605
|
+
level: "error",
|
|
2612
2606
|
message: `Failed to mark message ${inFlight.evidentMessageId.slice(0, 8)} done within the watch window \u2014 leaving for the cron safety net: ${err instanceof Error ? err.message : String(err)}`,
|
|
2613
2607
|
conversation_id: conv.id,
|
|
2614
2608
|
message_id: inFlight.evidentMessageId
|
|
@@ -2617,7 +2611,7 @@ var ChannelDriver = class {
|
|
|
2617
2611
|
return;
|
|
2618
2612
|
}
|
|
2619
2613
|
this.log({
|
|
2620
|
-
level: "
|
|
2614
|
+
level: "error",
|
|
2621
2615
|
message: `Failed to mark message ${inFlight.evidentMessageId.slice(0, 8)} done (will retry next tick): ${err instanceof Error ? err.message : String(err)}`,
|
|
2622
2616
|
conversation_id: conv.id,
|
|
2623
2617
|
message_id: inFlight.evidentMessageId
|
|
@@ -2645,7 +2639,7 @@ var ChannelDriver = class {
|
|
|
2645
2639
|
if (err instanceof ChannelAuthError) throw err;
|
|
2646
2640
|
if (err instanceof ChannelTerminalError) {
|
|
2647
2641
|
this.log({
|
|
2648
|
-
level: "
|
|
2642
|
+
level: "error",
|
|
2649
2643
|
message: `Failed to mark message ${inFlight.evidentMessageId.slice(0, 8)} failed (terminal HTTP ${err.status}) \u2014 leaving for the cron safety net: ${err.message}`,
|
|
2650
2644
|
conversation_id: conv.id,
|
|
2651
2645
|
message_id: inFlight.evidentMessageId
|
|
@@ -2655,7 +2649,7 @@ var ChannelDriver = class {
|
|
|
2655
2649
|
}
|
|
2656
2650
|
if (this.now() >= inFlight.deadline) {
|
|
2657
2651
|
this.log({
|
|
2658
|
-
level: "
|
|
2652
|
+
level: "error",
|
|
2659
2653
|
message: `Failed to mark message ${inFlight.evidentMessageId.slice(0, 8)} failed within the watch window \u2014 leaving for the cron safety net: ${err instanceof Error ? err.message : String(err)}`,
|
|
2660
2654
|
conversation_id: conv.id,
|
|
2661
2655
|
message_id: inFlight.evidentMessageId
|
|
@@ -2664,7 +2658,7 @@ var ChannelDriver = class {
|
|
|
2664
2658
|
return;
|
|
2665
2659
|
}
|
|
2666
2660
|
this.log({
|
|
2667
|
-
level: "
|
|
2661
|
+
level: "error",
|
|
2668
2662
|
message: `Failed to mark message ${inFlight.evidentMessageId.slice(0, 8)} failed (will retry next tick): ${err instanceof Error ? err.message : String(err)}`,
|
|
2669
2663
|
conversation_id: conv.id,
|
|
2670
2664
|
message_id: inFlight.evidentMessageId
|
|
@@ -2687,7 +2681,7 @@ var ChannelDriver = class {
|
|
|
2687
2681
|
const activelyRunning = state === "running" && !awaitingHuman;
|
|
2688
2682
|
if (activelyRunning && this.now() - inFlight.processingAnchorMs >= ABSOLUTE_MAX_PROCESSING_MS) {
|
|
2689
2683
|
this.log({
|
|
2690
|
-
level: "
|
|
2684
|
+
level: "error",
|
|
2691
2685
|
message: `Message ${inFlight.evidentMessageId.slice(0, 8)} exceeded the absolute processing ceiling (${Math.round((this.now() - inFlight.processingAnchorMs) / 6e4)}min, session ${sessionId}) while still actively running \u2014 releasing so the cron can reclaim it`,
|
|
2692
2686
|
conversation_id: conv.id,
|
|
2693
2687
|
message_id: inFlight.evidentMessageId
|
|
@@ -2730,7 +2724,7 @@ var ChannelDriver = class {
|
|
|
2730
2724
|
const queuedBehindRunningSibling = state === "queued" && hasActivelyRunningSibling;
|
|
2731
2725
|
if (!activelyRunning && !queuedBehindRunningSibling && this.now() >= inFlight.deadline) {
|
|
2732
2726
|
this.log({
|
|
2733
|
-
level: "
|
|
2727
|
+
level: "info",
|
|
2734
2728
|
message: `Message ${inFlight.evidentMessageId.slice(0, 8)} did not complete within the watch window \u2014 leaving for the cron safety net`,
|
|
2735
2729
|
conversation_id: conv.id,
|
|
2736
2730
|
message_id: inFlight.evidentMessageId
|
|
@@ -2773,7 +2767,7 @@ var ChannelDriver = class {
|
|
|
2773
2767
|
this.readoptPollUnresolvedSignalled.delete(id);
|
|
2774
2768
|
if (cleared || clearedUndeliverable) {
|
|
2775
2769
|
this.log({
|
|
2776
|
-
level: "
|
|
2770
|
+
level: "info",
|
|
2777
2771
|
message: `Re-adopt: message ${id.slice(0, 8)} left the processing list (cron reset) \u2014 cleared gave-up marker`,
|
|
2778
2772
|
message_id: id
|
|
2779
2773
|
});
|
|
@@ -2786,7 +2780,7 @@ var ChannelDriver = class {
|
|
|
2786
2780
|
for (const row of rows) {
|
|
2787
2781
|
if (!row.opencode_session_id) {
|
|
2788
2782
|
this.log({
|
|
2789
|
-
level: "
|
|
2783
|
+
level: "error",
|
|
2790
2784
|
message: `Cannot re-adopt processing message ${row.id.slice(0, 8)} \u2014 no opencode session id; leaving for the cron safety net`,
|
|
2791
2785
|
conversation_id: row.conversation_id,
|
|
2792
2786
|
message_id: row.id
|
|
@@ -2803,7 +2797,7 @@ var ChannelDriver = class {
|
|
|
2803
2797
|
const res = await this.fetchImpl(`${this.opencodeBase}/session/${sessionId}/message`);
|
|
2804
2798
|
if (!res.ok) {
|
|
2805
2799
|
this.log({
|
|
2806
|
-
level: "
|
|
2800
|
+
level: "error",
|
|
2807
2801
|
message: `Re-adopt: polling session ${sessionId.slice(0, 8)} returned HTTP ${res.status} \u2014 skipping this session this tick`
|
|
2808
2802
|
});
|
|
2809
2803
|
continue;
|
|
@@ -2811,7 +2805,7 @@ var ChannelDriver = class {
|
|
|
2811
2805
|
const body = await res.json();
|
|
2812
2806
|
if (!Array.isArray(body)) {
|
|
2813
2807
|
this.log({
|
|
2814
|
-
level: "
|
|
2808
|
+
level: "error",
|
|
2815
2809
|
message: `Re-adopt: polling session ${sessionId.slice(0, 8)} returned a non-array message body \u2014 skipping this session this tick`
|
|
2816
2810
|
});
|
|
2817
2811
|
continue;
|
|
@@ -2819,7 +2813,7 @@ var ChannelDriver = class {
|
|
|
2819
2813
|
messages = body;
|
|
2820
2814
|
} catch (err) {
|
|
2821
2815
|
this.log({
|
|
2822
|
-
level: "
|
|
2816
|
+
level: "error",
|
|
2823
2817
|
message: `Re-adopt: failed to poll session ${sessionId.slice(0, 8)} (will retry next drain): ${err instanceof Error ? err.message : String(err)}`
|
|
2824
2818
|
});
|
|
2825
2819
|
continue;
|
|
@@ -2852,7 +2846,7 @@ var ChannelDriver = class {
|
|
|
2852
2846
|
async readoptOne(sessionId, row, messages, sessionOngoing) {
|
|
2853
2847
|
if (this.isTracked(sessionId, row.id)) {
|
|
2854
2848
|
this.log({
|
|
2855
|
-
level: "
|
|
2849
|
+
level: "info",
|
|
2856
2850
|
message: `Re-adopt: message ${row.id.slice(0, 8)} already tracked in-flight \u2014 skipping (owned by the watcher loop)`,
|
|
2857
2851
|
conversation_id: row.conversation_id,
|
|
2858
2852
|
message_id: row.id
|
|
@@ -2864,7 +2858,7 @@ var ChannelDriver = class {
|
|
|
2864
2858
|
if (state === "done") {
|
|
2865
2859
|
if (this.doneUndeliverable.has(row.id)) {
|
|
2866
2860
|
this.log({
|
|
2867
|
-
level: "
|
|
2861
|
+
level: "info",
|
|
2868
2862
|
message: `Re-adopt: message ${row.id.slice(0, 8)} markDone is terminally undeliverable \u2014 left to the cron; skipping until it leaves processing`,
|
|
2869
2863
|
conversation_id: row.conversation_id,
|
|
2870
2864
|
message_id: row.id
|
|
@@ -2885,7 +2879,7 @@ var ChannelDriver = class {
|
|
|
2885
2879
|
if (err instanceof ChannelTerminalError) {
|
|
2886
2880
|
this.doneUndeliverable.add(row.id);
|
|
2887
2881
|
this.log({
|
|
2888
|
-
level: "
|
|
2882
|
+
level: "error",
|
|
2889
2883
|
message: `Re-adopt: failed to mark message ${row.id.slice(0, 8)} done (terminal HTTP ${err.status}) \u2014 parking until it leaves processing; leaving for the cron safety net: ${err.message}`,
|
|
2890
2884
|
conversation_id: row.conversation_id,
|
|
2891
2885
|
message_id: row.id
|
|
@@ -2894,7 +2888,7 @@ var ChannelDriver = class {
|
|
|
2894
2888
|
return;
|
|
2895
2889
|
}
|
|
2896
2890
|
this.log({
|
|
2897
|
-
level: "
|
|
2891
|
+
level: "error",
|
|
2898
2892
|
message: `Re-adopt: failed to mark message ${row.id.slice(0, 8)} done (will retry next drain): ${err instanceof Error ? err.message : String(err)}`,
|
|
2899
2893
|
conversation_id: row.conversation_id,
|
|
2900
2894
|
message_id: row.id
|
|
@@ -2920,7 +2914,7 @@ var ChannelDriver = class {
|
|
|
2920
2914
|
if (err instanceof ChannelTerminalError) {
|
|
2921
2915
|
this.doneUndeliverable.add(row.id);
|
|
2922
2916
|
this.log({
|
|
2923
|
-
level: "
|
|
2917
|
+
level: "error",
|
|
2924
2918
|
message: `Re-adopt: failed to mark message ${row.id.slice(0, 8)} failed (terminal HTTP ${err.status}) \u2014 parking until it leaves processing; leaving for the cron safety net: ${err.message}`,
|
|
2925
2919
|
conversation_id: row.conversation_id,
|
|
2926
2920
|
message_id: row.id
|
|
@@ -2929,7 +2923,7 @@ var ChannelDriver = class {
|
|
|
2929
2923
|
return;
|
|
2930
2924
|
}
|
|
2931
2925
|
this.log({
|
|
2932
|
-
level: "
|
|
2926
|
+
level: "error",
|
|
2933
2927
|
message: `Re-adopt: failed to mark message ${row.id.slice(0, 8)} failed (will retry next drain): ${err instanceof Error ? err.message : String(err)}`,
|
|
2934
2928
|
conversation_id: row.conversation_id,
|
|
2935
2929
|
message_id: row.id
|
|
@@ -2942,7 +2936,7 @@ var ChannelDriver = class {
|
|
|
2942
2936
|
}
|
|
2943
2937
|
if (this.dontRedispatch.has(row.id)) {
|
|
2944
2938
|
this.log({
|
|
2945
|
-
level: "
|
|
2939
|
+
level: "info",
|
|
2946
2940
|
message: `Re-adopt: message ${row.id.slice(0, 8)} already gave up \u2014 left to the cron; skipping until it leaves processing`,
|
|
2947
2941
|
conversation_id: row.conversation_id,
|
|
2948
2942
|
message_id: row.id
|
|
@@ -2967,7 +2961,7 @@ var ChannelDriver = class {
|
|
|
2967
2961
|
}
|
|
2968
2962
|
if (ongoing === true) {
|
|
2969
2963
|
this.log({
|
|
2970
|
-
level: "
|
|
2964
|
+
level: "info",
|
|
2971
2965
|
message: `Re-adopt: message ${row.id.slice(0, 8)} running/${shape} and session ${sessionId.slice(0, 8)} is ongoing per GET /session/status (busy/retry) \u2014 re-attaching watcher (no re-dispatch)`,
|
|
2972
2966
|
conversation_id: row.conversation_id,
|
|
2973
2967
|
message_id: row.id
|
|
@@ -2975,7 +2969,7 @@ var ChannelDriver = class {
|
|
|
2975
2969
|
} else {
|
|
2976
2970
|
if (shape === "b1") {
|
|
2977
2971
|
this.log({
|
|
2978
|
-
level: "
|
|
2972
|
+
level: "info",
|
|
2979
2973
|
message: `Re-adopt: message ${row.id.slice(0, 8)} running/b1 but GET /session/status was unreadable (null) for session ${sessionId.slice(0, 8)} \u2014 NOT latching a b1 row on a transient status blip; leaving it un-tracked to re-evaluate on the next drain`,
|
|
2980
2974
|
conversation_id: row.conversation_id,
|
|
2981
2975
|
message_id: row.id
|
|
@@ -2987,7 +2981,7 @@ var ChannelDriver = class {
|
|
|
2987
2981
|
return;
|
|
2988
2982
|
}
|
|
2989
2983
|
this.log({
|
|
2990
|
-
level: "
|
|
2984
|
+
level: "info",
|
|
2991
2985
|
message: `Re-adopt: message ${row.id.slice(0, 8)} running/${shape} but GET /session/status was unreadable (null) for session ${sessionId.slice(0, 8)} \u2014 falling back to the #253 preamble + descendant cross-check`,
|
|
2992
2986
|
conversation_id: row.conversation_id,
|
|
2993
2987
|
message_id: row.id
|
|
@@ -2998,7 +2992,7 @@ var ChannelDriver = class {
|
|
|
2998
2992
|
const descendantAlive = await this.isAnyDescendantSessionAlive(sessionId);
|
|
2999
2993
|
if (descendantAlive === true) {
|
|
3000
2994
|
this.log({
|
|
3001
|
-
level: "
|
|
2995
|
+
level: "info",
|
|
3002
2996
|
message: `Re-adopt: message ${row.id.slice(0, 8)} preamble-pinned running (root ${sessionId.slice(0, 8)}) but a live descendant sub-agent session was found \u2014 treating as still running, re-attaching watcher (no re-dispatch)`,
|
|
3003
2997
|
conversation_id: row.conversation_id,
|
|
3004
2998
|
message_id: row.id
|
|
@@ -3022,7 +3016,7 @@ var ChannelDriver = class {
|
|
|
3022
3016
|
this.readopted.add(row.id);
|
|
3023
3017
|
this.ensureWatcherRunning(sessionId);
|
|
3024
3018
|
this.log({
|
|
3025
|
-
level: "
|
|
3019
|
+
level: "info",
|
|
3026
3020
|
message: `Re-adopt: message ${row.id.slice(0, 8)} ${state} \u2014 re-attached watcher (stored id, no re-dispatch)`,
|
|
3027
3021
|
conversation_id: row.conversation_id,
|
|
3028
3022
|
message_id: row.id
|
|
@@ -3056,7 +3050,7 @@ var ChannelDriver = class {
|
|
|
3056
3050
|
async forceReadoptRun(sessionId, row) {
|
|
3057
3051
|
if (this.stopped) {
|
|
3058
3052
|
this.log({
|
|
3059
|
-
level: "
|
|
3053
|
+
level: "info",
|
|
3060
3054
|
message: `Re-adopt: message ${row.id.slice(0, 8)} orphaned but the runner is stopping \u2014 not starting a fresh turn; leaving for restart recovery`,
|
|
3061
3055
|
conversation_id: row.conversation_id,
|
|
3062
3056
|
message_id: row.id
|
|
@@ -3065,7 +3059,7 @@ var ChannelDriver = class {
|
|
|
3065
3059
|
}
|
|
3066
3060
|
if (this.awaitingReadopt.has(row.id)) {
|
|
3067
3061
|
this.log({
|
|
3068
|
-
level: "
|
|
3062
|
+
level: "info",
|
|
3069
3063
|
message: `Re-adopt: message ${row.id.slice(0, 8)} already has a re-dispatch awaiting read-back \u2014 skipping (at most once)`,
|
|
3070
3064
|
conversation_id: row.conversation_id,
|
|
3071
3065
|
message_id: row.id
|
|
@@ -3075,7 +3069,7 @@ var ChannelDriver = class {
|
|
|
3075
3069
|
if (this.processedAtMs(row) + this.pausedMaxWaitMs <= this.now()) {
|
|
3076
3070
|
this.dontRedispatch.add(row.id);
|
|
3077
3071
|
this.log({
|
|
3078
|
-
level: "
|
|
3072
|
+
level: "info",
|
|
3079
3073
|
message: `Re-adopt: message ${row.id.slice(0, 8)} orphaned but its re-adopt window has already elapsed \u2014 not dispatching an unwatchable turn; parking until it leaves processing (cron will reset it)`,
|
|
3080
3074
|
conversation_id: row.conversation_id,
|
|
3081
3075
|
message_id: row.id
|
|
@@ -3104,7 +3098,7 @@ var ChannelDriver = class {
|
|
|
3104
3098
|
this.awaitingReadopt.delete(row.id);
|
|
3105
3099
|
if (err instanceof ChannelAuthError) throw err;
|
|
3106
3100
|
this.log({
|
|
3107
|
-
level: "
|
|
3101
|
+
level: "error",
|
|
3108
3102
|
message: `Re-adopt: re-dispatch failed for message ${row.id.slice(0, 8)} (will retry next drain): ${err instanceof Error ? err.message : String(err)}`,
|
|
3109
3103
|
conversation_id: row.conversation_id,
|
|
3110
3104
|
message_id: row.id
|
|
@@ -3115,7 +3109,7 @@ var ChannelDriver = class {
|
|
|
3115
3109
|
if (ocId === null) {
|
|
3116
3110
|
this.awaitingReadopt.delete(row.id);
|
|
3117
3111
|
this.log({
|
|
3118
|
-
level: "
|
|
3112
|
+
level: "error",
|
|
3119
3113
|
message: `Re-adopt: message ${row.id.slice(0, 8)} re-dispatched but its opencode id could not be read back \u2014 leaving un-tracked to retry next drain`,
|
|
3120
3114
|
conversation_id: row.conversation_id,
|
|
3121
3115
|
message_id: row.id
|
|
@@ -3200,7 +3194,7 @@ var ChannelDriver = class {
|
|
|
3200
3194
|
if (this.readopted.delete(evidentMessageId) && inFlight && !inFlight.done) {
|
|
3201
3195
|
this.dontRedispatch.add(evidentMessageId);
|
|
3202
3196
|
this.log({
|
|
3203
|
-
level: "
|
|
3197
|
+
level: "info",
|
|
3204
3198
|
message: `Re-adopt: message ${evidentMessageId.slice(0, 8)} gave up \u2014 parking until it leaves the processing list (cron reset)`,
|
|
3205
3199
|
conversation_id: watcher.conv.id,
|
|
3206
3200
|
message_id: evidentMessageId
|
|
@@ -3372,13 +3366,13 @@ var ChannelDriver = class {
|
|
|
3372
3366
|
return null;
|
|
3373
3367
|
}
|
|
3374
3368
|
this.log({
|
|
3375
|
-
level: "
|
|
3369
|
+
level: "info",
|
|
3376
3370
|
message: `Session title fetch for session ${sessionId.slice(0, 8)} (agent ${this.agentId.slice(0, 8)}) returned HTTP ${res.status} \u2014 omitting title`,
|
|
3377
3371
|
conversation_id: conversationId
|
|
3378
3372
|
});
|
|
3379
3373
|
} catch (err) {
|
|
3380
3374
|
this.log({
|
|
3381
|
-
level: "
|
|
3375
|
+
level: "info",
|
|
3382
3376
|
message: `Best-effort session title fetch failed for session ${sessionId.slice(0, 8)} (agent ${this.agentId.slice(0, 8)}) \u2014 omitting title: ${err instanceof Error ? err.message : String(err)}`,
|
|
3383
3377
|
conversation_id: conversationId
|
|
3384
3378
|
});
|
|
@@ -3428,7 +3422,7 @@ var ChannelDriver = class {
|
|
|
3428
3422
|
const sessions = await listSessions(this.port);
|
|
3429
3423
|
if (!sessions) {
|
|
3430
3424
|
this.log({
|
|
3431
|
-
level: "
|
|
3425
|
+
level: "error",
|
|
3432
3426
|
message: `Re-adopt: could not enumerate sessions to cross-check descendant liveness for root ${rootSessionId} (listSessions failed) \u2014 treating child liveness as indeterminate`
|
|
3433
3427
|
});
|
|
3434
3428
|
return null;
|
|
@@ -3714,7 +3708,7 @@ var ChannelDriver = class {
|
|
|
3714
3708
|
);
|
|
3715
3709
|
if (!res.ok) {
|
|
3716
3710
|
this.log({
|
|
3717
|
-
level: "
|
|
3711
|
+
level: "error",
|
|
3718
3712
|
message: `Signal '${signal}' for message ${messageId.slice(0, 8)} returned HTTP ${res.status} (telemetry-only, ignored)`,
|
|
3719
3713
|
conversation_id: conversationId,
|
|
3720
3714
|
message_id: messageId
|
|
@@ -3724,7 +3718,7 @@ var ChannelDriver = class {
|
|
|
3724
3718
|
return true;
|
|
3725
3719
|
} catch (err) {
|
|
3726
3720
|
this.log({
|
|
3727
|
-
level: "
|
|
3721
|
+
level: "error",
|
|
3728
3722
|
message: `Signal '${signal}' for message ${messageId.slice(0, 8)} failed (telemetry-only, ignored): ${err instanceof Error ? err.message : String(err)}`,
|
|
3729
3723
|
conversation_id: conversationId,
|
|
3730
3724
|
message_id: messageId
|
|
@@ -4068,53 +4062,23 @@ var MAX_ACTIVITY_LOG_ENTRIES = 10;
|
|
|
4068
4062
|
var CHANNEL_POLL_INTERVAL_MS = Number(process.env.EVIDENT_CHANNEL_POLL_INTERVAL_MS) || 2e3;
|
|
4069
4063
|
var CHANNEL_STUCK_QUEUED_MS = Number(process.env.EVIDENT_STUCK_QUEUED_MS) || void 0;
|
|
4070
4064
|
var SHUTDOWN_DRAIN_TIMEOUT_MS = Number(process.env.EVIDENT_SHUTDOWN_DRAIN_MS) || 25e3;
|
|
4071
|
-
function
|
|
4072
|
-
const accepted = Object.keys(LOG_LEVELS);
|
|
4073
|
-
const validate = (value, source) => {
|
|
4074
|
-
const normalized = value.trim().toLowerCase();
|
|
4075
|
-
if (!accepted.includes(normalized)) {
|
|
4076
|
-
throw new Error(
|
|
4077
|
-
`Invalid log level "${value}"${source}; expected one of ${accepted.join(", ")}`
|
|
4078
|
-
);
|
|
4079
|
-
}
|
|
4080
|
-
return normalized;
|
|
4081
|
-
};
|
|
4082
|
-
if (options.logLevel !== void 0) {
|
|
4083
|
-
return validate(options.logLevel, " (--log-level)");
|
|
4084
|
-
}
|
|
4085
|
-
if (options.verbose) {
|
|
4086
|
-
return "debug";
|
|
4087
|
-
}
|
|
4088
|
-
const env = process.env.EVIDENT_LOG_LEVEL;
|
|
4089
|
-
if (env !== void 0 && env !== "") {
|
|
4090
|
-
return validate(env, " (EVIDENT_LOG_LEVEL)");
|
|
4091
|
-
}
|
|
4092
|
-
return "info";
|
|
4093
|
-
}
|
|
4094
|
-
function meetsThreshold(state, level) {
|
|
4095
|
-
return LOG_LEVELS[level] >= LOG_LEVELS[state.logLevel];
|
|
4096
|
-
}
|
|
4097
|
-
function log2(state, message, level = "info") {
|
|
4098
|
-
if (!meetsThreshold(state, level)) return;
|
|
4065
|
+
function log2(state, message, isError = false) {
|
|
4099
4066
|
if (state.json) {
|
|
4100
4067
|
console.log(
|
|
4101
4068
|
JSON.stringify({
|
|
4102
4069
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4103
|
-
level,
|
|
4070
|
+
level: isError ? "error" : "info",
|
|
4104
4071
|
message
|
|
4105
4072
|
})
|
|
4106
4073
|
);
|
|
4107
4074
|
} else if (!state.interactive) {
|
|
4108
|
-
const prefix =
|
|
4075
|
+
const prefix = isError ? chalk6.red("\u2717") : chalk6.green("\u2022");
|
|
4109
4076
|
console.log(`${prefix} ${message}`);
|
|
4110
4077
|
}
|
|
4111
4078
|
}
|
|
4112
4079
|
function logActivity(state, entry) {
|
|
4113
|
-
const level = entry.level ?? (entry.type === "error" ? "error" : "info");
|
|
4114
|
-
if (!meetsThreshold(state, level)) return;
|
|
4115
4080
|
const fullEntry = {
|
|
4116
4081
|
...entry,
|
|
4117
|
-
level,
|
|
4118
4082
|
timestamp: /* @__PURE__ */ new Date()
|
|
4119
4083
|
};
|
|
4120
4084
|
state.activityLog.push(fullEntry);
|
|
@@ -4123,9 +4087,9 @@ function logActivity(state, entry) {
|
|
|
4123
4087
|
}
|
|
4124
4088
|
if (!state.interactive) {
|
|
4125
4089
|
if (entry.type === "error") {
|
|
4126
|
-
log2(state, entry.error ?? "Unknown error",
|
|
4127
|
-
} else if (entry.message) {
|
|
4128
|
-
log2(state, entry.message
|
|
4090
|
+
log2(state, entry.error ?? "Unknown error", true);
|
|
4091
|
+
} else if (entry.type === "info" && entry.message) {
|
|
4092
|
+
log2(state, entry.message);
|
|
4129
4093
|
}
|
|
4130
4094
|
}
|
|
4131
4095
|
}
|
|
@@ -4324,7 +4288,7 @@ function scheduleSessionCleanup(state, driver, options) {
|
|
|
4324
4288
|
process.env
|
|
4325
4289
|
);
|
|
4326
4290
|
for (const warning2 of config2.warnings) {
|
|
4327
|
-
logActivity(state, { type: "info",
|
|
4291
|
+
logActivity(state, { type: "info", message: `Session cleanup: ${warning2}` });
|
|
4328
4292
|
}
|
|
4329
4293
|
if (!config2.enabled) return;
|
|
4330
4294
|
logActivity(state, {
|
|
@@ -4396,20 +4360,6 @@ async function cleanup(state, opts = {}) {
|
|
|
4396
4360
|
}
|
|
4397
4361
|
async function run(options) {
|
|
4398
4362
|
const interactive = isInteractive(options.json);
|
|
4399
|
-
let logLevel;
|
|
4400
|
-
try {
|
|
4401
|
-
logLevel = resolveLogLevel(options);
|
|
4402
|
-
} catch (error2) {
|
|
4403
|
-
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
4404
|
-
if (options.json) {
|
|
4405
|
-
console.log(JSON.stringify({ status: "error", error: message }));
|
|
4406
|
-
} else {
|
|
4407
|
-
printError(message);
|
|
4408
|
-
}
|
|
4409
|
-
await shutdownTelemetry();
|
|
4410
|
-
process.exit(1);
|
|
4411
|
-
return;
|
|
4412
|
-
}
|
|
4413
4363
|
const state = {
|
|
4414
4364
|
agentId: options.agent || "",
|
|
4415
4365
|
agentName: null,
|
|
@@ -4418,7 +4368,6 @@ async function run(options) {
|
|
|
4418
4368
|
idleTimeout: options.idleTimeout ?? null,
|
|
4419
4369
|
json: options.json ?? false,
|
|
4420
4370
|
interactive,
|
|
4421
|
-
logLevel,
|
|
4422
4371
|
connected: false,
|
|
4423
4372
|
opencodeConnected: false,
|
|
4424
4373
|
opencodeVersion: null,
|
|
@@ -4436,8 +4385,8 @@ async function run(options) {
|
|
|
4436
4385
|
if (state.idleTimeout === null && (process.env.GITHUB_ACTIONS || process.env.CI)) {
|
|
4437
4386
|
log2(
|
|
4438
4387
|
state,
|
|
4439
|
-
"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.",
|
|
4440
|
-
|
|
4388
|
+
"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.",
|
|
4389
|
+
false
|
|
4441
4390
|
);
|
|
4442
4391
|
}
|
|
4443
4392
|
const handleSignal = async () => {
|
|
@@ -4553,9 +4502,9 @@ async function run(options) {
|
|
|
4553
4502
|
ocSpinner?.succeed(`OpenCode running on port ${state.port}${version2}`);
|
|
4554
4503
|
const versionWarning = buildOpenCodeVersionWarning(state.opencodeVersion);
|
|
4555
4504
|
if (versionWarning) {
|
|
4556
|
-
log2(state, versionWarning,
|
|
4505
|
+
log2(state, versionWarning, false);
|
|
4557
4506
|
if (state.interactive && !state.json) {
|
|
4558
|
-
logActivity(state, { type: "info",
|
|
4507
|
+
logActivity(state, { type: "info", message: versionWarning });
|
|
4559
4508
|
}
|
|
4560
4509
|
}
|
|
4561
4510
|
} catch (error2) {
|
|
@@ -4570,17 +4519,11 @@ async function run(options) {
|
|
|
4570
4519
|
getAuthHeader: () => state.authHeader,
|
|
4571
4520
|
conversationFilter: state.conversationFilter,
|
|
4572
4521
|
stuckQueuedMs: CHANNEL_STUCK_QUEUED_MS,
|
|
4573
|
-
log: (entry) => (
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
type: entry.level === "error" ? "error" : "info",
|
|
4579
|
-
level: entry.level,
|
|
4580
|
-
message: entry.message,
|
|
4581
|
-
error: entry.level === "error" ? entry.message : void 0
|
|
4582
|
-
})
|
|
4583
|
-
)
|
|
4522
|
+
log: (entry) => logActivity(state, {
|
|
4523
|
+
type: entry.level === "error" ? "error" : "info",
|
|
4524
|
+
message: entry.message,
|
|
4525
|
+
error: entry.level === "error" ? entry.message : void 0
|
|
4526
|
+
})
|
|
4584
4527
|
});
|
|
4585
4528
|
state.channelDriver = channelDriver;
|
|
4586
4529
|
const connection = new RunnerConnection({
|
|
@@ -4734,10 +4677,7 @@ program.name("evident").description("Run OpenCode locally and connect it to Evid
|
|
|
4734
4677
|
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);
|
|
4735
4678
|
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 }));
|
|
4736
4679
|
program.command("whoami").description("Show the currently logged in user").action(whoami);
|
|
4737
|
-
program.command("run").description("Connect to Evident and process messages").option("-a, --agent [id]", "Agent ID to connect to (optional when EVIDENT_AGENT_KEY is set)").option("-p, --port <port>", "OpenCode port (default: 4096)", "4096").option(
|
|
4738
|
-
"--log-level <level>",
|
|
4739
|
-
"Log verbosity: debug | info | warn | error (default: info). Env: EVIDENT_LOG_LEVEL"
|
|
4740
|
-
).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(
|
|
4680
|
+
program.command("run").description("Connect to Evident and process messages").option("-a, --agent [id]", "Agent ID to connect to (optional when EVIDENT_AGENT_KEY is set)").option("-p, --port <port>", "OpenCode port (default: 4096)", "4096").option("-v, --verbose", "Show detailed request/response information").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(
|
|
4741
4681
|
"--session-cleanup-max-age <duration>",
|
|
4742
4682
|
"Delete OpenCode sessions idle longer than this (e.g. 7d, 24h). Enables cleanup. Env: EVIDENT_SESSION_CLEANUP_MAX_AGE"
|
|
4743
4683
|
).option(
|
|
@@ -4751,9 +4691,6 @@ program.command("run").description("Connect to Evident and process messages").op
|
|
|
4751
4691
|
run({
|
|
4752
4692
|
agent: options.agent,
|
|
4753
4693
|
port: parseInt(options.port, 10),
|
|
4754
|
-
// Raw string — validation/precedence is single-sourced in run.ts's
|
|
4755
|
-
// resolveLogLevel (flag > -v > EVIDENT_LOG_LEVEL > info).
|
|
4756
|
-
logLevel: options.logLevel,
|
|
4757
4694
|
verbose: options.verbose,
|
|
4758
4695
|
conversation: options.conversation,
|
|
4759
4696
|
idleTimeout: options.idleTimeout ? parseInt(options.idleTimeout, 10) : void 0,
|