mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-11-13 07:53:41 -04:00
fix(gemini-vertex): doctor validates the Vertex credential before launch
The Vertex generation-readiness check unconditionally passed ("relying on
ambient ADC"), so a fresh env with a project but no resolvable ADC passed the
doctor that provider-launch runs as its preflight, then `node bin/openclaude`
failed startup validation. Reuse the runtime resolveGeminiCredential() (mapping
GEMINI_VERTEX_AUTH_MODE -> GEMINI_AUTH_MODE and clearing API keys, exactly like
the native client) and fail when the credential cannot be resolved, so the
preflight matches the provider that will actually run. Also clarify the
GEMINI_VERTEX_AUTH line that ambient ADC is validated by the readiness check.
Tests: readiness passes when a credential resolves and fails when none does.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
80583a5ed7
commit
8fb16561ed
@@ -495,4 +495,32 @@ describe('doctor recognises Gemini Vertex', () => {
|
||||
expect(summary.GEMINI_VERTEX_PROJECT).toBe('my-proj')
|
||||
expect(summary.GEMINI_VERTEX_CREDENTIAL_SET).toBe(true)
|
||||
})
|
||||
|
||||
test('generation readiness passes when a Vertex credential resolves', async () => {
|
||||
const { __test } = await import('./system-check.ts')
|
||||
for (const k of FLAGS) delete process.env[k]
|
||||
process.env.CLAUDE_CODE_USE_GEMINI_VERTEX = '1'
|
||||
process.env.GEMINI_VERTEX_PROJECT = 'my-proj'
|
||||
process.env.GEMINI_VERTEX_AUTH_MODE = 'access-token'
|
||||
process.env.GEMINI_ACCESS_TOKEN = 'tok'
|
||||
|
||||
const result = await __test.checkProviderGenerationReadiness()
|
||||
expect(result.ok).toBe(true)
|
||||
expect(result.detail).toContain('resolved')
|
||||
})
|
||||
|
||||
test('generation readiness fails when no Vertex credential resolves (preflight matches startup)', async () => {
|
||||
const { __test } = await import('./system-check.ts')
|
||||
for (const k of FLAGS) delete process.env[k]
|
||||
process.env.CLAUDE_CODE_USE_GEMINI_VERTEX = '1'
|
||||
process.env.GEMINI_VERTEX_PROJECT = 'my-proj'
|
||||
// Same fail branch the runtime resolver takes when ambient ADC cannot be
|
||||
// found: an explicit auth mode with no usable credential must NOT report a
|
||||
// false green, or the launcher preflight would pass and startup would fail.
|
||||
process.env.GEMINI_VERTEX_AUTH_MODE = 'access-token'
|
||||
|
||||
const result = await __test.checkProviderGenerationReadiness()
|
||||
expect(result.ok).toBe(false)
|
||||
expect(result.detail).toContain('could not be resolved')
|
||||
})
|
||||
})
|
||||
|
||||
+31
-4
@@ -26,7 +26,10 @@ import {
|
||||
redactSecretSubstringsForDisplay,
|
||||
type SecretValueSource,
|
||||
} from '../src/utils/providerSecrets.js'
|
||||
import { getGeminiVertexProjectId } from '../src/utils/geminiAuth.js'
|
||||
import {
|
||||
getGeminiVertexProjectId,
|
||||
resolveGeminiCredential,
|
||||
} from '../src/utils/geminiAuth.js'
|
||||
import { redactUrlForDisplay } from '../src/utils/urlRedaction.js'
|
||||
import {
|
||||
MIN_NODE_ENGINE_RANGE,
|
||||
@@ -430,7 +433,7 @@ function checkGeminiVertexEnv(): CheckResult[] {
|
||||
results.push(
|
||||
adcFile
|
||||
? pass('GEMINI_VERTEX_AUTH', 'ADC via GOOGLE_APPLICATION_CREDENTIALS.')
|
||||
: pass('GEMINI_VERTEX_AUTH', 'ADC mode — relying on ambient Google Application Default Credentials.'),
|
||||
: pass('GEMINI_VERTEX_AUTH', 'ADC mode — ambient Google ADC is validated by the generation-readiness check below.'),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -729,9 +732,29 @@ async function checkProviderGenerationReadiness(): Promise<CheckResult> {
|
||||
const useMistral = isTruthy(process.env.CLAUDE_CODE_USE_MISTRAL)
|
||||
|
||||
if (useGeminiVertex) {
|
||||
// Reuse the runtime credential resolver so this preflight matches what
|
||||
// startup/runtime will accept. Otherwise "relying on ambient ADC" is a
|
||||
// false green: a fresh env with a project but no resolvable ADC passes the
|
||||
// doctor, then `node bin/openclaude` fails startup validation. Map the
|
||||
// Vertex auth mode to GEMINI_AUTH_MODE and clear API keys, exactly like the
|
||||
// native client does, then fail when nothing actually resolves.
|
||||
const credential = await resolveGeminiCredential({
|
||||
...process.env,
|
||||
GEMINI_AUTH_MODE:
|
||||
process.env.GEMINI_VERTEX_AUTH_MODE ??
|
||||
(process.env.GEMINI_ACCESS_TOKEN ? 'access-token' : 'adc'),
|
||||
GEMINI_API_KEY: undefined,
|
||||
GOOGLE_API_KEY: undefined,
|
||||
})
|
||||
if (credential.kind === 'none') {
|
||||
return fail(
|
||||
'Provider generation readiness',
|
||||
'Gemini Vertex authentication could not be resolved. access-token mode needs GEMINI_ACCESS_TOKEN; ADC mode needs GOOGLE_APPLICATION_CREDENTIALS or ambient Google ADC (e.g. `gcloud auth application-default login`).',
|
||||
)
|
||||
}
|
||||
return pass(
|
||||
'Provider generation readiness',
|
||||
'Skipped for Gemini Vertex (native generateContent flow; env/credential checks above cover setup).',
|
||||
`Gemini Vertex credential resolved (${credential.kind}).`,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1029,4 +1052,8 @@ if (import.meta.main) {
|
||||
}
|
||||
|
||||
// Test-only surface for the provider dispatch.
|
||||
export const __test = { checkOpenAIEnv, serializeSafeEnvSummary }
|
||||
export const __test = {
|
||||
checkOpenAIEnv,
|
||||
serializeSafeEnvSummary,
|
||||
checkProviderGenerationReadiness,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user