fix: recover Codex rotation auth failures
- mark Codex bearer/refresh failures as terminal auth-expired states - sync refreshed session auth back to rotation slots and revive refreshed dead_auth slots - stop paired arbiter retry loops when Codex accounts are unavailable - add regression coverage for rotation leases, follow-up suppression, and arbiter closure
This commit is contained in:
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
classifyAgentError,
|
||||
classifyClaudeAuthError,
|
||||
classifyCodexAuthError,
|
||||
detectClaudeProviderFailureMessage,
|
||||
isClaudeOrgAccessDeniedMessage,
|
||||
shouldRotateClaudeToken,
|
||||
@@ -66,6 +67,32 @@ describe('agent-error-detection', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('classifies Codex reused refresh-token errors as auth-expired', () => {
|
||||
expect(
|
||||
classifyCodexAuthError(
|
||||
'Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.',
|
||||
),
|
||||
).toEqual({
|
||||
category: 'auth-expired',
|
||||
reason: 'auth-expired',
|
||||
});
|
||||
});
|
||||
|
||||
it('classifies a Codex auth-expired trigger reason as auth-expired', () => {
|
||||
expect(classifyCodexAuthError('auth-expired')).toEqual({
|
||||
category: 'auth-expired',
|
||||
reason: 'auth-expired',
|
||||
});
|
||||
});
|
||||
|
||||
it('classifies Codex workspace credit exhaustion as rate-limit', () => {
|
||||
expect(classifyAgentError('Workspace out of credits')).toEqual({
|
||||
category: 'rate-limit',
|
||||
reason: '429',
|
||||
retryAfterMs: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('marks only Claude quota/auth reasons as Claude rotation reasons', () => {
|
||||
expect(shouldRotateClaudeToken('429')).toBe(true);
|
||||
expect(shouldRotateClaudeToken('usage-exhausted')).toBe(true);
|
||||
|
||||
Reference in New Issue
Block a user