@evident-ai/cli 3.4.1-dev.4a15fbd → 3.4.1-dev.5210d05
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 +298 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -805,6 +805,7 @@ async function reportResourceUsage(agentId, authHeader, usage) {
|
|
|
805
805
|
headers: { Authorization: authHeader, "Content-Type": "application/json" },
|
|
806
806
|
body: JSON.stringify({
|
|
807
807
|
cpu_percent: usage.cpuPercent,
|
|
808
|
+
cpu_peak_percent: usage.cpuPeakPercent,
|
|
808
809
|
cpu_count: usage.cpuCount,
|
|
809
810
|
memory_total_bytes: usage.memoryTotalBytes,
|
|
810
811
|
memory_available_bytes: usage.memoryAvailableBytes,
|
|
@@ -1215,6 +1216,7 @@ var TelemetryEventTypes = {
|
|
|
1215
1216
|
// ../../packages/types/src/tunnel/index.ts
|
|
1216
1217
|
var MAX_FRAME_BYTES = 256 * 1024;
|
|
1217
1218
|
var TUNNEL_DRAIN_PING_PATH = "/__evident/drain";
|
|
1219
|
+
var TUNNEL_USAGE_REARM_PING_PATH = "/__evident/usage-rearm";
|
|
1218
1220
|
|
|
1219
1221
|
// ../../packages/types/src/runner-files.ts
|
|
1220
1222
|
var MAX_FILE_PUSH_BYTES = 64 * 1024;
|
|
@@ -3150,6 +3152,44 @@ function findLastAssistantReplyFor(messages, userMessageId) {
|
|
|
3150
3152
|
}
|
|
3151
3153
|
return lastOk ?? last;
|
|
3152
3154
|
}
|
|
3155
|
+
function collectSubagentSessions(messages, userMessageId) {
|
|
3156
|
+
if (!messages || messages.length === 0) return [];
|
|
3157
|
+
const byParent = messages.filter(
|
|
3158
|
+
(message) => roleOf(message) === "assistant" && parentIdOf(message) === userMessageId
|
|
3159
|
+
);
|
|
3160
|
+
const assistants = byParent.length > 0 ? byParent : [];
|
|
3161
|
+
if (assistants.length === 0) {
|
|
3162
|
+
const userIndex = messages.findIndex((message) => idOf(message) === userMessageId);
|
|
3163
|
+
if (userIndex === -1) return [];
|
|
3164
|
+
for (let i = userIndex + 1; i < messages.length; i++) {
|
|
3165
|
+
const message = messages[i];
|
|
3166
|
+
if (roleOf(message) === "user") break;
|
|
3167
|
+
if (roleOf(message) === "assistant") assistants.push(message);
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
const refs = [];
|
|
3171
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3172
|
+
for (const message of assistants) {
|
|
3173
|
+
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
3174
|
+
for (const part of parts) {
|
|
3175
|
+
if (!part || typeof part !== "object" || part.type !== "tool" || part.tool !== "task")
|
|
3176
|
+
continue;
|
|
3177
|
+
const state = part.state;
|
|
3178
|
+
if (!state || typeof state !== "object") continue;
|
|
3179
|
+
const metadata = state.metadata;
|
|
3180
|
+
if (!metadata || typeof metadata !== "object") continue;
|
|
3181
|
+
const sessionId = metadata.sessionId;
|
|
3182
|
+
if (typeof sessionId !== "string" || sessionId.length === 0 || seen.has(sessionId)) continue;
|
|
3183
|
+
seen.add(sessionId);
|
|
3184
|
+
const start = state.time?.start;
|
|
3185
|
+
refs.push({
|
|
3186
|
+
sessionId,
|
|
3187
|
+
startedAtMs: typeof start === "number" && Number.isFinite(start) ? start : null
|
|
3188
|
+
});
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
return refs;
|
|
3192
|
+
}
|
|
3153
3193
|
function messageUsage(messages, userMessageId) {
|
|
3154
3194
|
if (!messages || messages.length === 0) return null;
|
|
3155
3195
|
const byParentAll = messages.filter(
|
|
@@ -3278,8 +3318,7 @@ function isAbortedTerminalReply(messages, userMessageId) {
|
|
|
3278
3318
|
}
|
|
3279
3319
|
return false;
|
|
3280
3320
|
}
|
|
3281
|
-
function
|
|
3282
|
-
const reply = findLastAssistantReplyFor(messages, userMessageId);
|
|
3321
|
+
function classifyReplyAuthError(reply) {
|
|
3283
3322
|
const error2 = errorOf(reply);
|
|
3284
3323
|
if (error2 == null || typeof error2 !== "object") return null;
|
|
3285
3324
|
const e = error2;
|
|
@@ -3304,6 +3343,32 @@ function messageFailure(messages, userMessageId) {
|
|
|
3304
3343
|
}
|
|
3305
3344
|
return null;
|
|
3306
3345
|
}
|
|
3346
|
+
function messageFailure(messages, userMessageId) {
|
|
3347
|
+
return classifyReplyAuthError(findLastAssistantReplyFor(messages, userMessageId));
|
|
3348
|
+
}
|
|
3349
|
+
function findLatestSubagentAuthOutcome(messages, sinceMs) {
|
|
3350
|
+
if (!messages || messages.length === 0) return null;
|
|
3351
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
3352
|
+
const message = messages[i];
|
|
3353
|
+
if (roleOf(message) !== "assistant") continue;
|
|
3354
|
+
const created = createdOf(message);
|
|
3355
|
+
if (sinceMs !== null && typeof created === "number" && created < sinceMs) continue;
|
|
3356
|
+
const failure = classifyReplyAuthError(message);
|
|
3357
|
+
if (failure) {
|
|
3358
|
+
if (!failure.providerId) return null;
|
|
3359
|
+
return { providerId: failure.providerId, outcome: "failed", failure };
|
|
3360
|
+
}
|
|
3361
|
+
const providerId = message.info?.providerID;
|
|
3362
|
+
if (errorOf(message) == null && typeof providerId === "string" && providerId.length > 0) {
|
|
3363
|
+
return { providerId, outcome: "succeeded" };
|
|
3364
|
+
}
|
|
3365
|
+
return null;
|
|
3366
|
+
}
|
|
3367
|
+
return null;
|
|
3368
|
+
}
|
|
3369
|
+
function findSubagentAuthOutcome(messages, sinceMs) {
|
|
3370
|
+
return findLatestSubagentAuthOutcome(messages, sinceMs);
|
|
3371
|
+
}
|
|
3307
3372
|
function applyZeroProviderFallback(classified, hasConfiguredProvider, replyProviderId, replyModelId = null) {
|
|
3308
3373
|
if (classified != null) return classified;
|
|
3309
3374
|
if (hasConfiguredProvider !== false) return null;
|
|
@@ -3634,7 +3699,6 @@ var StreamForwarder = class {
|
|
|
3634
3699
|
handleFrame(frame) {
|
|
3635
3700
|
switch (frame.type) {
|
|
3636
3701
|
case "open":
|
|
3637
|
-
this.callbacks.onOpen?.(frame.sid, frame.method, frame.path);
|
|
3638
3702
|
void this.handleOpen(frame);
|
|
3639
3703
|
break;
|
|
3640
3704
|
case "req_data":
|
|
@@ -3670,12 +3734,21 @@ var StreamForwarder = class {
|
|
|
3670
3734
|
const { sid, method, path, headers, has_body } = frame;
|
|
3671
3735
|
const correlationId = headers?.[CORRELATION_ID_HEADER];
|
|
3672
3736
|
const startedAt = Date.now();
|
|
3737
|
+
if (path !== TUNNEL_DRAIN_PING_PATH && path !== TUNNEL_USAGE_REARM_PING_PATH) {
|
|
3738
|
+
this.callbacks.onOpen?.(sid, method, path);
|
|
3739
|
+
}
|
|
3673
3740
|
if (path === TUNNEL_DRAIN_PING_PATH) {
|
|
3674
3741
|
this.callbacks.onDrainPing?.();
|
|
3675
3742
|
this.send({ type: "head", sid, status: 204, headers: {} });
|
|
3676
3743
|
this.send({ type: "res_end", sid });
|
|
3677
3744
|
return;
|
|
3678
3745
|
}
|
|
3746
|
+
if (path === TUNNEL_USAGE_REARM_PING_PATH) {
|
|
3747
|
+
this.callbacks.onUsageRearmPing?.();
|
|
3748
|
+
this.send({ type: "head", sid, status: 204, headers: {} });
|
|
3749
|
+
this.send({ type: "res_end", sid });
|
|
3750
|
+
return;
|
|
3751
|
+
}
|
|
3679
3752
|
if (process.env.DEBUG) {
|
|
3680
3753
|
log("debug", "agent_request", {
|
|
3681
3754
|
correlation_id: correlationId,
|
|
@@ -3820,7 +3893,8 @@ function connectTunnel(options) {
|
|
|
3820
3893
|
onResponse,
|
|
3821
3894
|
onInfo,
|
|
3822
3895
|
onWarning,
|
|
3823
|
-
onDrainPing
|
|
3896
|
+
onDrainPing,
|
|
3897
|
+
onUsageRearmPing
|
|
3824
3898
|
} = options;
|
|
3825
3899
|
const tunnelUrl = getTunnelUrlConfig();
|
|
3826
3900
|
const url = `${tunnelUrl}/tunnel/${agentId}/connect`;
|
|
@@ -3832,7 +3906,8 @@ function connectTunnel(options) {
|
|
|
3832
3906
|
});
|
|
3833
3907
|
const forwarder = new StreamForwarder(ws, port, {
|
|
3834
3908
|
onHead: () => onResponse?.(),
|
|
3835
|
-
onDrainPing: () => onDrainPing?.()
|
|
3909
|
+
onDrainPing: () => onDrainPing?.(),
|
|
3910
|
+
onUsageRearmPing: () => onUsageRearmPing?.()
|
|
3836
3911
|
});
|
|
3837
3912
|
const connectionTimeout = setTimeout(() => {
|
|
3838
3913
|
ws.close();
|
|
@@ -3993,6 +4068,7 @@ var RunnerConnection = class {
|
|
|
3993
4068
|
onError: (error2) => events.onError?.(error2),
|
|
3994
4069
|
onResponse: () => events.onResponse?.(),
|
|
3995
4070
|
onDrainPing: () => events.onDrainPing?.(),
|
|
4071
|
+
onUsageRearmPing: () => events.onUsageRearmPing?.(),
|
|
3996
4072
|
onInfo: (message) => events.onInfo?.(message),
|
|
3997
4073
|
onWarning: (message) => events.onWarning?.(message)
|
|
3998
4074
|
});
|
|
@@ -4437,45 +4513,84 @@ function readDisk(homeDir) {
|
|
|
4437
4513
|
};
|
|
4438
4514
|
}
|
|
4439
4515
|
}
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4516
|
+
var CPU_PEAK_WINDOW_MS = 6e4;
|
|
4517
|
+
var CPU_PEAK_WINDOW_SAMPLE_COUNT = 4;
|
|
4518
|
+
var CPU_PEAK_SAMPLE_INTERVAL_MS = CPU_PEAK_WINDOW_MS / CPU_PEAK_WINDOW_SAMPLE_COUNT;
|
|
4519
|
+
function createCpuPeakSampler() {
|
|
4520
|
+
const sampleHistory = new Array(CPU_PEAK_WINDOW_SAMPLE_COUNT);
|
|
4521
|
+
sampleHistory[0] = readCpuSample();
|
|
4522
|
+
let nextSampleIndex = 1;
|
|
4523
|
+
let sampleCount = 1;
|
|
4524
|
+
let peak = null;
|
|
4525
|
+
const timer = setInterval(() => {
|
|
4443
4526
|
const current = readCpuSample();
|
|
4444
|
-
const
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
const warnings = [];
|
|
4451
|
-
if (disk.warning) warnings.push(disk.warning);
|
|
4452
|
-
if (ecsWarning) warnings.push(ecsWarning);
|
|
4453
|
-
let cpuPercent = hostCpuPercent;
|
|
4454
|
-
let cpuCount = hostCpuCount;
|
|
4455
|
-
let memoryTotalBytes = totalmem();
|
|
4456
|
-
let memoryAvailableBytes = freemem();
|
|
4457
|
-
if (limits !== null) {
|
|
4458
|
-
cpuCount = limits.cpuCount;
|
|
4459
|
-
memoryTotalBytes = limits.memoryTotalBytes;
|
|
4460
|
-
memoryAvailableBytes = clamp(
|
|
4461
|
-
limits.memoryTotalBytes - (totalmem() - freemem()),
|
|
4462
|
-
0,
|
|
4463
|
-
limits.memoryTotalBytes
|
|
4464
|
-
);
|
|
4465
|
-
cpuPercent = hostCpuPercent === null ? null : clamp(round2(hostCpuPercent * hostCpuCount / limits.cpuCount), 0, 100);
|
|
4527
|
+
const sampleFromWindowAgo = sampleCount === CPU_PEAK_WINDOW_SAMPLE_COUNT ? sampleHistory[nextSampleIndex] : void 0;
|
|
4528
|
+
if (sampleFromWindowAgo !== void 0) {
|
|
4529
|
+
const percentage = cpuPercentBetween(sampleFromWindowAgo, current);
|
|
4530
|
+
if (percentage !== null) {
|
|
4531
|
+
peak = peak === null ? percentage : Math.max(peak, percentage);
|
|
4532
|
+
}
|
|
4466
4533
|
}
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4534
|
+
sampleHistory[nextSampleIndex] = current;
|
|
4535
|
+
nextSampleIndex = (nextSampleIndex + 1) % CPU_PEAK_WINDOW_SAMPLE_COUNT;
|
|
4536
|
+
sampleCount = Math.min(sampleCount + 1, CPU_PEAK_WINDOW_SAMPLE_COUNT);
|
|
4537
|
+
}, CPU_PEAK_SAMPLE_INTERVAL_MS);
|
|
4538
|
+
return {
|
|
4539
|
+
takeAndReset: () => {
|
|
4540
|
+
const currentPeak = peak;
|
|
4541
|
+
peak = null;
|
|
4542
|
+
return currentPeak;
|
|
4543
|
+
},
|
|
4544
|
+
stop: () => clearInterval(timer)
|
|
4545
|
+
};
|
|
4546
|
+
}
|
|
4547
|
+
function createResourceUsageCollector(homeDir) {
|
|
4548
|
+
let previous = readCpuSample();
|
|
4549
|
+
const cpuPeakSampler = createCpuPeakSampler();
|
|
4550
|
+
return {
|
|
4551
|
+
collect: async () => {
|
|
4552
|
+
const current = readCpuSample();
|
|
4553
|
+
const hostCpuPercent = cpuPercentBetween(previous, current);
|
|
4554
|
+
const hostCpuPeakPercent = cpuPeakSampler.takeAndReset();
|
|
4555
|
+
const hostCpuCount = cpus().length;
|
|
4556
|
+
previous = current;
|
|
4557
|
+
const disk = readDisk(homeDir);
|
|
4558
|
+
const opencodeDbBytes = statSessionDbBytes(homeDir);
|
|
4559
|
+
const { limits, warning: ecsWarning } = await readEcsTaskLimits(process.env);
|
|
4560
|
+
const warnings = [];
|
|
4561
|
+
if (disk.warning) warnings.push(disk.warning);
|
|
4562
|
+
if (ecsWarning) warnings.push(ecsWarning);
|
|
4563
|
+
let cpuPercent = hostCpuPercent;
|
|
4564
|
+
let cpuPeakPercent = hostCpuPeakPercent;
|
|
4565
|
+
let cpuCount = hostCpuCount;
|
|
4566
|
+
let memoryTotalBytes = totalmem();
|
|
4567
|
+
let memoryAvailableBytes = freemem();
|
|
4568
|
+
if (limits !== null) {
|
|
4569
|
+
cpuCount = limits.cpuCount;
|
|
4570
|
+
memoryTotalBytes = limits.memoryTotalBytes;
|
|
4571
|
+
memoryAvailableBytes = clamp(
|
|
4572
|
+
limits.memoryTotalBytes - (totalmem() - freemem()),
|
|
4573
|
+
0,
|
|
4574
|
+
limits.memoryTotalBytes
|
|
4575
|
+
);
|
|
4576
|
+
cpuPercent = hostCpuPercent === null ? null : clamp(round2(hostCpuPercent * hostCpuCount / limits.cpuCount), 0, 100);
|
|
4577
|
+
cpuPeakPercent = hostCpuPeakPercent === null ? null : clamp(round2(hostCpuPeakPercent * hostCpuCount / limits.cpuCount), 0, 100);
|
|
4578
|
+
}
|
|
4579
|
+
return {
|
|
4580
|
+
usage: {
|
|
4581
|
+
cpuPercent,
|
|
4582
|
+
cpuPeakPercent,
|
|
4583
|
+
cpuCount,
|
|
4584
|
+
memoryTotalBytes,
|
|
4585
|
+
memoryAvailableBytes,
|
|
4586
|
+
diskTotalBytes: disk.totalBytes,
|
|
4587
|
+
diskFreeBytes: disk.freeBytes,
|
|
4588
|
+
opencodeDbBytes
|
|
4589
|
+
},
|
|
4590
|
+
warnings
|
|
4591
|
+
};
|
|
4592
|
+
},
|
|
4593
|
+
stop: cpuPeakSampler.stop
|
|
4479
4594
|
};
|
|
4480
4595
|
}
|
|
4481
4596
|
|
|
@@ -6062,6 +6177,9 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
6062
6177
|
});
|
|
6063
6178
|
await this.markFailed(conv.id, message.id, sessionId, error2, usage, failure);
|
|
6064
6179
|
}
|
|
6180
|
+
if (ocId !== null) {
|
|
6181
|
+
await this.reportSubagentAuthFailures(conv.id, ocId, message.id, messages);
|
|
6182
|
+
}
|
|
6065
6183
|
} catch (err) {
|
|
6066
6184
|
if (err instanceof ChannelAuthError) throw err;
|
|
6067
6185
|
this.log({
|
|
@@ -7026,6 +7144,12 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
7026
7144
|
return;
|
|
7027
7145
|
}
|
|
7028
7146
|
inFlight.done = true;
|
|
7147
|
+
await this.reportSubagentAuthFailures(
|
|
7148
|
+
watcher.conv.id,
|
|
7149
|
+
inFlight.opencodeMessageId,
|
|
7150
|
+
inFlight.evidentMessageId,
|
|
7151
|
+
messages
|
|
7152
|
+
);
|
|
7029
7153
|
}
|
|
7030
7154
|
this.removeInFlight(watcher, inFlight.evidentMessageId);
|
|
7031
7155
|
return;
|
|
@@ -7268,6 +7392,12 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
7268
7392
|
return;
|
|
7269
7393
|
}
|
|
7270
7394
|
inFlight.done = true;
|
|
7395
|
+
await this.reportSubagentAuthFailures(
|
|
7396
|
+
watcher.conv.id,
|
|
7397
|
+
inFlight.opencodeMessageId,
|
|
7398
|
+
inFlight.evidentMessageId,
|
|
7399
|
+
messages
|
|
7400
|
+
);
|
|
7271
7401
|
}
|
|
7272
7402
|
this.removeInFlight(watcher, inFlight.evidentMessageId);
|
|
7273
7403
|
}
|
|
@@ -7438,6 +7568,7 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
7438
7568
|
});
|
|
7439
7569
|
return;
|
|
7440
7570
|
}
|
|
7571
|
+
await this.reportSubagentAuthFailures(row.conversation_id, ocId ?? "", row.id, messages);
|
|
7441
7572
|
this.dontRedispatch.delete(row.id);
|
|
7442
7573
|
void this.postSignal(row.conversation_id, row.id, "readopt_failed");
|
|
7443
7574
|
return;
|
|
@@ -7599,6 +7730,9 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
7599
7730
|
});
|
|
7600
7731
|
return;
|
|
7601
7732
|
}
|
|
7733
|
+
if (ocId !== null) {
|
|
7734
|
+
await this.reportSubagentAuthFailures(row.conversation_id, ocId, row.id, messages);
|
|
7735
|
+
}
|
|
7602
7736
|
this.dontRedispatch.delete(row.id);
|
|
7603
7737
|
void this.postSignal(row.conversation_id, row.id, "readopt_done");
|
|
7604
7738
|
}
|
|
@@ -8550,6 +8684,111 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
8550
8684
|
reply?.info?.modelID ?? null
|
|
8551
8685
|
);
|
|
8552
8686
|
}
|
|
8687
|
+
async recordSubagentModelAuthFailure(failure, conversationId, messageId) {
|
|
8688
|
+
const providerId = failure.providerId ?? "(unknown)";
|
|
8689
|
+
try {
|
|
8690
|
+
const res = await this.fetchImpl(
|
|
8691
|
+
`${this.apiUrl}/runners/${this.agentId}/model-auth-failures`,
|
|
8692
|
+
{
|
|
8693
|
+
method: "POST",
|
|
8694
|
+
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
8695
|
+
body: JSON.stringify({
|
|
8696
|
+
provider_id: failure.providerId,
|
|
8697
|
+
model_id: failure.modelId,
|
|
8698
|
+
reason: failure.reason
|
|
8699
|
+
})
|
|
8700
|
+
}
|
|
8701
|
+
);
|
|
8702
|
+
if (!res.ok) {
|
|
8703
|
+
this.log({
|
|
8704
|
+
level: "warn",
|
|
8705
|
+
message: `Sub-agent model-auth report for provider ${providerId} (${failure.reason}) returned HTTP ${res.status} (conversation ${conversationId.slice(0, 8)}, message ${messageId.slice(0, 8)})`,
|
|
8706
|
+
conversation_id: conversationId,
|
|
8707
|
+
message_id: messageId
|
|
8708
|
+
});
|
|
8709
|
+
}
|
|
8710
|
+
} catch (err) {
|
|
8711
|
+
this.log({
|
|
8712
|
+
level: "warn",
|
|
8713
|
+
message: `Sub-agent model-auth report for provider ${providerId} (${failure.reason}) failed with status network-error (conversation ${conversationId.slice(0, 8)}, message ${messageId.slice(0, 8)}): ${err instanceof Error ? err.message : String(err)}`,
|
|
8714
|
+
conversation_id: conversationId,
|
|
8715
|
+
message_id: messageId
|
|
8716
|
+
});
|
|
8717
|
+
}
|
|
8718
|
+
}
|
|
8719
|
+
async clearSubagentModelAuthFailure(providerId, conversationId, messageId) {
|
|
8720
|
+
try {
|
|
8721
|
+
const res = await this.fetchImpl(
|
|
8722
|
+
`${this.apiUrl}/runners/${this.agentId}/model-auth-failures/${encodeURIComponent(providerId)}`,
|
|
8723
|
+
{
|
|
8724
|
+
method: "DELETE",
|
|
8725
|
+
headers: { Authorization: this.getAuthHeader() }
|
|
8726
|
+
}
|
|
8727
|
+
);
|
|
8728
|
+
if (!res.ok) {
|
|
8729
|
+
this.log({
|
|
8730
|
+
level: "warn",
|
|
8731
|
+
message: `Sub-agent model-auth clear for provider ${providerId} returned HTTP ${res.status} (conversation ${conversationId.slice(0, 8)}, message ${messageId.slice(0, 8)})`,
|
|
8732
|
+
conversation_id: conversationId,
|
|
8733
|
+
message_id: messageId
|
|
8734
|
+
});
|
|
8735
|
+
}
|
|
8736
|
+
} catch (err) {
|
|
8737
|
+
this.log({
|
|
8738
|
+
level: "warn",
|
|
8739
|
+
message: `Sub-agent model-auth clear for provider ${providerId} failed with status network-error (conversation ${conversationId.slice(0, 8)}, message ${messageId.slice(0, 8)}): ${err instanceof Error ? err.message : String(err)}`,
|
|
8740
|
+
conversation_id: conversationId,
|
|
8741
|
+
message_id: messageId
|
|
8742
|
+
});
|
|
8743
|
+
}
|
|
8744
|
+
}
|
|
8745
|
+
async reportSubagentAuthFailures(conversationId, opencodeMessageId, evidentMessageId, messages) {
|
|
8746
|
+
const refs = collectSubagentSessions(messages, opencodeMessageId);
|
|
8747
|
+
if (refs.length === 0) return;
|
|
8748
|
+
const failedProviders = /* @__PURE__ */ new Map();
|
|
8749
|
+
const succeededProviders = /* @__PURE__ */ new Set();
|
|
8750
|
+
for (const ref of refs) {
|
|
8751
|
+
try {
|
|
8752
|
+
const childMessages = await getSessionMessages(this.port, ref.sessionId);
|
|
8753
|
+
if (childMessages === null) {
|
|
8754
|
+
this.log({
|
|
8755
|
+
level: "debug",
|
|
8756
|
+
message: `Could not read sub-agent session ${ref.sessionId} while checking credential failures \u2014 skipping it`,
|
|
8757
|
+
conversation_id: conversationId,
|
|
8758
|
+
message_id: evidentMessageId
|
|
8759
|
+
});
|
|
8760
|
+
continue;
|
|
8761
|
+
}
|
|
8762
|
+
const outcome = findSubagentAuthOutcome(childMessages, ref.startedAtMs);
|
|
8763
|
+
if (!outcome) continue;
|
|
8764
|
+
if (outcome.outcome === "failed") {
|
|
8765
|
+
failedProviders.set(outcome.providerId, outcome.failure);
|
|
8766
|
+
} else {
|
|
8767
|
+
succeededProviders.add(outcome.providerId);
|
|
8768
|
+
}
|
|
8769
|
+
} catch (err) {
|
|
8770
|
+
this.log({
|
|
8771
|
+
level: "warn",
|
|
8772
|
+
message: `Failed to inspect sub-agent session ${ref.sessionId} for credential failures (conversation ${conversationId.slice(0, 8)}, message ${evidentMessageId.slice(0, 8)}): ${err instanceof Error ? err.message : String(err)}`,
|
|
8773
|
+
conversation_id: conversationId,
|
|
8774
|
+
message_id: evidentMessageId
|
|
8775
|
+
});
|
|
8776
|
+
}
|
|
8777
|
+
}
|
|
8778
|
+
for (const [providerId, failure] of failedProviders) {
|
|
8779
|
+
this.log({
|
|
8780
|
+
level: "warn",
|
|
8781
|
+
message: `Sub-agent turn failed on provider ${providerId} (${failure.reason}) \u2014 recording credential evidence`,
|
|
8782
|
+
conversation_id: conversationId,
|
|
8783
|
+
message_id: evidentMessageId
|
|
8784
|
+
});
|
|
8785
|
+
await this.recordSubagentModelAuthFailure(failure, conversationId, evidentMessageId);
|
|
8786
|
+
}
|
|
8787
|
+
for (const providerId of succeededProviders) {
|
|
8788
|
+
if (failedProviders.has(providerId)) continue;
|
|
8789
|
+
await this.clearSubagentModelAuthFailure(providerId, conversationId, evidentMessageId);
|
|
8790
|
+
}
|
|
8791
|
+
}
|
|
8553
8792
|
/**
|
|
8554
8793
|
* Best-effort, SINGLE-ATTEMPT runner→server telemetry ping
|
|
8555
8794
|
* (queued-followup-redrive). `POST .../messages/:id/signal {signal, ...extra}`
|
|
@@ -10080,7 +10319,8 @@ function scheduleResourceUsageReporting(state, options) {
|
|
|
10080
10319
|
});
|
|
10081
10320
|
return;
|
|
10082
10321
|
}
|
|
10083
|
-
const collect = createResourceUsageCollector(homedir5());
|
|
10322
|
+
const { collect, stop } = createResourceUsageCollector(homedir5());
|
|
10323
|
+
state.stopResourceUsageSampling = stop;
|
|
10084
10324
|
let consecutiveFailures = 0;
|
|
10085
10325
|
const tick = async () => {
|
|
10086
10326
|
try {
|
|
@@ -10190,6 +10430,8 @@ async function cleanup(state, opts = {}) {
|
|
|
10190
10430
|
clearTimeout(state.resourceUsageTimer);
|
|
10191
10431
|
state.resourceUsageTimer = null;
|
|
10192
10432
|
}
|
|
10433
|
+
state.stopResourceUsageSampling?.();
|
|
10434
|
+
state.stopResourceUsageSampling = null;
|
|
10193
10435
|
const credentialSync = state.credentialSync;
|
|
10194
10436
|
const flushCredentials = credentialSync ? async (phase, publish) => {
|
|
10195
10437
|
await timeShutdownPhase(state, durations, phase, async () => {
|
|
@@ -10357,6 +10599,7 @@ async function run(options) {
|
|
|
10357
10599
|
openaiUsageTimer: null,
|
|
10358
10600
|
openaiUsageRearm: null,
|
|
10359
10601
|
resourceUsageTimer: null,
|
|
10602
|
+
stopResourceUsageSampling: null,
|
|
10360
10603
|
credentialSync: null,
|
|
10361
10604
|
authHeader: ""
|
|
10362
10605
|
};
|
|
@@ -10917,6 +11160,18 @@ async function run(options) {
|
|
|
10917
11160
|
if (state.interactive) displayStatus(state);
|
|
10918
11161
|
});
|
|
10919
11162
|
},
|
|
11163
|
+
// Both loops are rearmed because `rearm()` is idempotent for the
|
|
11164
|
+
// provider that did not just connect, and is a no-op when reporting is off.
|
|
11165
|
+
onUsageRearmPing: () => {
|
|
11166
|
+
if (!state.running) return;
|
|
11167
|
+
logActivity(state, {
|
|
11168
|
+
type: "info",
|
|
11169
|
+
level: "debug",
|
|
11170
|
+
message: "Usage rearm ping received"
|
|
11171
|
+
});
|
|
11172
|
+
state.claudeUsageRearm?.();
|
|
11173
|
+
state.openaiUsageRearm?.();
|
|
11174
|
+
},
|
|
10920
11175
|
onInfo: (message) => logActivity(state, { type: "info", message })
|
|
10921
11176
|
}
|
|
10922
11177
|
});
|