From 7004a1a80568d8d62572dfa6640f6ae743cfeeb1 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Thu, 26 Feb 2026 09:40:58 -0800 Subject: [PATCH] fix(tui): only offer auth_mode prompt after successful credential storage Introduce a `credentialStored` flag in all 4 credential paths (OpenAI API key, OpenAI OAuth, Anthropic auth token, Anthropic API key). The auth_mode prompt is now gated on `credentialStored`, so a failed store call no longer falls through to prompt the user for an auth mode that was never set. Co-Authored-By: Claude Sonnet 4.6 --- src/frontends/tui/minimal.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/frontends/tui/minimal.ts b/src/frontends/tui/minimal.ts index 7c4322f..a7f2416 100644 --- a/src/frontends/tui/minimal.ts +++ b/src/frontends/tui/minimal.ts @@ -1178,12 +1178,14 @@ export class MinimalTui { console.log(`${colors.gray}Create a key at:${colors.reset} https://platform.openai.com/api-keys`); console.log(''); + let credentialStored = false; try { this.rl.pause(); const apiKey = await promptHidden('Enter OpenAI API key: '); storeOpenAIApiKey(apiKey); console.log(''); console.log(`${colors.gray}OpenAI API key stored in ~/.config/flynn/auth.json${colors.reset}\n`); + credentialStored = true; } catch (error) { const message = error instanceof Error ? error.message : String(error); console.log(`${colors.gray}OpenAI API key storage failed:${colors.reset} ${message}\n`); @@ -1192,7 +1194,7 @@ export class MinimalTui { } // Offer to set auth_mode if config is available - if (this.config.currentConfig && this.config.configPath) { + if (credentialStored && this.config.currentConfig && this.config.configPath) { const modeInput = (await this.prompt( `${colors.orange}Set active auth mode?${colors.reset} ${colors.gray}[api_key/oauth/auto/skip] (default: skip):${colors.reset} `, )).trim().toLowerCase(); @@ -1218,6 +1220,7 @@ export class MinimalTui { console.log(`${colors.gray}Starting OpenAI OAuth device flow...${colors.reset}`); + let credentialStored = false; try { await loginOpenAI((userCode, verificationUri) => { console.log(''); @@ -1228,13 +1231,14 @@ export class MinimalTui { }); console.log(`${colors.gray}OpenAI authentication successful! Token stored.${colors.reset}\n`); + credentialStored = true; } catch (error) { const message = error instanceof Error ? error.message : String(error); console.log(`${colors.gray}OpenAI login failed:${colors.reset} ${message}\n`); } // Offer to set auth_mode if config is available - if (this.config.currentConfig && this.config.configPath) { + if (credentialStored && this.config.currentConfig && this.config.configPath) { const modeInput = (await this.prompt( `${colors.orange}Set active auth mode?${colors.reset} ${colors.gray}[api_key/oauth/auto/skip] (default: skip):${colors.reset} `, )).trim().toLowerCase(); @@ -1270,12 +1274,14 @@ export class MinimalTui { console.log(`${colors.gray}Anthropic supports token-style auth (provider-specific).${colors.reset}`); console.log(''); + let credentialStored = false; try { this.rl.pause(); const token = await promptHidden('Enter Anthropic auth token: '); storeAnthropicAuthToken(token); console.log(''); console.log(`${colors.gray}Anthropic auth token stored in ~/.config/flynn/auth.json${colors.reset}\n`); + credentialStored = true; } catch (error) { const message = error instanceof Error ? error.message : String(error); console.log(`${colors.gray}Anthropic auth failed:${colors.reset} ${message}\n`); @@ -1284,7 +1290,7 @@ export class MinimalTui { } // Offer to set auth_mode if config is available - if (this.config.currentConfig && this.config.configPath) { + if (credentialStored && this.config.currentConfig && this.config.configPath) { const modeInput = (await this.prompt( `${colors.orange}Set active auth mode?${colors.reset} ${colors.gray}[api_key/oauth/auto/skip] (default: skip):${colors.reset} `, )).trim().toLowerCase(); @@ -1311,12 +1317,14 @@ export class MinimalTui { console.log(`${colors.gray}Create a key at:${colors.reset} https://console.anthropic.com/settings/keys`); console.log(''); + let credentialStored = false; try { this.rl.pause(); const apiKey = await promptHidden('Enter Anthropic API key: '); storeAnthropicAuth(apiKey); console.log(''); console.log(`${colors.gray}Anthropic API key stored in ~/.config/flynn/auth.json${colors.reset}\n`); + credentialStored = true; } catch (error) { const message = error instanceof Error ? error.message : String(error); console.log(`${colors.gray}Anthropic auth failed:${colors.reset} ${message}\n`); @@ -1325,7 +1333,7 @@ export class MinimalTui { } // Offer to set auth_mode if config is available - if (this.config.currentConfig && this.config.configPath) { + if (credentialStored && this.config.currentConfig && this.config.configPath) { const modeInput = (await this.prompt( `${colors.orange}Set active auth mode?${colors.reset} ${colors.gray}[api_key/oauth/auto/skip] (default: skip):${colors.reset} `, )).trim().toLowerCase();