fix: allow provider recovery during startup (#765)
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
|||||||
} from '../utils/providerProfile.js'
|
} from '../utils/providerProfile.js'
|
||||||
import {
|
import {
|
||||||
getProviderValidationError,
|
getProviderValidationError,
|
||||||
validateProviderEnvOrExit,
|
validateProviderEnvForStartupOrExit,
|
||||||
} from '../utils/providerValidation.js'
|
} from '../utils/providerValidation.js'
|
||||||
|
|
||||||
// OpenClaude: polyfill globalThis.File for Node < 20.
|
// OpenClaude: polyfill globalThis.File for Node < 20.
|
||||||
@@ -132,7 +132,7 @@ async function main(): Promise<void> {
|
|||||||
hydrateGithubModelsTokenFromSecureStorage()
|
hydrateGithubModelsTokenFromSecureStorage()
|
||||||
}
|
}
|
||||||
|
|
||||||
await validateProviderEnvOrExit()
|
await validateProviderEnvForStartupOrExit()
|
||||||
|
|
||||||
// Print the gradient startup screen before the Ink UI loads
|
// Print the gradient startup screen before the Ink UI loads
|
||||||
const { printStartupScreen } = await import('../components/StartupScreen.js')
|
const { printStartupScreen } = await import('../components/StartupScreen.js')
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { afterEach, expect, test } from 'bun:test'
|
import { afterEach, expect, test } from 'bun:test'
|
||||||
|
|
||||||
import { getProviderValidationError } from './providerValidation.ts'
|
import {
|
||||||
|
getProviderValidationError,
|
||||||
|
shouldExitForStartupProviderValidationError,
|
||||||
|
} from './providerValidation.ts'
|
||||||
|
|
||||||
const originalEnv = {
|
const originalEnv = {
|
||||||
CLAUDE_CODE_USE_OPENAI: process.env.CLAUDE_CODE_USE_OPENAI,
|
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('Saved startup settings can come from')
|
||||||
expect(message).toContain('.openclaude-profile.json')
|
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)
|
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