diff --git a/backend/igny8_core/ai/engine.py b/backend/igny8_core/ai/engine.py index ea2240da..4161df28 100644 --- a/backend/igny8_core/ai/engine.py +++ b/backend/igny8_core/ai/engine.py @@ -215,13 +215,15 @@ class AIEngine: except ValueError as e: # IntegrationSettings not configured or model missing error_msg = str(e) + error_type = 'ConfigurationError' logger.error(f"[AIEngine] {error_msg}") - return self._handle_error(error_msg, fn) + return self._handle_error(error_msg, fn, error_type=error_type) except Exception as e: # Other unexpected errors error_msg = f"Failed to get model configuration: {str(e)}" + error_type = type(e).__name__ logger.error(f"[AIEngine] {error_msg}", exc_info=True) - return self._handle_error(error_msg, fn) + return self._handle_error(error_msg, fn, error_type=error_type) # Debug logging: Show model configuration (console only, not in step tracker) logger.info(f"[AIEngine] Model Configuration for {function_name}:") @@ -373,18 +375,28 @@ class AIEngine: } except Exception as e: - logger.error(f"Error in AIEngine.execute for {function_name}: {str(e)}", exc_info=True) - return self._handle_error(str(e), fn, exc_info=True) + error_msg = str(e) + error_type = type(e).__name__ + logger.error(f"Error in AIEngine.execute for {function_name}: {error_msg}", exc_info=True) + return self._handle_error(error_msg, fn, exc_info=True, error_type=error_type) - def _handle_error(self, error: str, fn: BaseAIFunction = None, exc_info=False): + def _handle_error(self, error: str, fn: BaseAIFunction = None, exc_info=False, error_type: str = None): """Centralized error handling""" function_name = fn.get_name() if fn else 'unknown' + # Determine error type + if error_type: + final_error_type = error_type + elif isinstance(error, Exception): + final_error_type = type(error).__name__ + else: + final_error_type = 'Error' + self.step_tracker.add_request_step("Error", "error", error, error=error) error_meta = { 'error': error, - 'error_type': type(error).__name__ if isinstance(error, Exception) else 'Error', + 'error_type': final_error_type, **self.step_tracker.get_meta() } self.tracker.error(error, meta=error_meta) @@ -399,7 +411,7 @@ class AIEngine: return { 'success': False, 'error': error, - 'error_type': type(error).__name__ if isinstance(error, Exception) else 'Error', + 'error_type': final_error_type, 'request_steps': self.step_tracker.request_steps, 'response_steps': self.step_tracker.response_steps } diff --git a/frontend/src/components/debug/ResourceDebugOverlay.tsx b/frontend/src/components/debug/ResourceDebugOverlay.tsx index da09a6c2..2cd9e79b 100644 --- a/frontend/src/components/debug/ResourceDebugOverlay.tsx +++ b/frontend/src/components/debug/ResourceDebugOverlay.tsx @@ -128,7 +128,7 @@ export default function ResourceDebugOverlay({ enabled }: ResourceDebugOverlayPr headers['Authorization'] = `Bearer ${token}`; } - // Silently handle 404s and other errors - metrics might not exist for all requests + // Silently handle 404s and other errors - metrics might not exist for all requests try { const response = await nativeFetch.call(window, `${API_BASE_URL}/v1/system/request-metrics/${requestId}/`, { method: 'GET', @@ -136,6 +136,11 @@ export default function ResourceDebugOverlay({ enabled }: ResourceDebugOverlayPr credentials: 'include', // Include session cookies for authentication }); + // Silently ignore 404s - metrics endpoint might not exist for all requests + if (response.status === 404) { + return; // Don't log or retry 404s + } + if (response.ok) { const responseData = await response.json(); // Extract data from unified API response format: {success: true, data: {...}} diff --git a/frontend/src/store/authStore.ts b/frontend/src/store/authStore.ts index bac7f86e..1dc24adb 100644 --- a/frontend/src/store/authStore.ts +++ b/frontend/src/store/authStore.ts @@ -192,32 +192,23 @@ export const useAuthStore = create()( } try { - const API_BASE_URL = import.meta.env.VITE_BACKEND_URL || 'https://api.igny8.com/api'; - const token = state.token || getAuthToken(); + // Use fetchAPI which handles token automatically and extracts data from unified format + const { fetchAPI } = await import('../services/api'); + const response = await fetchAPI('/v1/auth/me/'); - const response = await fetch(`${API_BASE_URL}/v1/auth/me/`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - ...(token ? { 'Authorization': `Bearer ${token}` } : {}), - }, - credentials: 'include', - }); - - const data = await response.json(); - - if (!response.ok || !data.success) { - throw new Error(data.message || 'Failed to refresh user data'); + // fetchAPI extracts data field, so response is {user: {...}} + if (!response || !response.user) { + throw new Error('Failed to refresh user data'); } // Update user data with latest from server // This ensures account/plan changes are reflected immediately - set({ user: data.user }); + set({ user: response.user }); } catch (error: any) { // If refresh fails, don't logout - just log the error // User might still be authenticated, just couldn't refresh data console.warn('Failed to refresh user data:', error); - throw new Error(error.message || 'Failed to refresh user data'); + // Don't throw - just log the warning to prevent error accumulation } }, }),