fix: allow provider recovery during startup (#765)

This commit is contained in:
Kevin Codex
2026-04-20 06:46:05 +08:00
committed by GitHub
parent e6e8d9a248
commit f828171ef1
3 changed files with 89 additions and 3 deletions

View File

@@ -5,7 +5,7 @@ import {
} from '../utils/providerProfile.js'
import {
getProviderValidationError,
validateProviderEnvOrExit,
validateProviderEnvForStartupOrExit,
} from '../utils/providerValidation.js'
// OpenClaude: polyfill globalThis.File for Node < 20.
@@ -132,7 +132,7 @@ async function main(): Promise<void> {
hydrateGithubModelsTokenFromSecureStorage()
}
await validateProviderEnvOrExit()
await validateProviderEnvForStartupOrExit()
// Print the gradient startup screen before the Ink UI loads
const { printStartupScreen } = await import('../components/StartupScreen.js')

View File

@@ -1,6 +1,9 @@
import { afterEach, expect, test } from 'bun:test'
import { getProviderValidationError } from './providerValidation.ts'
import {
getProviderValidationError,
shouldExitForStartupProviderValidationError,
} from './providerValidation.ts'
const originalEnv = {
CLAUDE_CODE_USE_OPENAI: process.env.CLAUDE_CODE_USE_OPENAI,
@@ -93,3 +96,45 @@ test('openai missing key error includes recovery guidance and config locations',
expect(message).toContain('Saved startup settings can come from')
expect(message).toContain('.openclaude-profile.json')
})
test('startup provider validation allows interactive recovery', () => {
expect(
shouldExitForStartupProviderValidationError({
args: [],
stdoutIsTTY: true,
}),
).toBe(false)
})
test('startup provider validation stays strict for non-interactive launches', () => {
expect(
shouldExitForStartupProviderValidationError({
args: ['-p', 'hello'],
stdoutIsTTY: true,
}),
).toBe(true)
expect(
shouldExitForStartupProviderValidationError({
args: ['--print', 'hello'],
stdoutIsTTY: true,
}),
).toBe(true)
expect(
shouldExitForStartupProviderValidationError({
args: [],
stdoutIsTTY: false,
}),
).toBe(true)
expect(
shouldExitForStartupProviderValidationError({
args: ['--sdk-url', 'ws://127.0.0.1:3000'],
stdoutIsTTY: true,
}),
).toBe(true)
expect(
shouldExitForStartupProviderValidationError({
args: ['--sdk-url=ws://127.0.0.1:3000'],
stdoutIsTTY: true,
}),
).toBe(true)
})

View File

@@ -169,3 +169,44 @@ export async function validateProviderEnvOrExit(
process.exit(1)
}
}
export function shouldExitForStartupProviderValidationError(options: {
args?: string[]
stdoutIsTTY?: boolean
} = {}): boolean {
const args = options.args ?? process.argv.slice(2)
const stdoutIsTTY = options.stdoutIsTTY ?? process.stdout.isTTY
if (!stdoutIsTTY) {
return true
}
return (
args.includes('-p') ||
args.includes('--print') ||
args.includes('--init-only') ||
args.some(arg => arg.startsWith('--sdk-url'))
)
}
export async function validateProviderEnvForStartupOrExit(
env: NodeJS.ProcessEnv = process.env,
options?: {
args?: string[]
stdoutIsTTY?: boolean
},
): Promise<void> {
const error = await getProviderValidationError(env)
if (!error) {
return
}
if (shouldExitForStartupProviderValidationError(options)) {
console.error(error)
process.exit(1)
}
console.error(
`Warning: provider configuration is incomplete.\n${error}\nOpenClaude will continue starting so you can run /provider and repair the saved provider settings.`,
)
}