Files
orca/src/shared/codex-auth-errors.ts
T
NeilandBrennan Benson 9f30a780f5 fix(codex): prevent transient managed-auth onboarding (#11731)
* fix(codex): gate terminal spawn on managed auth readiness

* fix(codex): recover unavailable managed auth safely

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-07-31 14:40:46 -07:00

70 lines
2.1 KiB
TypeScript

const CODEX_AUTH_ERROR_PATTERNS = [
/access token could not be refreshed/i,
/authentication session could not be refreshed/i,
/refresh token (?:has expired|was already used|was revoked)/i,
/you have since logged out or signed in to another account/i,
/please (?:log out and )?sign in again/i,
/please reauthenticate/i,
/not logged in/i,
/sign in with chatgpt/i,
/token data is not available/i,
/auth (?:is missing|tokens are missing|does not expose)/i,
// Why: app-server rejects account/rateLimits/read with this when auth.json
// holds only an API key; without classification the fetcher falls through to
// a hidden PTY probe that can only time out (15s) on every refresh.
/chatgpt authentication required/i
]
const ANSI_ESCAPE_RE = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*[a-zA-Z]`, 'g')
export function isCodexAuthError(error: string | null | undefined): boolean {
const message = error?.trim()
if (!message) {
return false
}
return CODEX_AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message))
}
export function extractCodexAuthError(output: string | null | undefined): string | null {
if (!output) {
return null
}
let cleanPrefix = ''
for (const rawLine of iterateCodexOutputLines(output)) {
const line = rawLine.replace(ANSI_ESCAPE_RE, '').trim()
if (!line) {
continue
}
if (isCodexAuthError(line)) {
return line.slice(0, 4_000)
}
if (cleanPrefix.length < 4_000) {
cleanPrefix = cleanPrefix ? `${cleanPrefix}\n${line}` : line
cleanPrefix = cleanPrefix.slice(0, 4_000)
}
}
return isCodexAuthError(cleanPrefix) ? cleanPrefix : null
}
function* iterateCodexOutputLines(output: string): Generator<string> {
let lineStart = 0
for (let index = 0; index < output.length; index++) {
const code = output.charCodeAt(index)
if (code !== 10 && code !== 13) {
continue
}
yield output.slice(lineStart, index)
if (code === 13 && output.charCodeAt(index + 1) === 10) {
index++
}
lineStart = index + 1
}
if (lineStart <= output.length) {
yield output.slice(lineStart)
}
}