Recognize sign-in failures for every agent and fall through
Codex re-runs device login on revoked, expired, or reused sessions and token_revoked/401 errors, not only invalid_refresh_token. Claude and OpenCode credential rejections are classified too. Sign-in failures fall through to the next profile, and the failure comment names each tried profile with a fixed reason label.
This commit is contained in:
+47
-9
@@ -10,7 +10,7 @@ const context: PostContext = {
|
||||
};
|
||||
|
||||
async function fixture(
|
||||
source: { ok: false } | { ok: true; body: string },
|
||||
source: Extract<RuntimeOutcome, { ok: false }> | { ok: true; body: string },
|
||||
review?: string,
|
||||
anchors?: unknown,
|
||||
): Promise<{
|
||||
@@ -138,8 +138,15 @@ Deno.test("retries a rejected inline review without anchors", async () => {
|
||||
assert(await missing(result.runtimeDir));
|
||||
});
|
||||
|
||||
Deno.test("reports a generic agent failure and keeps the action failed", async () => {
|
||||
const result = await fixture({ ok: false });
|
||||
Deno.test("reports each tried profile and keeps the action failed", async () => {
|
||||
const result = await fixture({
|
||||
ok: false,
|
||||
failures: [
|
||||
{ type: "codex", model: "gpt-test", reason: "sign-in failed" },
|
||||
{ type: "claude", model: "claude-test", reason: "usage exhausted" },
|
||||
{ type: "opencode", model: "openrouter/test", reason: "failed" },
|
||||
],
|
||||
});
|
||||
const bodies: unknown[] = [];
|
||||
|
||||
await assertRejects(
|
||||
@@ -153,14 +160,47 @@ Deno.test("reports a generic agent failure and keeps the action failed", async (
|
||||
);
|
||||
|
||||
assertEquals(bodies, [{
|
||||
body: "AI bot failed.\n\n> Profile: none · all profiles failed",
|
||||
body: "AI bot failed.\n\n> Tried: `codex` · `gpt-test` (sign-in failed), " +
|
||||
"`claude` · `claude-test` (usage exhausted), " +
|
||||
"`opencode` · `openrouter/test` (failed)",
|
||||
}]);
|
||||
assert(!JSON.stringify(bodies).includes("reviewer-secret"));
|
||||
assert(await missing(result.runtimeDir));
|
||||
});
|
||||
|
||||
Deno.test("drops failure entries that are not known labels", async () => {
|
||||
const result = await fixture({ ok: false, failures: [] });
|
||||
await Deno.writeTextFile(
|
||||
result.outcomeFile,
|
||||
JSON.stringify({
|
||||
ok: false,
|
||||
failures: [
|
||||
{ type: "codex", model: "gpt-test", reason: "token sk-secret leaked" },
|
||||
{ type: "shell", model: "x", reason: "failed" },
|
||||
{ type: "claude", model: "claude-test", reason: "sign-in failed" },
|
||||
],
|
||||
}),
|
||||
);
|
||||
const bodies: unknown[] = [];
|
||||
|
||||
await assertRejects(
|
||||
() =>
|
||||
postRuntime(result.manifestPath, context, (_url, init) => {
|
||||
bodies.push(JSON.parse(String(init?.body)));
|
||||
return Promise.resolve(new Response(null, { status: 201 }));
|
||||
}),
|
||||
Error,
|
||||
"agent phase failed",
|
||||
);
|
||||
|
||||
assertEquals(bodies, [{
|
||||
body:
|
||||
"AI bot failed.\n\n> Tried: `claude` · `claude-test` (sign-in failed)",
|
||||
}]);
|
||||
});
|
||||
|
||||
Deno.test("reports a generic failure when the runner wrote no outcome", async () => {
|
||||
const result = await fixture({ ok: false });
|
||||
const result = await fixture({ ok: false, failures: [] });
|
||||
await Deno.remove(result.outcomeFile);
|
||||
const bodies: unknown[] = [];
|
||||
|
||||
@@ -174,9 +214,7 @@ Deno.test("reports a generic failure when the runner wrote no outcome", async ()
|
||||
"agent phase failed",
|
||||
);
|
||||
|
||||
assertEquals(bodies, [{
|
||||
body: "AI bot failed.\n\n> Profile: none · all profiles failed",
|
||||
}]);
|
||||
assertEquals(bodies, [{ body: "AI bot failed.\n\n> Profile: none" }]);
|
||||
assert(await missing(result.runtimeDir));
|
||||
});
|
||||
|
||||
@@ -252,7 +290,7 @@ Deno.test("reports an attributed failure when a pull request review is missing",
|
||||
);
|
||||
|
||||
assertEquals(bodies, [{
|
||||
body: "AI bot failed.\n\n> Profile: none · all profiles failed",
|
||||
body: "AI bot failed.\n\n> Tried: `codex` · `gpt-test` (failed)",
|
||||
}]);
|
||||
assert(await missing(result.runtimeDir));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user