mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-08 01:57:31 +01:00
fix(codex-local): route typed ACP credential rejections to sign-in recovery (#19146)
Classify a typed Codex ACP `access` failure as `acpx_auth_required` when the provider text reports `401 Unauthorized`, `invalid_api_key`, or an incorrect/invalid API key. Other `access` failures keep `acpx_turn_failed`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
482ec0aea9
commit
6fa54d5577
2 files changed
+41
No files matched your search
@@ -160,6 +160,40 @@ it("keeps the historical generic terminal-service error unclassified", () => {
|
||||
}, now)).toBeNull();
|
||||
});
|
||||
|
||||
it.each([
|
||||
"unexpected status 401 Unauthorized: Incorrect API key provided: sk-test...abcd., auth error code: invalid_api_key",
|
||||
"Incorrect API key provided",
|
||||
"Invalid API key",
|
||||
"auth error code: invalid_api_key",
|
||||
])("routes a typed Codex credential rejection to sign-in recovery: %s", (title) => {
|
||||
expect(classifyCodexTerminalSessionFailure({ category: "access", title }, now))
|
||||
.toEqual({ errorCode: "acpx_auth_required" });
|
||||
expect(classifyCodexTerminalSessionFailure({ category: "access", title: "Codex turn failed", details: title }, now))
|
||||
.toEqual({ errorCode: "acpx_auth_required" });
|
||||
});
|
||||
|
||||
it.each([
|
||||
["ACP agent reported a terminal access failure.", "access"],
|
||||
["403 Forbidden: project does not have access to model gpt-5", "access"],
|
||||
["Permission denied for tool shell", "access"],
|
||||
["Incorrect API key provided", "request"],
|
||||
["Incorrect API key provided", "service"],
|
||||
["Incorrect API key provided", "connection"],
|
||||
])("keeps other typed failures out of sign-in recovery: %s (%s)", (title, category) => {
|
||||
expect(classifyCodexTerminalSessionFailure({ category, title }, now)).toBeNull();
|
||||
});
|
||||
|
||||
it("requires sign-in for a typed Codex credential rejection instead of a turn failure", async () => {
|
||||
const title = "unexpected status 401 Unauthorized: Incorrect API key provided, auth error code: invalid_api_key";
|
||||
const { result } = await executeFailure(title, "access");
|
||||
expect(result).toMatchObject({
|
||||
exitCode: 1,
|
||||
errorCode: "acpx_auth_required",
|
||||
resultJson: { terminalSessionFailure: { category: "access" } },
|
||||
});
|
||||
expect(result.errorFamily).toBeUndefined();
|
||||
});
|
||||
|
||||
it("arms the bounded transient retry for a typed Codex model capacity failure", async () => {
|
||||
const title = "Selected model is at capacity. Please try a different model.";
|
||||
const { result } = await executeFailure(title, "service");
|
||||
|
||||
@@ -269,10 +269,17 @@ async function prepareCodexRemoteManagedHome(
|
||||
const CODEX_MODEL_CAPACITY_RE =
|
||||
/\b(?:selected model is at capacity|model is at capacity|at capacity for this model|serverOverloaded|server overloaded)\b/i;
|
||||
|
||||
const CODEX_PROVIDER_AUTH_RE =
|
||||
/\b(?:401 unauthorized|invalid_api_key|(?:incorrect|invalid) api key)\b/i;
|
||||
|
||||
export function classifyCodexTerminalSessionFailure(
|
||||
failure: AcpxTerminalSessionFailure,
|
||||
now: Date,
|
||||
): AcpxTerminalFailureClassification | null {
|
||||
if (failure.category === "access") {
|
||||
const text = [failure.title, failure.details].filter(Boolean).join("\n");
|
||||
return CODEX_PROVIDER_AUTH_RE.test(text) ? { errorCode: "acpx_auth_required" } : null;
|
||||
}
|
||||
if (failure.category === "service") {
|
||||
const text = [failure.title, failure.details].filter(Boolean).join("\n");
|
||||
return CODEX_MODEL_CAPACITY_RE.test(text)
|
||||
|
||||
Reference in new issue
Block a user