Skip to content

Commit 4ee7a29

Browse files
committed
feat: implement API key validation and configuration UI for providers
1 parent 3aec50c commit 4ee7a29

File tree

2 files changed

+222
-91
lines changed

2 files changed

+222
-91
lines changed

app.py

Lines changed: 106 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,70 @@ def is_ollama_available() -> bool:
100100
return False
101101

102102

103+
def _check_api_key_validity(provider: str) -> bool:
104+
"""
105+
Check if API key for a provider is valid and configured using actual connection tests.
106+
107+
Args:
108+
provider: The provider name (openai, google, ollama)
109+
110+
Returns:
111+
True if API key is valid, False otherwise
112+
"""
113+
logger.debug("Checking API key validity for provider: %s", provider)
114+
115+
try:
116+
from src.ui.settings_page import (
117+
_test_google_connection,
118+
_test_ollama_connection,
119+
_test_openai_connection,
120+
)
121+
122+
if provider == "openai":
123+
api_key = os.getenv("OPENAI_API_KEY", "").strip()
124+
if not api_key:
125+
logger.debug("OpenAI API key not configured")
126+
return False
127+
# Test the connection
128+
model = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
129+
success, _ = _test_openai_connection(api_key, model)
130+
logger.debug("OpenAI API key validity: %s", success)
131+
return success
132+
133+
elif provider == "google":
134+
api_key = os.getenv("GOOGLE_API_KEY", "").strip()
135+
if not api_key:
136+
logger.debug("Google API key not configured")
137+
return False
138+
# Test the connection
139+
model = os.getenv("GOOGLE_MODEL", "gemini-2.0-flash-exp")
140+
success, _ = _test_google_connection(api_key, model)
141+
logger.debug("Google API key validity: %s", success)
142+
return success
143+
144+
elif provider == "ollama":
145+
# Ollama doesn't need API key, just needs to be running
146+
logger.debug("Ollama provider doesn't require API key validation")
147+
return is_ollama_available()
148+
149+
else:
150+
logger.warning("Unknown provider: %s", provider)
151+
return False
152+
153+
except Exception as e:
154+
logger.error("Error checking API key validity for %s: %s", provider, str(e))
155+
return False
156+
157+
103158
def get_available_providers() -> list:
104159
"""
105-
Get list of available providers.
106-
Ollama is only available if it's running.
160+
Get list of available providers with valid API keys.
161+
Only returns providers that have valid credentials configured.
107162
108163
Returns:
109164
List of available provider names
110165
"""
111-
logger.debug("Getting available providers")
166+
logger.debug("Getting available providers with valid API keys")
112167

113168
all_providers = list_providers()
114169
logger.debug("All registered providers: %s", all_providers)
@@ -123,9 +178,14 @@ def get_available_providers() -> list:
123178
else:
124179
logger.debug("Ollama is not available")
125180
else:
126-
# Google and OpenAI are always available (if API keys are set, they'll work)
127-
available.append(provider)
128-
logger.debug("Provider %s is available", provider)
181+
# Check if API key is valid for Google and OpenAI
182+
if _check_api_key_validity(provider):
183+
available.append(provider)
184+
logger.debug("Provider %s is available with valid API key", provider)
185+
else:
186+
logger.debug(
187+
"Provider %s is not available (no valid API key)", provider
188+
)
129189

130190
logger.info("Available providers: %s", available)
131191
return available
@@ -483,6 +543,10 @@ def _initialize_session_state():
483543
False,
484544
"Initialized show_settings session state to False",
485545
),
546+
"skip_initial_settings": (
547+
False,
548+
"Initialized skip_initial_settings session state to False",
549+
),
486550
}
487551

488552
for key, (default_value, debug_message) in session_state_defaults.items():
@@ -552,6 +616,11 @@ def _show_provider_selection():
552616
use_container_width=True,
553617
)
554618

619+
if st.button("🔑 Configure API Keys", use_container_width=True):
620+
logger.info("Opening API configuration from provider selection")
621+
st.session_state.show_settings = True
622+
st.rerun()
623+
555624
st.divider()
556625
st.info(
557626
"💡 **Tip:** Ollama is free and runs locally. "
@@ -699,7 +768,7 @@ def _setup_sidebar(chatbot_agent, financial_advisor_agent):
699768
st.session_state.agent_is_healthy = False
700769
st.session_state.profile_loaded_from_json = False
701770
st.success("Conversation cleared!")
702-
771+
703772
# API Configuration button
704773
if st.button("🔑 API Configuration", use_container_width=True):
705774
logger.info("Opening API configuration settings")
@@ -1585,8 +1654,36 @@ def main():
15851654

15861655
# Initialize session state
15871656
_initialize_session_state()
1588-
1589-
# Show settings page if requested
1657+
1658+
# Check if any providers are available
1659+
available_providers = get_available_providers()
1660+
logger.debug("Available providers on startup: %s", available_providers)
1661+
1662+
# Show API key configuration on first load only if NO providers are available
1663+
if not st.session_state.skip_initial_settings and not available_providers:
1664+
logger.debug(
1665+
"First load with no available providers - showing API key configuration page"
1666+
)
1667+
_show_header()
1668+
st.subheader("🔑 Configure Your API Keys")
1669+
st.markdown(
1670+
"Welcome! No LLM providers are currently configured. Let's set up your API keys and LLM provider settings before we get started."
1671+
)
1672+
show_settings_page()
1673+
1674+
# Add button to proceed to provider selection
1675+
if st.button("✅ Continue to Provider Selection", use_container_width=True):
1676+
logger.info("User proceeding to provider selection after configuration")
1677+
st.session_state.skip_initial_settings = True
1678+
st.rerun()
1679+
return
1680+
1681+
# Mark initial settings as skipped if we reach here (at least one provider is available)
1682+
if not st.session_state.skip_initial_settings and available_providers:
1683+
logger.debug("Skipping initial settings - at least one provider is available")
1684+
st.session_state.skip_initial_settings = True
1685+
1686+
# Show settings page if requested from sidebar
15901687
if st.session_state.get("show_settings", False):
15911688
show_settings_page()
15921689
return

0 commit comments

Comments
 (0)