"""AI providers setup component.""" import streamlit as st from loguru import logger from typing import Dict, Any from ..manager import APIKeyManager from .base import render_navigation_buttons, render_step_indicator, render_tab_style from ..wizard_state import next_step, update_progress from datetime import datetime import os from dotenv import load_dotenv def validate_api_key(key: str) -> bool: """Validate if an API key is properly formatted.""" if not key: return False # Basic validation - check if key is not empty and has minimum length return len(key.strip()) > 0 def save_to_env_file(key_name: str, key_value: str) -> bool: """Save API key to .env file.""" try: env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))), '.env') # Read existing .env file env_contents = [] if os.path.exists(env_path): with open(env_path, 'r') as f: env_contents = f.readlines() # Check if key already exists key_exists = False for i, line in enumerate(env_contents): if line.startswith(f"{key_name}="): env_contents[i] = f"{key_name}={key_value}\n" key_exists = True break # Add new key if it doesn't exist if not key_exists: env_contents.append(f"{key_name}={key_value}\n") # Write back to .env file with open(env_path, 'w') as f: f.writelines(env_contents) # Reload environment variables to ensure consistency load_dotenv(override=True) logger.info(f"[save_to_env_file] Successfully saved {key_name} to .env file") return True except Exception as e: logger.error(f"[save_to_env_file] Error saving to .env file: {str(e)}") return False def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]: """Render the AI providers setup step.""" logger.info("[render_ai_providers] Starting AI providers setup") try: # Load environment variables load_dotenv(override=True) # Get existing API keys from .env openai_key = os.getenv('OPENAI_API_KEY', '') gemini_key = os.getenv('GEMINI_API_KEY', '') # Initialize wizard state if not already initialized if 'wizard_state' not in st.session_state: st.session_state.wizard_state = { 'current_step': 1, 'total_steps': 6, 'progress': 0, 'completed_steps': set(), 'last_updated': datetime.now() } logger.info("[render_ai_providers] Initialized wizard state") # Store API key manager in session state for update_progress st.session_state['api_key_manager'] = api_key_manager # Main content st.markdown("""

🤖 AI LLM Providers Setup

""", unsafe_allow_html=True) # Create tabs for different AI providers tabs = st.tabs(["Primary Providers", "Additional Providers"]) # Track if any changes were made changes_made = False has_valid_key = False validation_message = "" with tabs[0]: st.markdown("### Primary AI Providers") # Create a grid layout for AI provider cards col1, col2 = st.columns(2) with col1: # OpenAI Card with st.container(): openai_input = st.text_input( "OpenAI API Key", value=openai_key, type="password", key="openai_key", help="Enter your OpenAI API key", placeholder="Power your content generation with GPT-4 AI models" ) if openai_key: st.success("✅ OpenAI API key found in environment") elif openai_input: if validate_api_key(openai_input): st.markdown("""
✓ API key configured
""", unsafe_allow_html=True) else: st.markdown("""
⚠️ Invalid API key format
""", unsafe_allow_html=True) with st.expander("📋 How to get your OpenAI API key", expanded=False): st.markdown(""" **Step-by-step guide:** 1. Go to [OpenAI's website](https://platform.openai.com) 2. Sign up or log in to your account 3. Navigate to the API section 4. Click "Create new secret key" 5. Copy the generated key and paste it here **Note:** Keep your API key secure and never share it publicly. """) with col2: # Google Card with st.container(): gemini_input = st.text_input( "Google Gemini API Key", value=gemini_key, type="password", key="google_key", help="Enter your Google API key", placeholder="Power your content generation with Gemini AI models" ) if gemini_key: st.success("✅ Gemini API key found in environment") elif gemini_input: if validate_api_key(gemini_input): st.markdown("""
✓ API key configured
""", unsafe_allow_html=True) else: st.markdown("""
⚠️ Invalid API key format
""", unsafe_allow_html=True) with st.expander("📋 How to get your Google API key", expanded=False): st.markdown(""" **Step-by-step guide:** 1. Visit [Google AI Studio](https://makersuite.google.com/app/apikey) 2. Sign in with your Google account 3. Click "Create API key" 4. Copy the generated key and paste it here **Note:** Make sure to enable the Gemini API in your Google Cloud Console. """) with tabs[1]: st.markdown("### Additional AI Providers") st.markdown("Configure additional AI providers for enhanced capabilities") # Create a grid layout for additional provider cards col1, col2 = st.columns(2) with col1: # Anthropic Card (Coming Soon) with st.container(): st.markdown("""
🧠
Anthropic Coming Soon

Access Claude for advanced content generation

""", unsafe_allow_html=True) st.info("Anthropic integration will be available in the next update") with col2: # Mistral Card (Coming Soon) with st.container(): st.markdown("""
Mistral Coming Soon

Use Mistral's efficient language models

""", unsafe_allow_html=True) st.info("Mistral integration will be available in the next update") # Track changes and validate keys if any([openai_input, gemini_input]): changes_made = True # Check if at least one valid API key is provided if validate_api_key(openai_input) or validate_api_key(gemini_input): has_valid_key = True validation_message = "✅ At least one AI provider configured successfully" else: validation_message = "⚠️ Please provide at least one valid API key" else: validation_message = "⚠️ Please configure at least one AI provider to continue" # Display validation message if validation_message: if "✅" in validation_message: st.success(validation_message) else: st.warning(validation_message) # Navigation buttons if render_navigation_buttons(1, 6, changes_made): if has_valid_key: # Save API keys to .env file if validate_api_key(openai_input): if save_to_env_file("OPENAI_API_KEY", openai_input): logger.info("[render_ai_providers] OpenAI API key saved to .env file") else: st.error("Failed to save OpenAI API key to .env file") return {"current_step": 1, "error": "Failed to save OpenAI API key"} if validate_api_key(gemini_input): if save_to_env_file("GEMINI_API_KEY", gemini_input): logger.info("[render_ai_providers] Google Gemini API key saved to .env file") else: st.error("Failed to save Gemini API key to .env file") return {"current_step": 1, "error": "Failed to save Gemini API key"} # Reload environment variables to ensure consistency load_dotenv(override=True) # Get updated API keys from environment updated_openai_key = os.getenv('OPENAI_API_KEY', '') updated_gemini_key = os.getenv('GEMINI_API_KEY', '') # Store the API keys in session state st.session_state['api_keys'] = { 'openai': updated_openai_key, 'google': updated_gemini_key } # Update progress and move to next step st.session_state['current_step'] = 2 # Set the next step explicitly update_progress() st.rerun() # Rerun to apply the changes else: st.error("Please configure at least one valid AI provider to continue") return {"current_step": 1, "changes_made": changes_made} except Exception as e: error_msg = f"Error in AI providers setup: {str(e)}" logger.error(f"[render_ai_providers] {error_msg}") st.error(error_msg) return {"current_step": 1, "error": error_msg}