@evident-ai/cli 3.3.1-dev.181ad3f → 3.3.1-dev.25e01b7

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
@@ -106,10 +106,10 @@ Options:
106
106
  Claude credential is ever read. An unrecognized value falls back to `auto` with
107
107
  a warning. Env: `EVIDENT_CLAUDE_USAGE_REPORTING`.
108
108
  - `--no-resource-usage-reporting` — Don't report this machine's CPU
109
- utilization, total and available memory, and core count to Evident, so it
110
- shows on the runner page. On by default; nothing else about the machine
111
- leaves it. Env: `EVIDENT_RESOURCE_USAGE_REPORTING=off` (the flag wins if
112
- both are set).
109
+ utilization, total and available memory, core count, disk space, and the
110
+ OpenCode session-store size to Evident, so it shows on the runner page. On
111
+ by default; nothing else about the machine leaves it. Env:
112
+ `EVIDENT_RESOURCE_USAGE_REPORTING=off` (the flag wins if both are set).
113
113
  - `--json` — Output in JSON format (forces non-interactive mode).
114
114
  - `--session-cleanup-max-age <duration>` — Delete OpenCode sessions idle longer
115
115
  than this window (format `<number><unit>`, unit one of `s, m, h, d` — e.g.
package/dist/index.js CHANGED
@@ -756,7 +756,10 @@ async function reportResourceUsage(agentId, authHeader, usage) {
756
756
  cpu_percent: usage.cpuPercent,
757
757
  cpu_count: usage.cpuCount,
758
758
  memory_total_bytes: usage.memoryTotalBytes,
759
- memory_available_bytes: usage.memoryAvailableBytes
759
+ memory_available_bytes: usage.memoryAvailableBytes,
760
+ disk_total_bytes: usage.diskTotalBytes,
761
+ disk_free_bytes: usage.diskFreeBytes,
762
+ opencode_db_bytes: usage.opencodeDbBytes
760
763
  }),
761
764
  signal: AbortSignal.timeout(BEST_EFFORT_NOTIFY_TIMEOUT_MS)
762
765
  });
