fix: allow provider recovery during startup (#765)
This commit is contained in:
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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.`,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user