@evident-ai/cli 3.1.1-dev.b4e1c75 → 3.1.1-dev.b5f0ac5
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 +77 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1548,6 +1548,42 @@ function messageError(messages, userMessageId) {
|
|
|
1548
1548
|
}
|
|
1549
1549
|
return "The agent run failed.";
|
|
1550
1550
|
}
|
|
1551
|
+
function messageFailure(messages, userMessageId) {
|
|
1552
|
+
const reply = findLastAssistantReplyFor(messages, userMessageId);
|
|
1553
|
+
const error2 = errorOf(reply);
|
|
1554
|
+
if (error2 == null || typeof error2 !== "object") return null;
|
|
1555
|
+
const e = error2;
|
|
1556
|
+
const replyProviderId = reply?.info?.providerID ?? null;
|
|
1557
|
+
const replyModelId = reply?.info?.modelID ?? null;
|
|
1558
|
+
if (e.name === "ProviderAuthError") {
|
|
1559
|
+
const data = e.data;
|
|
1560
|
+
const providerId = typeof data?.providerID === "string" && data.providerID || replyProviderId;
|
|
1561
|
+
return { kind: "model_auth", providerId, modelId: replyModelId, reason: "missing" };
|
|
1562
|
+
}
|
|
1563
|
+
if (e.name === "APIError") {
|
|
1564
|
+
const data = e.data;
|
|
1565
|
+
const statusCode = data?.statusCode;
|
|
1566
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
1567
|
+
return {
|
|
1568
|
+
kind: "model_auth",
|
|
1569
|
+
providerId: replyProviderId,
|
|
1570
|
+
modelId: replyModelId,
|
|
1571
|
+
reason: "rejected"
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
return null;
|
|
1576
|
+
}
|
|
1577
|
+
function applyZeroProviderFallback(classified, hasConfiguredProvider, replyProviderId, replyModelId = null) {
|
|
1578
|
+
if (classified != null) return classified;
|
|
1579
|
+
if (hasConfiguredProvider !== false) return null;
|
|
1580
|
+
return {
|
|
1581
|
+
kind: "model_auth",
|
|
1582
|
+
providerId: replyProviderId,
|
|
1583
|
+
modelId: replyModelId,
|
|
1584
|
+
reason: "missing"
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1551
1587
|
function hasRunningAssistantExcept(messages, exceptUserMessageId) {
|
|
1552
1588
|
if (!messages || messages.length === 0) return false;
|
|
1553
1589
|
return messages.some(
|
|
@@ -3598,8 +3634,16 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
3598
3634
|
message_id: inFlight.evidentMessageId
|
|
3599
3635
|
});
|
|
3600
3636
|
const usage = messageUsage(messages, inFlight.opencodeMessageId);
|
|
3637
|
+
const failure = await this.classifyModelAuthFailure(messages, inFlight.opencodeMessageId);
|
|
3601
3638
|
try {
|
|
3602
|
-
await this.markFailed(
|
|
3639
|
+
await this.markFailed(
|
|
3640
|
+
conv.id,
|
|
3641
|
+
inFlight.evidentMessageId,
|
|
3642
|
+
sessionId,
|
|
3643
|
+
error2,
|
|
3644
|
+
usage,
|
|
3645
|
+
failure
|
|
3646
|
+
);
|
|
3603
3647
|
} catch (err) {
|
|
3604
3648
|
if (err instanceof ChannelAuthError) throw err;
|
|
3605
3649
|
if (err instanceof ChannelTerminalError) {
|
|
@@ -3980,6 +4024,7 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
3980
4024
|
if (state === "failed") {
|
|
3981
4025
|
const error2 = messageError(messages, ocId ?? "") ?? void 0;
|
|
3982
4026
|
const usage = messageUsage(messages, ocId ?? "");
|
|
4027
|
+
const failure = await this.classifyModelAuthFailure(messages, ocId ?? "");
|
|
3983
4028
|
this.log({
|
|
3984
4029
|
level: "error",
|
|
3985
4030
|
message: `Re-adopt: message ${row.id.slice(0, 8)} errored while unwatched \u2014 marking failed: ${error2 ?? "(no error text)"}`,
|
|
@@ -3987,7 +4032,7 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
3987
4032
|
message_id: row.id
|
|
3988
4033
|
});
|
|
3989
4034
|
try {
|
|
3990
|
-
await this.markFailed(row.conversation_id, row.id, sessionId, error2, usage);
|
|
4035
|
+
await this.markFailed(row.conversation_id, row.id, sessionId, error2, usage, failure);
|
|
3991
4036
|
} catch (err) {
|
|
3992
4037
|
if (err instanceof ChannelAuthError) throw err;
|
|
3993
4038
|
if (err instanceof ChannelTerminalError) {
|
|
@@ -4965,7 +5010,7 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
4965
5010
|
* exists but is wedged, so the next attempt must get a fresh one
|
|
4966
5011
|
* instead of reusing it — see WI-1's server-side null-clearing PATCH).
|
|
4967
5012
|
*/
|
|
4968
|
-
async markFailed(conversationId, messageId, sessionId, error2, usage) {
|
|
5013
|
+
async markFailed(conversationId, messageId, sessionId, error2, usage, failure) {
|
|
4969
5014
|
const body = { status: "failed" };
|
|
4970
5015
|
if (sessionId === null) {
|
|
4971
5016
|
body.opencode_session_id = null;
|
|
@@ -4974,6 +5019,12 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
4974
5019
|
}
|
|
4975
5020
|
if (error2 !== void 0) body.error = error2;
|
|
4976
5021
|
if (usage) Object.assign(body, usage);
|
|
5022
|
+
if (failure) {
|
|
5023
|
+
body.failure_kind = failure.kind;
|
|
5024
|
+
body.failure_provider_id = failure.providerId;
|
|
5025
|
+
body.failure_model_id = failure.modelId;
|
|
5026
|
+
body.failure_reason = failure.reason;
|
|
5027
|
+
}
|
|
4977
5028
|
await this.callWithRetry(
|
|
4978
5029
|
"marking message as failed",
|
|
4979
5030
|
() => this.fetchImpl(
|
|
@@ -4986,6 +5037,29 @@ var ChannelDriver = class _ChannelDriver {
|
|
|
4986
5037
|
)
|
|
4987
5038
|
);
|
|
4988
5039
|
}
|
|
5040
|
+
/**
|
|
5041
|
+
* Classify an errored turn as a model-auth failure (#736 P1-4), for `markFailed`.
|
|
5042
|
+
*
|
|
5043
|
+
* `messageFailure` alone (structured OpenCode error → `model_auth`) covers
|
|
5044
|
+
* most cases; when it returns `null` on this ALREADY-FAILED turn, fall back
|
|
5045
|
+
* to the P1-2b zero-provider check — one extra loopback call to
|
|
5046
|
+
* `hasAnyConfiguredProvider`, only reached when the structured classifier
|
|
5047
|
+
* couldn't place it. Fails open (never throws): a fallback probe failure
|
|
5048
|
+
* (`null`/indeterminate) leaves the classification `null`, which produces
|
|
5049
|
+
* today's byte-identical PATCH body via `markFailed`'s `if (failure)` guard.
|
|
5050
|
+
*/
|
|
5051
|
+
async classifyModelAuthFailure(messages, userMessageId) {
|
|
5052
|
+
const classified = messageFailure(messages, userMessageId);
|
|
5053
|
+
if (classified != null) return classified;
|
|
5054
|
+
const reply = findLastAssistantReplyFor(messages, userMessageId);
|
|
5055
|
+
const hasProvider = await hasAnyConfiguredProvider(this.port);
|
|
5056
|
+
return applyZeroProviderFallback(
|
|
5057
|
+
classified,
|
|
5058
|
+
hasProvider,
|
|
5059
|
+
reply?.info?.providerID ?? null,
|
|
5060
|
+
reply?.info?.modelID ?? null
|
|
5061
|
+
);
|
|
5062
|
+
}
|
|
4989
5063
|
/**
|
|
4990
5064
|
* Best-effort, SINGLE-ATTEMPT runner→server telemetry ping
|
|
4991
5065
|
* (queued-followup-redrive). `POST .../messages/:id/signal {signal, ...extra}`
|