@evident-ai/cli 3.0.1-dev.bf0949e → 3.0.1-dev.bf495ea

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 CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import { createRequire } from "module";
4
5
  import { Command } from "commander";
5
6
 
6
7
  // src/commands/login.ts
@@ -490,6 +491,29 @@ var TelemetryEventTypes = {
490
491
  var MAX_FRAME_BYTES = 256 * 1024;
491
492
  var TUNNEL_DRAIN_PING_PATH = "/__evident/drain";
492
493
 
494
+ // ../../packages/types/src/logging/index.ts
495
+ var CORRELATION_ID_HEADER = "x-evident-correlation-id";
496
+ function log(level, event, fields) {
497
+ const method = level === "debug" ? "log" : level;
498
+ try {
499
+ console[method]("[evident]", JSON.stringify({ level, event, ...fields }));
500
+ } catch (err) {
501
+ console.error(
502
+ "[evident] log_serialize_failed",
503
+ event,
504
+ err instanceof Error ? err.message : String(err)
505
+ );
506
+ }
507
+ }
508
+ function stripQuery(url) {
509
+ try {
510
+ return new URL(url).pathname;
511
+ } catch {
512
+ const q = url.indexOf("?");
513
+ return q === -1 ? url : url.slice(0, q);
514
+ }
515
+ }
516
+
493
517
  // src/lib/telemetry.ts
494
518
  var CLI_VERSION = process.env.npm_package_version || "unknown";
495
519
  var eventBuffer = [];
@@ -692,13 +716,13 @@ async function waitForOpenCodeHealth(port, timeoutMs = 3e4) {
692
716
 
693
717
  // src/lib/opencode/opencode-version-gate.ts
694
718
  var QUEUE_VALIDATED_OPENCODE_VERSIONS = ["1.17.11"];
695
- function isQueueValidatedVersion(version) {
696
- if (!version) return false;
697
- return QUEUE_VALIDATED_OPENCODE_VERSIONS.includes(version);
719
+ function isQueueValidatedVersion(version2) {
720
+ if (!version2) return false;
721
+ return QUEUE_VALIDATED_OPENCODE_VERSIONS.includes(version2);
698
722
  }
699
- function buildOpenCodeVersionWarning(version) {
700
- if (isQueueValidatedVersion(version)) return null;
701
- const detected = version ? `v${version}` : "unknown";
723
+ function buildOpenCodeVersionWarning(version2) {
724
+ if (isQueueValidatedVersion(version2)) return null;
725
+ const detected = version2 ? `v${version2}` : "unknown";
702
726
  const validated = QUEUE_VALIDATED_OPENCODE_VERSIONS.map((v) => `v${v}`).join(", ");
703
727
  return `Warning: opencode ${detected} is not a queue-validated version (validated: ${validated}). Native message queuing \u2014 which channel (Slack/WhatsApp) message handling relies on \u2014 is unverified on this version; queued/follow-up messages may behave unexpectedly. Continuing anyway. Bumping the validated set requires re-running the queue validation.`;
704
728
  }
@@ -1192,12 +1216,20 @@ var StreamForwarder = class {
1192
1216
  }
1193
1217
  async handleOpen(frame) {
1194
1218
  const { sid, method, path, headers, has_body } = frame;
1219
+ const correlationId = headers?.[CORRELATION_ID_HEADER];
1220
+ const startedAt = Date.now();
1195
1221
  if (path === TUNNEL_DRAIN_PING_PATH) {
1196
1222
  this.callbacks.onDrainPing?.();
1197
1223
  this.send({ type: "head", sid, status: 204, headers: {} });
1198
1224
  this.send({ type: "res_end", sid });
1199
1225
  return;
1200
1226
  }
1227
+ log("info", "agent_request", {
1228
+ correlation_id: correlationId,
1229
+ sid,
1230
+ method,
1231
+ path: stripQuery(path)
1232
+ });
1201
1233
  const ac = new AbortController();
1202
1234
  let bodyPromise;
1203
1235
  let pushBody;
@@ -1244,6 +1276,12 @@ var StreamForwarder = class {
1244
1276
  if (!STRIP_RES.has(key.toLowerCase())) resHeaders[key] = value;
1245
1277
  });
1246
1278
  this.send({ type: "head", sid, status: upstream.status, headers: resHeaders });
1279
+ log("info", "agent_response", {
1280
+ correlation_id: correlationId,
1281
+ sid,
1282
+ status: upstream.status,
1283
+ duration_ms: Date.now() - startedAt
1284
+ });
1247
1285
  this.callbacks.onHead?.(sid, upstream.status);
1248
1286
  try {
1249
1287
  if (upstream.body) {
@@ -2535,7 +2573,7 @@ async function getAgentInfo(agentId, authHeader) {
2535
2573
  // src/commands/run.ts
2536
2574
  var MAX_ACTIVITY_LOG_ENTRIES = 10;
2537
2575
  var CHANNEL_POLL_INTERVAL_MS = Number(process.env.EVIDENT_CHANNEL_POLL_INTERVAL_MS) || 2e3;
2538
- function log(state, message, isError = false) {
2576
+ function log2(state, message, isError = false) {
2539
2577
  if (state.json) {
2540
2578
  console.log(
2541
2579
  JSON.stringify({
@@ -2560,9 +2598,9 @@ function logActivity(state, entry) {
2560
2598
  }
2561
2599
  if (!state.interactive) {
2562
2600
  if (entry.type === "error") {
2563
- log(state, entry.error ?? "Unknown error", true);
2601
+ log2(state, entry.error ?? "Unknown error", true);
2564
2602
  } else if (entry.type === "info" && entry.message) {
2565
- log(state, entry.message);
2603
+ log2(state, entry.message);
2566
2604
  }
2567
2605
  }
2568
2606
  }
@@ -2648,6 +2686,7 @@ async function handleAuthError(state, error2) {
2648
2686
  }
2649
2687
  async function driveChannels(state, driver) {
2650
2688
  let idlePolls = 0;
2689
+ let lastSeenProxiedActivityAt = state.lastProxiedActivityAt;
2651
2690
  while (state.running) {
2652
2691
  if (state.connection?.reconnecting && state.connection.reconnectPromise) {
2653
2692
  logActivity(state, { type: "info", message: "Waiting for tunnel reconnection..." });
@@ -2657,7 +2696,9 @@ async function driveChannels(state, driver) {
2657
2696
  try {
2658
2697
  const processed = await driver.drainPending();
2659
2698
  state.messageCount += processed;
2660
- if (processed > 0 || driver.hasInFlightWatchers()) {
2699
+ const proxiedActivity = state.lastProxiedActivityAt !== lastSeenProxiedActivityAt;
2700
+ lastSeenProxiedActivityAt = state.lastProxiedActivityAt;
2701
+ if (processed > 0 || driver.hasInFlightWatchers() || proxiedActivity) {
2661
2702
  idlePolls = 0;
2662
2703
  if (processed > 0 && state.interactive) displayStatus(state);
2663
2704
  } else if (state.idleTimeout !== null) {
@@ -2709,7 +2750,7 @@ async function cleanup(state) {
2709
2750
  logActivity(state, { type: "info", message: "Stopped OpenCode process" });
2710
2751
  displayStatus(state);
2711
2752
  } else {
2712
- log(state, "Stopped OpenCode process");
2753
+ log2(state, "Stopped OpenCode process");
2713
2754
  }
2714
2755
  state.opencodeProcess = null;
2715
2756
  }
@@ -2732,10 +2773,11 @@ async function run(options) {
2732
2773
  running: true,
2733
2774
  activityLog: [],
2734
2775
  messageCount: 0,
2776
+ lastProxiedActivityAt: null,
2735
2777
  authHeader: ""
2736
2778
  };
2737
2779
  if (state.idleTimeout === null && (process.env.GITHUB_ACTIONS || process.env.CI)) {
2738
- log(
2780
+ log2(
2739
2781
  state,
2740
2782
  "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.",
2741
2783
  false
@@ -2746,7 +2788,7 @@ async function run(options) {
2746
2788
  logActivity(state, { type: "info", message: "Shutting down..." });
2747
2789
  displayStatus(state);
2748
2790
  } else {
2749
- log(state, "Shutting down...");
2791
+ log2(state, "Shutting down...");
2750
2792
  }
2751
2793
  await cleanup(state);
2752
2794
  await shutdownTelemetry();
@@ -2779,7 +2821,7 @@ async function run(options) {
2779
2821
  const resolved = await resolveAgentIdFromKey(state.authHeader);
2780
2822
  if (resolved.agent_id) {
2781
2823
  state.agentId = resolved.agent_id;
2782
- log(state, `Resolved agent ID from key: ${state.agentId}`);
2824
+ log2(state, `Resolved agent ID from key: ${state.agentId}`);
2783
2825
  if (state.interactive && !state.json) {
2784
2826
  logActivity(state, {
2785
2827
  type: "info",
@@ -2842,17 +2884,17 @@ async function run(options) {
2842
2884
  port: state.port,
2843
2885
  interactive: state.interactive,
2844
2886
  agentId: state.agentId,
2845
- log: (message) => log(state, message)
2887
+ log: (message) => log2(state, message)
2846
2888
  });
2847
2889
  state.port = oc.port;
2848
2890
  state.opencodeProcess = oc.process;
2849
2891
  state.opencodeVersion = oc.version;
2850
2892
  state.opencodeConnected = oc.process !== null || oc.version !== null;
2851
- const version = state.opencodeVersion ? ` (v${state.opencodeVersion})` : "";
2852
- ocSpinner?.succeed(`OpenCode running on port ${state.port}${version}`);
2893
+ const version2 = state.opencodeVersion ? ` (v${state.opencodeVersion})` : "";
2894
+ ocSpinner?.succeed(`OpenCode running on port ${state.port}${version2}`);
2853
2895
  const versionWarning = buildOpenCodeVersionWarning(state.opencodeVersion);
2854
2896
  if (versionWarning) {
2855
- log(state, versionWarning, false);
2897
+ log2(state, versionWarning, false);
2856
2898
  if (state.interactive && !state.json) {
2857
2899
  logActivity(state, { type: "info", message: versionWarning });
2858
2900
  }
@@ -2921,9 +2963,14 @@ async function run(options) {
2921
2963
  logActivity(state, { type: "error", error: error2 });
2922
2964
  if (state.interactive) displayStatus(state);
2923
2965
  },
2924
- // Web traffic is proxied transparently; only note opencode is live.
2966
+ // Web traffic is proxied transparently; note opencode is live and stamp
2967
+ // proxied activity so the idle loop treats interactive proxy use as work.
2968
+ // Fires per forwarded response head (incl. every SSE open) and excludes
2969
+ // the internal drain-ping, so an actively-used proxy keeps the timer
2970
+ // fresh while a lone idle SSE with no follow-up requests still ages out.
2925
2971
  onResponse: () => {
2926
2972
  state.opencodeConnected = true;
2973
+ state.lastProxiedActivityAt = Date.now();
2927
2974
  },
2928
2975
  // A channel message was queued and the api-worker pinged us over the
2929
2976
  // tunnel to drain immediately instead of waiting for the next poll tick.
@@ -2962,7 +3009,7 @@ async function run(options) {
2962
3009
  throw error2;
2963
3010
  }
2964
3011
  if (!interactive || state.json) {
2965
- log(state, "Driving channel messages...");
3012
+ log2(state, "Driving channel messages...");
2966
3013
  }
2967
3014
  await driveChannels(state, channelDriver);
2968
3015
  await cleanup(state);
@@ -2974,7 +3021,7 @@ async function run(options) {
2974
3021
  })
2975
3022
  );
2976
3023
  } else if (!interactive) {
2977
- log(state, `Completed. Processed ${state.messageCount} message(s).`);
3024
+ log2(state, `Completed. Processed ${state.messageCount} message(s).`);
2978
3025
  }
2979
3026
  await shutdownTelemetry();
2980
3027
  process.exit(0);
@@ -2996,8 +3043,9 @@ async function run(options) {
2996
3043
  }
2997
3044
 
2998
3045
  // src/index.ts
3046
+ var { version } = createRequire(import.meta.url)("../package.json");
2999
3047
  var program = new Command();
3000
- program.name("evident").description("Run OpenCode locally and connect it to Evident").version("0.1.0").option(
3048
+ program.name("evident").description("Run OpenCode locally and connect it to Evident").version(version).option(
3001
3049
  "--endpoint <url>",
3002
3050
  "Evident API base URL (default: production; e.g. http://localhost:3001)"
3003
3051
  ).option("--tunnel <url>", "Tunnel WebSocket URL (default: production; e.g. ws://localhost:8787)").hook("preAction", (thisCommand) => {