fix(agents): classify embedded provider business denials for fallback

This commit is contained in:
clawsweeper
2026-05-29 23:18:56 +00:00
parent 78e3d56b81
commit a7b776932c
2 changed files with 45 additions and 2 deletions

View File

@@ -89,4 +89,24 @@ describe("classifyEmbeddedAgentRunResultForModelFallback", () => {
expect(result).toBeNull();
});
it("does not retry non-business transport error payloads", () => {
const result = classifyEmbeddedAgentRunResultForModelFallback({
provider: "custom",
model: "llama-3.1",
result: {
payloads: [
{
isError: true,
text: "HTTP 500: internal server error",
},
],
meta: {
durationMs: 42,
},
},
});
expect(result).toBeNull();
});
});

View File

@@ -1,5 +1,10 @@
import { isSilentReplyPayloadText } from "../../auto-reply/tokens.js";
import { classifyFailoverReason } from "../embedded-agent-helpers.js";
import {
isAuthErrorMessage,
isAuthPermanentErrorMessage,
isBillingErrorMessage,
} from "../embedded-agent-helpers/failover-matches.js";
import type { FailoverReason } from "../embedded-agent-helpers/types.js";
import { isGpt5ModelId } from "../gpt5-prompt-overlay.js";
import type { ModelFallbackResultClassification } from "../model-fallback.js";
import { hasOutboundDeliveryEvidence, hasVisibleAgentPayload } from "./delivery-evidence.js";
@@ -56,6 +61,24 @@ function classifyHarnessResult(params: {
}
}
function classifyBusinessDenialErrorPayloadReason(
errorText: string,
): Extract<FailoverReason, "auth" | "auth_permanent" | "billing"> | null {
if (!errorText.trim()) {
return null;
}
if (isBillingErrorMessage(errorText)) {
return "billing";
}
if (isAuthPermanentErrorMessage(errorText)) {
return "auth_permanent";
}
if (isAuthErrorMessage(errorText)) {
return "auth";
}
return null;
}
export function classifyEmbeddedAgentRunResultForModelFallback(params: {
provider: string;
model: string;
@@ -105,7 +128,7 @@ export function classifyEmbeddedAgentRunResultForModelFallback(params: {
code: "incomplete_result",
};
}
const failoverReason = classifyFailoverReason(errorText, { provider: params.provider });
const failoverReason = classifyBusinessDenialErrorPayloadReason(errorText);
if (failoverReason) {
return {
message: `${params.provider}/${params.model} ended with a provider error: ${errorText}`,