@@ -3061,6 +3064,53 @@ function resolveResourceUsageReportingEnabled(flagValue, env) {
3061
3064
 
3062
3065
  // src/lib/resource-usage.ts
3063
3066
  import { cpus, totalmem, freemem } from "os";
3067
+ import { statfsSync as statfsSync2 } from "fs";
3068
+
3069
+ // src/lib/ecs-task-metadata.ts
3070
+ var ECS_METADATA_TIMEOUT_MS = 2e3;
3071
+ function parseEcsTaskLimits(payload) {
3072
+ if (typeof payload !== "object" || payload === null) return null;
3073
+ const limits = payload.Limits;
3074
+ if (typeof limits !== "object" || limits === null) return null;
3075
+ const cpu = limits.CPU;
3076
+ const memory = limits.Memory;
3077
+ if (typeof cpu !== "number" || !Number.isFinite(cpu) || cpu <= 0) return null;
3078
+ if (typeof memory !== "number" || !Number.isFinite(memory) || memory <= 0) return null;
3079
+ return {
3080
+ cpuCount: Math.max(1, Math.round(cpu)),
3081
+ memoryTotalBytes: memory * 1024 * 1024
3082
+ };
3083
+ }
3084
+ async function readEcsTaskLimits(env) {
3085
+ const uri = env.ECS_CONTAINER_METADATA_URI_V4;
3086
+ if (!uri) {
3087
+ return { limits: null };
3088
+ }
3089
+ const url = `${uri}/task`;
3090
+ try {
3091
+ const response = await fetch(url, { signal: AbortSignal.timeout(ECS_METADATA_TIMEOUT_MS) });
3092
+ if (!response.ok) {
3093
+ return {
3094
+ limits: null,
3095
+ warning: `ECS task metadata fetch (${url}) returned HTTP ${response.status}`
3096
+ };
3097
+ }
3098
+ const payload = await response.json();
3099
+ const limits = parseEcsTaskLimits(payload);
3100
+ if (limits === null) {
3101
+ return {
3102
+ limits: null,
3103
+ warning: `ECS task metadata fetch (${url}) returned an unexpected payload`
3104
+ };
3105
+ }
3106
+ return { limits };
3107
+ } catch (error2) {
3108
+ const message = error2 instanceof Error ? error2.message : String(error2);
3109
+ return { limits: null, warning: `ECS task metadata fetch (${url}) failed: ${message}` };
3110
+ }
3111
+ }
3112
+
3113
+ // src/lib/resource-usage.ts
3064
3114
  function readCpuSample() {
3065
3115
  let busyMs = 0;
3066
3116
  let idleMs = 0;
@@ -3077,17 +3127,66 @@ function cpuPercentBetween(previous, current) {
3077
3127
  if (total === 0) return null;
3078
3128
  return Math.round((deltaBusy / total * 100 + Number.EPSILON) * 100) / 100;
3079
3129
  }
3080
- function createResourceUsageCollector() {
3130
+ function clamp(value, min, max) {
3131
+ return Math.min(Math.max(value, min), max);
3132
+ }
3133
+ function round2(value) {
3134
+ return Math.round((value + Number.EPSILON) * 100) / 100;
3135
+ }
3136
+ function readDisk(homeDir) {
3137
+ try {
3138
+ const stats = statfsSync2(homeDir);
3139
+ return {
3140
+ totalBytes: stats.bsize * stats.blocks,
3141
+ freeBytes: stats.bsize * stats.bavail
3142
+ };
3143
+ } catch (error2) {
3144
+ const message = error2 instanceof Error ? error2.message : String(error2);
3145
+ return {
3146
+ totalBytes: null,
3147
+ freeBytes: null,
3148
+ warning: `Could not read disk usage for ${homeDir}: ${message}`
3149
+ };
3150
+ }
3151
+ }
3152
+ function createResourceUsageCollector(homeDir) {
3081
3153
  let previous = readCpuSample();
3082
- return () => {
3154
+ return async () => {
3083
3155
  const current = readCpuSample();
3084
- const cpuPercent = cpuPercentBetween(previous, current);
3156
+ const hostCpuPercent = cpuPercentBetween(previous, current);
3157
+ const hostCpuCount = cpus().length;
3085
3158
  previous = current;
3159
+ const disk = readDisk(homeDir);
3160
+ const opencodeDbBytes = statSessionDbBytes(homeDir);
3161
+ const { limits, warning: ecsWarning } = await readEcsTaskLimits(process.env);
3162
+ const warnings = [];
3163
+ if (disk.warning) warnings.push(disk.warning);
3164
+ if (ecsWarning) warnings.push(ecsWarning);
3165
+ let cpuPercent = hostCpuPercent;
3166
+ let cpuCount = hostCpuCount;
3167
+ let memoryTotalBytes = totalmem();
3168
+ let memoryAvailableBytes = freemem();
3169
+ if (limits !== null) {
3170
+ cpuCount = limits.cpuCount;
3171
+ memoryTotalBytes = limits.memoryTotalBytes;
3172
+ memoryAvailableBytes = clamp(
3173
+ limits.memoryTotalBytes - (totalmem() - freemem()),
3174
+ 0,
3175
+ limits.memoryTotalBytes
3176
+ );
3177
+ cpuPercent = hostCpuPercent === null ? null : clamp(round2(hostCpuPercent * hostCpuCount / limits.cpuCount), 0, 100);
3178
+ }
3086
3179
  return {
3087
- cpuPercent,
3088
- cpuCount: cpus().length,
3089
- memoryTotalBytes: totalmem(),
3090
- memoryAvailableBytes: freemem()
3180
+ usage: {
3181
+ cpuPercent,
3182
+ cpuCount,
3183
+ memoryTotalBytes,
3184
+ memoryAvailableBytes,
3185
+ diskTotalBytes: disk.totalBytes,
3186
+ diskFreeBytes: disk.freeBytes,
3187
+ opencodeDbBytes
3188
+ },
3189
+ warnings
3091
3190
  };
3092
3191
  };
3093
3192
  }
@@ -7993,11 +8092,18 @@ function scheduleResourceUsageReporting(state, options) {
7993
8092
  });
7994
8093
  return;
7995
8094
  }
7996
- const collect = createResourceUsageCollector();
8095
+ const collect = createResourceUsageCollector(homedir3());
7997
8096
  let consecutiveFailures = 0;
7998
8097
  const tick = async () => {
7999
8098
  try {
8000
- const usage = collect();
8099
+ const { usage, warnings: collectWarnings } = await collect();
8100
+ for (const warning2 of collectWarnings) {
8101
+ logActivity(state, {
8102
+ type: "info",
8103
+ level: "debug",
8104
+ message: `Resource usage collection: ${warning2}`
8105
+ });
8106
+ }
8001
8107
  const result = await reportResourceUsage(state.agentId, state.authHeader, usage);
8002
8108
  if (result.ok) {
8003
8109
  if (consecutiveFailures > 0) {