Onboarding Manager and Router Manager refactored, analytics and background jobs added, database setup updated, environment setup updated, frontend updated, backend updated. Critical onboarding database migration implemented.
193 lines
8.5 KiB
Python
193 lines
8.5 KiB
Python
"""
|
|
Onboarding Summary Service
|
|
Handles the complex logic for generating comprehensive onboarding summaries.
|
|
"""
|
|
|
|
from typing import Dict, Any, Optional
|
|
from fastapi import HTTPException
|
|
from loguru import logger
|
|
|
|
from services.api_key_manager import get_api_key_manager
|
|
from services.database import get_db
|
|
from services.onboarding_database_service import OnboardingDatabaseService
|
|
from services.website_analysis_service import WebsiteAnalysisService
|
|
from services.research_preferences_service import ResearchPreferencesService
|
|
from services.persona_analysis_service import PersonaAnalysisService
|
|
|
|
class OnboardingSummaryService:
|
|
"""Service for handling onboarding summary generation with user isolation."""
|
|
|
|
def __init__(self, user_id: str):
|
|
"""
|
|
Initialize service with user-specific context.
|
|
|
|
Args:
|
|
user_id: Clerk user ID from authenticated request
|
|
"""
|
|
self.user_id = user_id # Store Clerk user ID (string)
|
|
self.db_service = OnboardingDatabaseService()
|
|
|
|
logger.info(f"OnboardingSummaryService initialized for user {user_id} (database mode)")
|
|
|
|
async def get_onboarding_summary(self) -> Dict[str, Any]:
|
|
"""Get comprehensive onboarding summary for FinalStep."""
|
|
try:
|
|
# Get API keys
|
|
api_keys = self._get_api_keys()
|
|
|
|
# Get website analysis data
|
|
website_analysis = self._get_website_analysis()
|
|
|
|
# Get research preferences
|
|
research_preferences = self._get_research_preferences()
|
|
|
|
# Get personalization settings
|
|
personalization_settings = self._get_personalization_settings(research_preferences)
|
|
|
|
# Check persona generation readiness
|
|
persona_readiness = self._check_persona_readiness(website_analysis)
|
|
|
|
# Determine capabilities
|
|
capabilities = self._determine_capabilities(api_keys, website_analysis, research_preferences, personalization_settings, persona_readiness)
|
|
|
|
return {
|
|
"api_keys": api_keys,
|
|
"website_url": website_analysis.get('website_url') if website_analysis else None,
|
|
"style_analysis": website_analysis.get('style_analysis') if website_analysis else None,
|
|
"research_preferences": research_preferences,
|
|
"personalization_settings": personalization_settings,
|
|
"persona_readiness": persona_readiness,
|
|
"integrations": {}, # TODO: Implement integrations data
|
|
"capabilities": capabilities
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error getting onboarding summary: {str(e)}")
|
|
raise HTTPException(status_code=500, detail="Internal server error")
|
|
|
|
def _get_api_keys(self) -> Dict[str, Any]:
|
|
"""Get configured API keys from database."""
|
|
try:
|
|
db = next(get_db())
|
|
api_keys = self.db_service.get_api_keys(self.user_id, db)
|
|
db.close()
|
|
|
|
if not api_keys:
|
|
return {
|
|
"openai": {"configured": False, "value": None},
|
|
"anthropic": {"configured": False, "value": None},
|
|
"google": {"configured": False, "value": None}
|
|
}
|
|
|
|
return {
|
|
"openai": {
|
|
"configured": bool(api_keys.get('openai_api_key')),
|
|
"value": api_keys.get('openai_api_key')[:8] + "..." if api_keys.get('openai_api_key') else None
|
|
},
|
|
"anthropic": {
|
|
"configured": bool(api_keys.get('anthropic_api_key')),
|
|
"value": api_keys.get('anthropic_api_key')[:8] + "..." if api_keys.get('anthropic_api_key') else None
|
|
},
|
|
"google": {
|
|
"configured": bool(api_keys.get('google_api_key')),
|
|
"value": api_keys.get('google_api_key')[:8] + "..." if api_keys.get('google_api_key') else None
|
|
}
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Error getting API keys: {str(e)}")
|
|
return {
|
|
"openai": {"configured": False, "value": None},
|
|
"anthropic": {"configured": False, "value": None},
|
|
"google": {"configured": False, "value": None}
|
|
}
|
|
|
|
def _get_website_analysis(self) -> Optional[Dict[str, Any]]:
|
|
"""Get website analysis data from database."""
|
|
try:
|
|
db = next(get_db())
|
|
website_data = self.db_service.get_website_analysis(self.user_id, db)
|
|
db.close()
|
|
return website_data
|
|
except Exception as e:
|
|
logger.error(f"Error getting website analysis: {str(e)}")
|
|
return None
|
|
|
|
async def get_website_analysis_data(self) -> Dict[str, Any]:
|
|
"""Get website analysis data for API endpoint."""
|
|
try:
|
|
website_analysis = self._get_website_analysis()
|
|
return {
|
|
"website_analysis": website_analysis,
|
|
"status": "success" if website_analysis else "no_data"
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Error in get_website_analysis_data: {str(e)}")
|
|
raise e
|
|
|
|
def _get_research_preferences(self) -> Optional[Dict[str, Any]]:
|
|
"""Get research preferences from database."""
|
|
try:
|
|
db = next(get_db())
|
|
preferences = self.db_service.get_research_preferences(self.user_id, db)
|
|
db.close()
|
|
return preferences
|
|
except Exception as e:
|
|
logger.error(f"Error getting research preferences: {str(e)}")
|
|
return None
|
|
|
|
def _get_personalization_settings(self, research_preferences: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Get personalization settings based on research preferences."""
|
|
if not research_preferences:
|
|
return {
|
|
"writing_style": "professional",
|
|
"target_audience": "general",
|
|
"content_focus": "informative"
|
|
}
|
|
|
|
return {
|
|
"writing_style": research_preferences.get('writing_style', 'professional'),
|
|
"target_audience": research_preferences.get('target_audience', 'general'),
|
|
"content_focus": research_preferences.get('content_focus', 'informative')
|
|
}
|
|
|
|
def _check_persona_readiness(self, website_analysis: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Check if persona generation is ready based on available data."""
|
|
if not website_analysis:
|
|
return {
|
|
"ready": False,
|
|
"reason": "Website analysis not completed",
|
|
"missing_data": ["website_url", "style_analysis"]
|
|
}
|
|
|
|
required_fields = ['website_url', 'writing_style', 'target_audience']
|
|
missing_fields = [field for field in required_fields if not website_analysis.get(field)]
|
|
|
|
return {
|
|
"ready": len(missing_fields) == 0,
|
|
"reason": "All required data available" if len(missing_fields) == 0 else f"Missing: {', '.join(missing_fields)}",
|
|
"missing_data": missing_fields
|
|
}
|
|
|
|
def _determine_capabilities(self, api_keys: Dict[str, Any], website_analysis: Optional[Dict[str, Any]],
|
|
research_preferences: Optional[Dict[str, Any]],
|
|
personalization_settings: Dict[str, Any],
|
|
persona_readiness: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Determine available capabilities based on configured data."""
|
|
capabilities = {
|
|
"ai_content_generation": any(key.get("configured") for key in api_keys.values()),
|
|
"website_analysis": website_analysis is not None,
|
|
"research_capabilities": research_preferences is not None,
|
|
"persona_generation": persona_readiness.get("ready", False),
|
|
"content_optimization": website_analysis is not None and research_preferences is not None
|
|
}
|
|
|
|
return capabilities
|
|
|
|
async def get_research_preferences_data(self) -> Dict[str, Any]:
|
|
"""Get research preferences data for the user."""
|
|
try:
|
|
research_prefs_service = ResearchPreferencesService()
|
|
return await research_prefs_service.get_research_preferences(self.user_id)
|
|
except Exception as e:
|
|
logger.error(f"Error getting research preferences data: {e}")
|
|
raise |