@evident-ai/cli 3.3.1-dev.dd703c3 → 3.4.0
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 +8 -0
- package/dist/index.js +311 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -105,6 +105,11 @@ Options:
|
|
|
105
105
|
keeps retrying) if no usable login is found; `off` disables it entirely — no
|
|
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
|
+
- `--no-resource-usage-reporting` — Don't report this machine's CPU
|
|
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).
|
|
108
113
|
- `--json` — Output in JSON format (forces non-interactive mode).
|
|
109
114
|
- `--session-cleanup-max-age <duration>` — Delete OpenCode sessions idle longer
|
|
110
115
|
than this window (format `<number><unit>`, unit one of `s, m, h, d` — e.g.
|
|
@@ -171,6 +176,9 @@ targets the **production** Evident platform by default.
|
|
|
171
176
|
- `EVIDENT_TUNNEL_URL` — Override the tunnel relay URL (equivalent to `--tunnel`).
|
|
172
177
|
- `EVIDENT_CLAUDE_USAGE_REPORTING` — Equivalent to `--claude-usage-reporting`; the
|
|
173
178
|
flag wins if both are set.
|
|
179
|
+
- `EVIDENT_RESOURCE_USAGE_REPORTING` — Equivalent to
|
|
180
|
+
`--no-resource-usage-reporting`; set it to `off` to disable. The flag wins
|
|
181
|
+
if both are set.
|
|
174
182
|
- `EVIDENT_LOG_LEVEL` — Equivalent to `--log-level`; the flag wins if both are
|
|
175
183
|
set, and `-v`/`--verbose` also outranks this env var.
|
|
176
184
|
- `EVIDENT_OPENCODE_START_TIMEOUT` — Equivalent to `--opencode-start-timeout`
|
package/dist/index.js
CHANGED
|
@@ -746,6 +746,35 @@ async function reportClaudeUsage(agentId, authHeader, snapshot) {
|
|
|
746
746
|
return { ok: false, error: describeBestEffortError(error2) };
|
|
747
747
|
}
|
|
748
748
|
}
|
|
749
|
+
async function reportResourceUsage(agentId, authHeader, usage) {
|
|
750
|
+
try {
|
|
751
|
+
const apiUrl = getApiUrlConfig();
|
|
752
|
+
const response = await fetch(`${apiUrl}/runners/${agentId}/resource-usage`, {
|
|
753
|
+
method: "POST",
|
|
754
|
+
headers: { Authorization: authHeader, "Content-Type": "application/json" },
|
|
755
|
+
body: JSON.stringify({
|
|
756
|
+
cpu_percent: usage.cpuPercent,
|
|
757
|
+
cpu_count: usage.cpuCount,
|
|
758
|
+
memory_total_bytes: usage.memoryTotalBytes,
|
|
759
|
+
memory_available_bytes: usage.memoryAvailableBytes,
|
|
760
|
+
disk_total_bytes: usage.diskTotalBytes,
|
|
761
|
+
disk_free_bytes: usage.diskFreeBytes,
|
|
762
|
+
opencode_db_bytes: usage.opencodeDbBytes
|
|
763
|
+
}),
|
|
764
|
+
signal: AbortSignal.timeout(BEST_EFFORT_NOTIFY_TIMEOUT_MS)
|
|
765
|
+
});
|
|
766
|
+
if (!response.ok) {
|
|
767
|
+
const serverMessage = await readErrorMessage(response);
|
|
768
|
+
return {
|
|
769
|
+
ok: false,
|
|
770
|
+
error: `HTTP ${response.status}${serverMessage ? `: ${serverMessage}` : ""}`
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
return { ok: true };
|
|
774
|
+
} catch (error2) {
|
|
775
|
+
return { ok: false, error: describeBestEffortError(error2) };
|
|
776
|
+
}
|
|
777
|
+
}
|
|
749
778
|
async function getAgentInfo(agentId, authHeader) {
|
|
750
779
|
const apiUrl = getApiUrlConfig();
|
|
751
780
|
try {
|
|
@@ -2962,6 +2991,21 @@ function writeTunnelReadyMarker(path, agentId) {
|
|
|
2962
2991
|
}
|
|
2963
2992
|
}
|
|
2964
2993
|
|
|
2994
|
+
// src/lib/reporting-schedule.ts
|
|
2995
|
+
function jitteredDelayMs(baseMs, jitterFraction, random = Math.random) {
|
|
2996
|
+
const jitterRangeMs = baseMs * jitterFraction;
|
|
2997
|
+
return baseMs - jitterRangeMs + random() * (2 * jitterRangeMs);
|
|
2998
|
+
}
|
|
2999
|
+
function firstReportDelayMs(random = Math.random) {
|
|
3000
|
+
return 5e3 + random() * 1e4;
|
|
3001
|
+
}
|
|
3002
|
+
function reportFailureLogLevel(consecutiveFailures, reescalationTicks) {
|
|
3003
|
+
return consecutiveFailures === 1 || consecutiveFailures % reescalationTicks === 0 ? "warn" : "debug";
|
|
3004
|
+
}
|
|
3005
|
+
function failureStreakSuffix(consecutiveFailures) {
|
|
3006
|
+
return consecutiveFailures > 1 ? ` (${consecutiveFailures} consecutive failures)` : "";
|
|
3007
|
+
}
|
|
3008
|
+
|
|
2965
3009
|
// src/lib/claude-usage-reporting.ts
|
|
2966
3010
|
var VALID_MODES = ["auto", "on", "off"];
|
|
2967
3011
|
function resolveClaudeUsageReportingMode(flagValue, env) {
|
|
@@ -2984,13 +3028,167 @@ function resolveClaudeUsageReportingMode(flagValue, env) {
|
|
|
2984
3028
|
var BASE_REPORT_DELAY_MS = 10 * 6e4;
|
|
2985
3029
|
var REPORT_DELAY_JITTER_FRACTION = 0.2;
|
|
2986
3030
|
function nextReportDelayMs(random = Math.random) {
|
|
2987
|
-
|
|
2988
|
-
return BASE_REPORT_DELAY_MS - jitterRangeMs + random() * (2 * jitterRangeMs);
|
|
3031
|
+
return jitteredDelayMs(BASE_REPORT_DELAY_MS, REPORT_DELAY_JITTER_FRACTION, random);
|
|
2989
3032
|
}
|
|
2990
|
-
var FIRST_REPORT_DELAY_MS =
|
|
3033
|
+
var FIRST_REPORT_DELAY_MS = firstReportDelayMs();
|
|
2991
3034
|
var CLAUDE_USAGE_FAILURE_REESCALATION_TICKS = 6;
|
|
2992
3035
|
function claudeUsageFailureLogLevel(consecutiveFailures) {
|
|
2993
|
-
return consecutiveFailures
|
|
3036
|
+
return reportFailureLogLevel(consecutiveFailures, CLAUDE_USAGE_FAILURE_REESCALATION_TICKS);
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
// src/lib/resource-usage-reporting.ts
|
|
3040
|
+
var ENABLED_VALUES = /* @__PURE__ */ new Set(["on", "true", "1"]);
|
|
3041
|
+
var DISABLED_VALUES = /* @__PURE__ */ new Set(["off", "false", "0"]);
|
|
3042
|
+
function resolveResourceUsageReportingEnabled(flagValue, env) {
|
|
3043
|
+
if (flagValue === false) {
|
|
3044
|
+
return { enabled: false, warnings: [] };
|
|
3045
|
+
}
|
|
3046
|
+
const raw = env.EVIDENT_RESOURCE_USAGE_REPORTING;
|
|
3047
|
+
if (raw === void 0 || raw === "") {
|
|
3048
|
+
return { enabled: true, warnings: [] };
|
|
3049
|
+
}
|
|
3050
|
+
const normalized = raw.trim().toLowerCase();
|
|
3051
|
+
if (DISABLED_VALUES.has(normalized)) {
|
|
3052
|
+
return { enabled: false, warnings: [] };
|
|
3053
|
+
}
|
|
3054
|
+
if (ENABLED_VALUES.has(normalized)) {
|
|
3055
|
+
return { enabled: true, warnings: [] };
|
|
3056
|
+
}
|
|
3057
|
+
return {
|
|
3058
|
+
enabled: true,
|
|
3059
|
+
warnings: [
|
|
3060
|
+
`Ignoring invalid EVIDENT_RESOURCE_USAGE_REPORTING "${raw}": expected on or off; leaving reporting on`
|
|
3061
|
+
]
|
|
3062
|
+
};
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
// src/lib/resource-usage.ts
|
|
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
|
|
3114
|
+
function readCpuSample() {
|
|
3115
|
+
let busyMs = 0;
|
|
3116
|
+
let idleMs = 0;
|
|
3117
|
+
for (const cpu of cpus()) {
|
|
3118
|
+
busyMs += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.irq;
|
|
3119
|
+
idleMs += cpu.times.idle;
|
|
3120
|
+
}
|
|
3121
|
+
return { busyMs, idleMs };
|
|
3122
|
+
}
|
|
3123
|
+
function cpuPercentBetween(previous, current) {
|
|
3124
|
+
const deltaBusy = current.busyMs - previous.busyMs;
|
|
3125
|
+
const deltaIdle = current.idleMs - previous.idleMs;
|
|
3126
|
+
const total = deltaBusy + deltaIdle;
|
|
3127
|
+
if (total === 0) return null;
|
|
3128
|
+
return Math.round((deltaBusy / total * 100 + Number.EPSILON) * 100) / 100;
|
|
3129
|
+
}
|
|
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) {
|
|
3153
|
+
let previous = readCpuSample();
|
|
3154
|
+
return async () => {
|
|
3155
|
+
const current = readCpuSample();
|
|
3156
|
+
const hostCpuPercent = cpuPercentBetween(previous, current);
|
|
3157
|
+
const hostCpuCount = cpus().length;
|
|
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
|
+
}
|
|
3179
|
+
return {
|
|
3180
|
+
usage: {
|
|
3181
|
+
cpuPercent,
|
|
3182
|
+
cpuCount,
|
|
3183
|
+
memoryTotalBytes,
|
|
3184
|
+
memoryAvailableBytes,
|
|
3185
|
+
diskTotalBytes: disk.totalBytes,
|
|
3186
|
+
diskFreeBytes: disk.freeBytes,
|
|
3187
|
+
opencodeDbBytes
|
|
3188
|
+
},
|
|
3189
|
+
warnings
|
|
3190
|
+
};
|
|
3191
|
+
};
|
|
2994
3192
|
}
|
|
2995
3193
|
|
|
2996
3194
|
// src/lib/channels/driver.ts
|
|
@@ -4851,6 +5049,17 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
4851
5049
|
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.`,
|
|
4852
5050
|
conversation_id: conv.id
|
|
4853
5051
|
});
|
|
5052
|
+
const watcher = this.watchers.get(bound);
|
|
5053
|
+
if (watcher) {
|
|
5054
|
+
for (const [evidentMessageId, inFlight] of [...watcher.inFlight]) {
|
|
5055
|
+
this.recordReleasedOpencodeId(evidentMessageId, bound, inFlight.opencodeMessageId);
|
|
5056
|
+
this.removeInFlight(watcher, evidentMessageId);
|
|
5057
|
+
void this.postSignal(watcher.conv.id, evidentMessageId, "watcher_recovered", {
|
|
5058
|
+
recovery: "session_gone_released"
|
|
5059
|
+
});
|
|
5060
|
+
}
|
|
5061
|
+
this.watchers.delete(bound);
|
|
5062
|
+
}
|
|
4854
5063
|
this.sessions.delete(conv.id);
|
|
4855
5064
|
return { sessionId: await this.createAndBindSession(conv.id), created: true };
|
|
4856
5065
|
}
|
|
@@ -7735,9 +7944,6 @@ function scheduleSessionCleanup(state, driver, options) {
|
|
|
7735
7944
|
);
|
|
7736
7945
|
state.sessionCleanupTimers.push(interval, firstSweep);
|
|
7737
7946
|
}
|
|
7738
|
-
function claudeUsageFailureStreakSuffix(consecutiveFailures) {
|
|
7739
|
-
return consecutiveFailures > 1 ? ` (${consecutiveFailures} consecutive failures)` : "";
|
|
7740
|
-
}
|
|
7741
7947
|
function scheduleClaudeUsageReporting(state, options) {
|
|
7742
7948
|
const { mode, warnings } = resolveClaudeUsageReportingMode(
|
|
7743
7949
|
options.claudeUsageReporting,
|
|
@@ -7819,7 +8025,7 @@ function scheduleClaudeUsageReporting(state, options) {
|
|
|
7819
8025
|
logActivity(state, {
|
|
7820
8026
|
type: "info",
|
|
7821
8027
|
level: claudeUsageFailureLogLevel(consecutiveFailures),
|
|
7822
|
-
message: `Failed to report Claude usage: ${result.error}${
|
|
8028
|
+
message: `Failed to report Claude usage: ${result.error}${failureStreakSuffix(consecutiveFailures)}`
|
|
7823
8029
|
});
|
|
7824
8030
|
}
|
|
7825
8031
|
scheduleNextTick();
|
|
@@ -7854,7 +8060,7 @@ function scheduleClaudeUsageReporting(state, options) {
|
|
|
7854
8060
|
logActivity(state, {
|
|
7855
8061
|
type: "info",
|
|
7856
8062
|
level: claudeUsageFailureLogLevel(consecutiveFailures),
|
|
7857
|
-
message: `Claude usage reporting failed: ${message}${
|
|
8063
|
+
message: `Claude usage reporting failed: ${message}${failureStreakSuffix(consecutiveFailures)}`
|
|
7858
8064
|
});
|
|
7859
8065
|
scheduleNextTick();
|
|
7860
8066
|
}
|
|
@@ -7863,6 +8069,90 @@ function scheduleClaudeUsageReporting(state, options) {
|
|
|
7863
8069
|
armProbe();
|
|
7864
8070
|
return rearm;
|
|
7865
8071
|
}
|
|
8072
|
+
var RESOURCE_USAGE_BASE_REPORT_DELAY_MS = 10 * 6e4;
|
|
8073
|
+
var RESOURCE_USAGE_REPORT_DELAY_JITTER_FRACTION = 0.2;
|
|
8074
|
+
var RESOURCE_USAGE_FAILURE_REESCALATION_TICKS = 6;
|
|
8075
|
+
function scheduleResourceUsageReporting(state, options) {
|
|
8076
|
+
const { enabled, warnings } = resolveResourceUsageReportingEnabled(
|
|
8077
|
+
options.resourceUsageReporting,
|
|
8078
|
+
process.env
|
|
8079
|
+
);
|
|
8080
|
+
for (const warning2 of warnings) {
|
|
8081
|
+
logActivity(state, {
|
|
8082
|
+
type: "info",
|
|
8083
|
+
level: "warn",
|
|
8084
|
+
message: `Resource usage reporting: ${warning2}`
|
|
8085
|
+
});
|
|
8086
|
+
}
|
|
8087
|
+
if (!enabled) {
|
|
8088
|
+
logActivity(state, {
|
|
8089
|
+
type: "info",
|
|
8090
|
+
level: "debug",
|
|
8091
|
+
message: "Resource usage reporting is off (--no-resource-usage-reporting)"
|
|
8092
|
+
});
|
|
8093
|
+
return;
|
|
8094
|
+
}
|
|
8095
|
+
const collect = createResourceUsageCollector(homedir3());
|
|
8096
|
+
let consecutiveFailures = 0;
|
|
8097
|
+
const tick = async () => {
|
|
8098
|
+
try {
|
|
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
|
+
}
|
|
8107
|
+
const result = await reportResourceUsage(state.agentId, state.authHeader, usage);
|
|
8108
|
+
if (result.ok) {
|
|
8109
|
+
if (consecutiveFailures > 0) {
|
|
8110
|
+
logActivity(state, {
|
|
8111
|
+
type: "info",
|
|
8112
|
+
level: "info",
|
|
8113
|
+
message: "Resource usage reporting recovered"
|
|
8114
|
+
});
|
|
8115
|
+
}
|
|
8116
|
+
consecutiveFailures = 0;
|
|
8117
|
+
logActivity(state, {
|
|
8118
|
+
type: "info",
|
|
8119
|
+
level: "debug",
|
|
8120
|
+
message: "Reported resource usage to Evident"
|
|
8121
|
+
});
|
|
8122
|
+
} else {
|
|
8123
|
+
consecutiveFailures++;
|
|
8124
|
+
logActivity(state, {
|
|
8125
|
+
type: "info",
|
|
8126
|
+
level: reportFailureLogLevel(
|
|
8127
|
+
consecutiveFailures,
|
|
8128
|
+
RESOURCE_USAGE_FAILURE_REESCALATION_TICKS
|
|
8129
|
+
),
|
|
8130
|
+
message: `Failed to report resource usage: ${result.error}${failureStreakSuffix(consecutiveFailures)}`
|
|
8131
|
+
});
|
|
8132
|
+
}
|
|
8133
|
+
} catch (error2) {
|
|
8134
|
+
consecutiveFailures++;
|
|
8135
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
8136
|
+
logActivity(state, {
|
|
8137
|
+
type: "info",
|
|
8138
|
+
level: reportFailureLogLevel(
|
|
8139
|
+
consecutiveFailures,
|
|
8140
|
+
RESOURCE_USAGE_FAILURE_REESCALATION_TICKS
|
|
8141
|
+
),
|
|
8142
|
+
message: `Resource usage reporting failed: ${message}${failureStreakSuffix(consecutiveFailures)}`
|
|
8143
|
+
});
|
|
8144
|
+
} finally {
|
|
8145
|
+
state.resourceUsageTimer = setTimeout(
|
|
8146
|
+
() => void tick(),
|
|
8147
|
+
jitteredDelayMs(
|
|
8148
|
+
RESOURCE_USAGE_BASE_REPORT_DELAY_MS,
|
|
8149
|
+
RESOURCE_USAGE_REPORT_DELAY_JITTER_FRACTION
|
|
8150
|
+
)
|
|
8151
|
+
);
|
|
8152
|
+
}
|
|
8153
|
+
};
|
|
8154
|
+
state.resourceUsageTimer = setTimeout(() => void tick(), firstReportDelayMs());
|
|
8155
|
+
}
|
|
7866
8156
|
async function notifyOffline(state) {
|
|
7867
8157
|
if (!state.agentId || !state.authHeader) return;
|
|
7868
8158
|
if (!state.connected) {
|
|
@@ -7903,6 +8193,10 @@ async function cleanup(state, opts = {}) {
|
|
|
7903
8193
|
state.claudeUsageTimer = null;
|
|
7904
8194
|
}
|
|
7905
8195
|
state.claudeUsageRearm = null;
|
|
8196
|
+
if (state.resourceUsageTimer) {
|
|
8197
|
+
clearTimeout(state.resourceUsageTimer);
|
|
8198
|
+
state.resourceUsageTimer = null;
|
|
8199
|
+
}
|
|
7906
8200
|
if (opts.graceful && state.channelDriver) {
|
|
7907
8201
|
state.channelDriver.stop();
|
|
7908
8202
|
log2(state, "Draining in-flight channel work before shutdown...");
|
|
@@ -7985,6 +8279,7 @@ async function run(options) {
|
|
|
7985
8279
|
sessionCleanupTimers: [],
|
|
7986
8280
|
claudeUsageTimer: null,
|
|
7987
8281
|
claudeUsageRearm: null,
|
|
8282
|
+
resourceUsageTimer: null,
|
|
7988
8283
|
authHeader: ""
|
|
7989
8284
|
};
|
|
7990
8285
|
setTelemetryAuthProvider(() => ({ authHeader: state.authHeader, agentId: state.agentId }));
|
|
@@ -8384,6 +8679,7 @@ async function run(options) {
|
|
|
8384
8679
|
}
|
|
8385
8680
|
scheduleSessionCleanup(state, channelDriver, options);
|
|
8386
8681
|
state.claudeUsageRearm = scheduleClaudeUsageReporting(state, options);
|
|
8682
|
+
scheduleResourceUsageReporting(state, options);
|
|
8387
8683
|
if (!interactive || state.json) {
|
|
8388
8684
|
log2(state, "Driving channel messages...");
|
|
8389
8685
|
}
|
|
@@ -8464,6 +8760,9 @@ program.command("run").description("Connect to Evident and process messages").op
|
|
|
8464
8760
|
).option(
|
|
8465
8761
|
"--claude-usage-reporting <mode>",
|
|
8466
8762
|
"Report Claude subscription usage to Evident: auto | on | off (default: auto). Env: EVIDENT_CLAUDE_USAGE_REPORTING"
|
|
8763
|
+
).option(
|
|
8764
|
+
"--no-resource-usage-reporting",
|
|
8765
|
+
"Don't report this machine's CPU and memory usage to Evident (reporting is on by default). Env: EVIDENT_RESOURCE_USAGE_REPORTING=off"
|
|
8467
8766
|
).option(
|
|
8468
8767
|
"--enable-file-sync-to <dir>",
|
|
8469
8768
|
"Allow Evident to write files into this directory (repeatable). Omit to disable file sync entirely.",
|
|
@@ -8496,6 +8795,9 @@ program.command("run").description("Connect to Evident and process messages").op
|
|
|
8496
8795
|
// Raw string — the resolver in run.ts single-sources parsing
|
|
8497
8796
|
// (resolveClaudeUsageReportingMode).
|
|
8498
8797
|
claudeUsageReporting: options.claudeUsageReporting,
|
|
8798
|
+
// Raw value — resolution is single-sourced in run.ts's
|
|
8799
|
+
// resolveResourceUsageReportingEnabled.
|
|
8800
|
+
resourceUsageReporting: options.resourceUsageReporting,
|
|
8499
8801
|
// Raw values — expansion/validation is single-sourced in run.ts's
|
|
8500
8802
|
// resolveFileSyncDirectories.
|
|
8501
8803
|
enableFileSyncTo: options.enableFileSyncTo,
|