Enhance error handling in AIEngine and update ResourceDebugOverlay
- Added error type handling in AIEngine for better error categorization during model configuration and execution. - Updated _handle_error method to accept and log error types. - Improved ResourceDebugOverlay to silently ignore 404 responses from the metrics endpoint, preventing unnecessary logging and retries. - Refactored authStore to utilize fetchAPI for automatic token handling and improved error logging without throwing exceptions.
This commit is contained in:
@@ -215,13 +215,15 @@ class AIEngine:
|
|||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
# IntegrationSettings not configured or model missing
|
# IntegrationSettings not configured or model missing
|
||||||
error_msg = str(e)
|
error_msg = str(e)
|
||||||
|
error_type = 'ConfigurationError'
|
||||||
logger.error(f"[AIEngine] {error_msg}")
|
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:
|
except Exception as e:
|
||||||
# Other unexpected errors
|
# Other unexpected errors
|
||||||
error_msg = f"Failed to get model configuration: {str(e)}"
|
error_msg = f"Failed to get model configuration: {str(e)}"
|
||||||
|
error_type = type(e).__name__
|
||||||
logger.error(f"[AIEngine] {error_msg}", exc_info=True)
|
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)
|
# Debug logging: Show model configuration (console only, not in step tracker)
|
||||||
logger.info(f"[AIEngine] Model Configuration for {function_name}:")
|
logger.info(f"[AIEngine] Model Configuration for {function_name}:")
|
||||||
@@ -373,18 +375,28 @@ class AIEngine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in AIEngine.execute for {function_name}: {str(e)}", exc_info=True)
|
error_msg = str(e)
|
||||||
return self._handle_error(str(e), fn, exc_info=True)
|
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"""
|
"""Centralized error handling"""
|
||||||
function_name = fn.get_name() if fn else 'unknown'
|
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)
|
self.step_tracker.add_request_step("Error", "error", error, error=error)
|
||||||
|
|
||||||
error_meta = {
|
error_meta = {
|
||||||
'error': error,
|
'error': error,
|
||||||
'error_type': type(error).__name__ if isinstance(error, Exception) else 'Error',
|
'error_type': final_error_type,
|
||||||
**self.step_tracker.get_meta()
|
**self.step_tracker.get_meta()
|
||||||
}
|
}
|
||||||
self.tracker.error(error, meta=error_meta)
|
self.tracker.error(error, meta=error_meta)
|
||||||
@@ -399,7 +411,7 @@ class AIEngine:
|
|||||||
return {
|
return {
|
||||||
'success': False,
|
'success': False,
|
||||||
'error': error,
|
'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,
|
'request_steps': self.step_tracker.request_steps,
|
||||||
'response_steps': self.step_tracker.response_steps
|
'response_steps': self.step_tracker.response_steps
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export default function ResourceDebugOverlay({ enabled }: ResourceDebugOverlayPr
|
|||||||
headers['Authorization'] = `Bearer ${token}`;
|
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 {
|
try {
|
||||||
const response = await nativeFetch.call(window, `${API_BASE_URL}/v1/system/request-metrics/${requestId}/`, {
|
const response = await nativeFetch.call(window, `${API_BASE_URL}/v1/system/request-metrics/${requestId}/`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@@ -136,6 +136,11 @@ export default function ResourceDebugOverlay({ enabled }: ResourceDebugOverlayPr
|
|||||||
credentials: 'include', // Include session cookies for authentication
|
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) {
|
if (response.ok) {
|
||||||
const responseData = await response.json();
|
const responseData = await response.json();
|
||||||
// Extract data from unified API response format: {success: true, data: {...}}
|
// Extract data from unified API response format: {success: true, data: {...}}
|
||||||
|
|||||||
@@ -192,32 +192,23 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const API_BASE_URL = import.meta.env.VITE_BACKEND_URL || 'https://api.igny8.com/api';
|
// Use fetchAPI which handles token automatically and extracts data from unified format
|
||||||
const token = state.token || getAuthToken();
|
const { fetchAPI } = await import('../services/api');
|
||||||
|
const response = await fetchAPI('/v1/auth/me/');
|
||||||
|
|
||||||
const response = await fetch(`${API_BASE_URL}/v1/auth/me/`, {
|
// fetchAPI extracts data field, so response is {user: {...}}
|
||||||
method: 'GET',
|
if (!response || !response.user) {
|
||||||
headers: {
|
throw new Error('Failed to refresh user data');
|
||||||
'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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update user data with latest from server
|
// Update user data with latest from server
|
||||||
// This ensures account/plan changes are reflected immediately
|
// This ensures account/plan changes are reflected immediately
|
||||||
set({ user: data.user });
|
set({ user: response.user });
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
// If refresh fails, don't logout - just log the error
|
// If refresh fails, don't logout - just log the error
|
||||||
// User might still be authenticated, just couldn't refresh data
|
// User might still be authenticated, just couldn't refresh data
|
||||||
console.warn('Failed to refresh user data:', error);
|
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
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user