Avoid Gemini readiness without a selected auth mode

Treat stale OAuth files and unrelated API keys as unverified when the native noninteractive CLI has no selected authentication.

Checks: 108 Gemini readiness tests; desktop packaging; git diff --check.
This commit is contained in:
Ryder Sun committed 2026-11-07 20:16:54 +08:00
1 parent ac78959842
commit d42f974d4e
3 files changed
+9 -1

No files matched your search

+1 -1
View File
@@ -817,7 +817,7 @@ function nativeCredentialState(kind, options = {}) {
return found ? { state: 'ready', source: options.credentialSource === 'native-shell' ? 'native-shell' : 'native-credential' }
: { state: 'unknown', source: 'unverified' }
}
if (selection.authType) return { state: 'unknown', source: 'unverified' }
return { state: 'unknown', source: 'unverified' }
}
const expandHome = value => String(value).replace(/^~(?=$|[\\/])/, home)
const piHome = env.PI_CODING_AGENT_DIR ? expandHome(env.PI_CODING_AGENT_DIR) : path.join(home, '.pi', 'agent')
@@ -34,7 +34,11 @@ test('Gemini readiness checks credentials for its selected auth mode', t => {
t.after(() => fs.rmSync(home, { recursive: true, force: true }))
const root = path.join(home, '.gemini')
fs.mkdirSync(root)
fs.writeFileSync(path.join(root, 'oauth_creds.json'), JSON.stringify({ refresh_token: 'oauth-token' }))
const noSelection = { GEMINI_CLI_SYSTEM_SETTINGS_PATH: path.join(home, 'system.json'), GOOGLE_API_KEY: 'unrelated' }
assert.deepEqual(nativeCredentialState('gemini', { home, env: noSelection }), { state: 'unknown', source: 'unverified' })
const env = { GEMINI_CLI_SYSTEM_SETTINGS_PATH: path.join(home, 'system.json'), GEMINI_CLI_AUTH_OVERRIDE: 'oauth-personal', GEMINI_API_KEY: 'unrelated' }
fs.unlinkSync(path.join(root, 'oauth_creds.json'))
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'unknown', source: 'unverified' })
fs.writeFileSync(path.join(root, 'oauth_creds.json'), JSON.stringify({ refresh_token: 'oauth-token' }))
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'ready', source: 'native-credential' })
@@ -220,6 +220,7 @@ test('Gemini uses its shell-selected native home for readiness and execution', a
assert.deepEqual(native, { GEMINI_CLI_HOME: selected })
assert.equal(nativeCredentialState('gemini', { home, env: native }).state, 'unknown')
fs.writeFileSync(path.join(selectedConfig, 'oauth_creds.json'), JSON.stringify({ refresh_token: 'selected-secret' }))
fs.writeFileSync(path.join(selectedConfig, 'settings.json'), JSON.stringify({ security: { auth: { selectedType: 'oauth-personal' } } }))
assert.equal(nativeCredentialState('gemini', { home, env: native }).state, 'ready')
assert.equal(childEnvironment({ kind: 'gemini' }, home, { env: native }, 'darwin').GEMINI_CLI_HOME, selected)
assert.deepEqual(nativeCredentialEnvironment('codex', captured.env), {})
@@ -1319,6 +1320,9 @@ test('native readiness recognizes credential files for every supported CLI', ()
fs.mkdirSync(path.dirname(filename), { recursive: true })
fs.writeFileSync(filename, JSON.stringify(value))
}
fs.writeFileSync(path.join(home, '.gemini', 'settings.json'), JSON.stringify({
security: { auth: { selectedType: 'oauth-personal' } },
}))
for (const [kind] of fixtures) {
assert.deepEqual(nativeCredentialState(kind, { home, env: {} }), {
state: 'ready', source: 'native-credential',