@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 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
- - `--log-level <level>`Log verbosity: `debug | info | warn | error` (default:
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: "warn",
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: "warn",
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: "warn",
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: "debug",
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: "warn",
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: "warn",
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: "debug",
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: "warn",
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: "warn",
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: "warn",
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: "warn",
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: "warn",
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: "warn",
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: "warn",
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: "debug",
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: "debug",
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: "warn",
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: "warn",
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: "warn",
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: "warn",
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: "debug",
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: "debug",
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: "warn",
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: "warn",
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: "warn",
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: "warn",
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: "debug",
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: "debug",
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: "debug",
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: "debug",
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: "debug",
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: "debug",
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: "debug",
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: "debug",
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: "debug",
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: "warn",
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: "warn",
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: "debug",
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: "debug",
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: "debug",
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: "warn",
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: "warn",
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: "warn",
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 resolveLogLevel(options) {
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 = level === "error" ? chalk6.red("\u2717") : level === "warn" ? chalk6.yellow("!") : level === "debug" ? chalk6.dim("\xB7") : chalk6.green("\u2022");
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", level);
4127
- } else if (entry.message) {
4128
- log2(state, entry.message, level);
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", level: "warn", message: `Session cleanup: ${warning2}` });
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
- "warn"
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, "warn");
4505
+ log2(state, versionWarning, false);
4557
4506
  if (state.interactive && !state.json) {
4558
- logActivity(state, { type: "info", level: "warn", message: versionWarning });
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
- // Thread the driver's real level straight through so `debug`/`warn`
4575
- // survive the sink filter (they no longer collapse to info). `type`
4576
- // stays the coarse error/non-error split the activity log renders with.
4577
- logActivity(state, {
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,