diff --git a/backend/igny8_core/ai/engine.py b/backend/igny8_core/ai/engine.py index 6cf27635..52a1f361 100644 --- a/backend/igny8_core/ai/engine.py +++ b/backend/igny8_core/ai/engine.py @@ -88,7 +88,8 @@ class AIEngine: function_id = f"ai-{function_id_base}-01-desktop" # Get model config from settings (Stage 4 requirement) - model_config = get_model_config(function_name) + # Pass account to read model from IntegrationSettings + model_config = get_model_config(function_name, account=self.account) model = model_config.get('model') self.console_tracker.ai_call(f"Calling {model or 'default'} model with {len(prompt)} char prompt") diff --git a/backend/igny8_core/ai/functions/generate_ideas.py b/backend/igny8_core/ai/functions/generate_ideas.py index c8f517ce..da519dd4 100644 --- a/backend/igny8_core/ai/functions/generate_ideas.py +++ b/backend/igny8_core/ai/functions/generate_ideas.py @@ -279,8 +279,8 @@ def generate_ideas_core(cluster_id: int, account_id: int = None, progress_callba tracker.prep("Building prompt...") prompt = fn.build_prompt(data, account) - # Get model config from settings - model_config = get_model_config('generate_ideas') + # Get model config from settings (pass account to read from IntegrationSettings) + model_config = get_model_config('generate_ideas', account=account) # Generate function_id for tracking (ai-generate-ideas-02 for legacy path) function_id = "ai-generate-ideas-02-desktop" diff --git a/backend/igny8_core/ai/settings.py b/backend/igny8_core/ai/settings.py index 097a0fa2..2b589ce7 100644 --- a/backend/igny8_core/ai/settings.py +++ b/backend/igny8_core/ai/settings.py @@ -46,12 +46,14 @@ FUNCTION_ALIASES = { } -def get_model_config(function_name: str) -> Dict[str, Any]: +def get_model_config(function_name: str, account=None) -> Dict[str, Any]: """ Get model configuration for an AI function. + Reads model from IntegrationSettings if account is provided, otherwise uses defaults. Args: function_name: AI function name (e.g., 'auto_cluster', 'generate_ideas') + account: Optional account object to read model from IntegrationSettings Returns: Dict with model, max_tokens, temperature, etc. @@ -59,8 +61,30 @@ def get_model_config(function_name: str) -> Dict[str, Any]: # Check aliases first actual_name = FUNCTION_ALIASES.get(function_name, function_name) - # Get config or return defaults - config = MODEL_CONFIG.get(actual_name, {}) + # Get base config + config = MODEL_CONFIG.get(actual_name, {}).copy() + + # Try to get model from IntegrationSettings if account is provided + model_from_settings = None + if account: + try: + from igny8_core.modules.system.models import IntegrationSettings + openai_settings = IntegrationSettings.objects.filter( + integration_type='openai', + account=account, + is_active=True + ).first() + if openai_settings and openai_settings.config: + model_from_settings = openai_settings.config.get('model') + if model_from_settings: + # Validate model is in our supported list + from igny8_core.utils.ai_processor import MODEL_RATES + if model_from_settings in MODEL_RATES: + config['model'] = model_from_settings + except Exception as e: + import logging + logger = logging.getLogger(__name__) + logger.warning(f"Could not load model from IntegrationSettings: {e}", exc_info=True) # Merge with defaults default_config = { diff --git a/frontend/src/hooks/useProgressModal.ts b/frontend/src/hooks/useProgressModal.ts index a333fe7f..0e7645a7 100644 --- a/frontend/src/hooks/useProgressModal.ts +++ b/frontend/src/hooks/useProgressModal.ts @@ -58,6 +58,7 @@ export function useProgressModal(): UseProgressModalReturn { const displayedPercentageRef = useRef(0); const currentStepRef = useRef(null); const stepTransitionTimeoutRef = useRef(null); + const autoIncrementIntervalRef = useRef(null); // Step mapping with user-friendly messages and percentages const getStepInfo = (stepName: string, message: string = '', allSteps: any[] = []): { percentage: number; friendlyMessage: string } => { @@ -350,6 +351,8 @@ export function useProgressModal(): UseProgressModalReturn { stepTransitionTimeoutRef.current = setTimeout(animateProgress, 200); } else { stepTransitionTimeoutRef.current = null; + // After reaching target, start auto-increment if below 80% + startAutoIncrement(); } } }; @@ -381,6 +384,8 @@ export function useProgressModal(): UseProgressModalReturn { phase: meta.phase, }, }); + // Start auto-increment if below 80% + startAutoIncrement(); } else { // Same percentage - just update message and details if needed currentStepRef.current = currentStep; @@ -395,8 +400,61 @@ export function useProgressModal(): UseProgressModalReturn { phase: meta.phase, }, })); + // Start auto-increment if below 80% + startAutoIncrement(); } + // Helper function to start auto-increment progress (1% every 300ms until 80%) + const startAutoIncrement = () => { + // Clear any existing auto-increment interval + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } + + // Only start if we're below 80% + if (displayedPercentageRef.current < 80) { + autoIncrementIntervalRef.current = setInterval(() => { + setProgress(prev => { + // Check current status - stop if not processing + if (prev.status !== 'processing') { + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } + return prev; + } + + const current = displayedPercentageRef.current; + if (current < 80) { + const newPercentage = Math.min(current + 1, 80); + displayedPercentageRef.current = newPercentage; + + // Stop if we've reached 80% + if (newPercentage >= 80) { + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } + } + + return { + ...prev, + percentage: newPercentage, + }; + } else { + // Stop if we've reached 80% + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } + return prev; + } + }); + }, 300); + } + }; + // Update step logs if available if (meta.request_steps || meta.response_steps) { // Collect all steps for display in modal @@ -657,6 +715,11 @@ export function useProgressModal(): UseProgressModalReturn { clearTimeout(stepTransitionTimeoutRef.current); stepTransitionTimeoutRef.current = null; } + // Clear auto-increment interval + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } // Reset displayed percentage displayedPercentageRef.current = 0; currentStepRef.current = null; @@ -669,6 +732,11 @@ export function useProgressModal(): UseProgressModalReturn { clearTimeout(stepTransitionTimeoutRef.current); stepTransitionTimeoutRef.current = null; } + // Clear auto-increment interval + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } displayedPercentageRef.current = 0; currentStepRef.current = null; setStepLogs([]); // Reset step logs when opening modal @@ -699,6 +767,11 @@ export function useProgressModal(): UseProgressModalReturn { clearTimeout(stepTransitionTimeoutRef.current); stepTransitionTimeoutRef.current = null; } + // Clear auto-increment interval + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } displayedPercentageRef.current = 0; currentStepRef.current = null; setStepLogs([]); // Clear step logs when closing modal @@ -722,6 +795,11 @@ export function useProgressModal(): UseProgressModalReturn { clearTimeout(stepTransitionTimeoutRef.current); stepTransitionTimeoutRef.current = null; } + // Clear auto-increment interval + if (autoIncrementIntervalRef.current) { + clearInterval(autoIncrementIntervalRef.current); + autoIncrementIntervalRef.current = null; + } displayedPercentageRef.current = 0; currentStepRef.current = null; setProgress({