Add SEO fields to Tasks model, improve content generation response handling, and enhance progress bar animation

- Added primary_keyword, secondary_keywords, tags, and categories fields to Tasks model
- Updated generate_content function to handle full JSON response with all SEO fields
- Improved progress bar animation: smooth 1% increments every 300ms
- Enhanced step detection for content generation vs clustering vs ideas
- Fixed progress modal to show correct messages for each function type
- Added comprehensive logging to Keywords and Tasks pages for AI functions
- Fixed error handling to show meaningful error messages instead of generic failures
This commit is contained in:
Gitea Deploy
2025-11-09 21:22:34 +00:00
parent 09d22ab0e2
commit 961362e088
17340 changed files with 10636 additions and 2248776 deletions

View File

@@ -777,25 +777,72 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
try:
task_state = task.state
except (ValueError, KeyError) as state_exc:
# Task has malformed exception info - try to get error from result
# Task has malformed exception info - try to get error from multiple sources
logger.warning(f"Error accessing task.state (malformed exception info): {str(state_exc)}")
error_msg = 'Task failed - exception details unavailable'
error_type = 'UnknownError'
request_steps = []
response_steps = []
# First, try to get from backend's stored meta (most reliable for our update_state calls)
try:
# Try to get error from task.result
if hasattr(task, 'result'):
result = task.result
if isinstance(result, dict) and 'error' in result:
error_msg = result['error']
elif isinstance(result, str):
error_msg = result
except Exception:
pass
backend = task.backend
if hasattr(backend, 'get_task_meta'):
stored_meta = backend.get_task_meta(task_id)
if stored_meta and isinstance(stored_meta, dict):
meta = stored_meta.get('meta', {})
if isinstance(meta, dict):
if 'error' in meta:
error_msg = meta.get('error')
if 'error_type' in meta:
error_type = meta.get('error_type', error_type)
if 'request_steps' in meta:
request_steps = meta.get('request_steps', [])
if 'response_steps' in meta:
response_steps = meta.get('response_steps', [])
except Exception as e:
logger.debug(f"Error getting from backend meta: {str(e)}")
# Try to get error from task.result
if error_msg == 'Task failed - exception details unavailable':
try:
if hasattr(task, 'result'):
result = task.result
if isinstance(result, dict):
error_msg = result.get('error', error_msg)
error_type = result.get('error_type', error_type)
request_steps = result.get('request_steps', request_steps)
response_steps = result.get('response_steps', response_steps)
elif isinstance(result, str):
error_msg = result
except Exception as e:
logger.debug(f"Error extracting error from task.result: {str(e)}")
# Also try to get error from task.info
if error_msg == 'Task failed - exception details unavailable':
try:
if hasattr(task, 'info') and task.info:
if isinstance(task.info, dict):
if 'error' in task.info:
error_msg = task.info['error']
if 'error_type' in task.info:
error_type = task.info['error_type']
if 'request_steps' in task.info:
request_steps = task.info.get('request_steps', request_steps)
if 'response_steps' in task.info:
response_steps = task.info.get('response_steps', response_steps)
except Exception as e:
logger.debug(f"Error extracting error from task.info: {str(e)}")
return Response({
'state': 'FAILURE',
'meta': {
'error': error_msg,
'error_type': error_type,
'percentage': 0,
'message': f'Error: {error_msg}',
'request_steps': request_steps,
'response_steps': response_steps,
}
})
except (KombuOperationalError, RedisConnectionError, ConnectionError) as conn_exc:
@@ -834,15 +881,29 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
})
# Safely get task info/result
# Try to get error from task.result first (before it gets malformed)
# Try to get error from multiple sources
task_result = None
task_info = None
error_message = None
error_type = None
# First, try to get from backend's stored meta (most reliable for our update_state calls)
try:
backend = task.backend
if hasattr(backend, 'get_task_meta'):
stored_meta = backend.get_task_meta(task_id)
if stored_meta and isinstance(stored_meta, dict):
meta = stored_meta.get('meta', {})
if isinstance(meta, dict):
if 'error' in meta:
error_message = meta.get('error')
error_type = meta.get('error_type', 'UnknownError')
except Exception as backend_err:
logger.debug(f"Could not get from backend meta: {backend_err}")
try:
# Try to get result first - this often has the actual error
if hasattr(task, 'result'):
if not error_message and hasattr(task, 'result'):
try:
task_result = task.result
# If result is a dict with error, extract it
@@ -850,6 +911,9 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
if 'error' in task_result:
error_message = task_result.get('error')
error_type = task_result.get('error_type', 'UnknownError')
elif 'success' in task_result and not task_result.get('success'):
error_message = task_result.get('error', 'Task failed')
error_type = task_result.get('error_type', 'UnknownError')
except Exception:
pass # Will try task.info next
except Exception:
@@ -971,6 +1035,25 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
else:
error_message = str(error_info) if error_info else 'Task failed'
# If still no error message, try to get from task backend directly
if not error_message:
try:
# Try to get from backend's stored result
backend = task.backend
if hasattr(backend, 'get'):
stored = backend.get(task_id)
if stored and isinstance(stored, dict):
if 'error' in stored:
error_message = stored['error']
elif isinstance(stored.get('result'), dict) and 'error' in stored['result']:
error_message = stored['result']['error']
except Exception as backend_err:
logger.warning(f"Error getting from backend: {backend_err}")
# Final fallback
if not error_message:
error_message = 'Task failed - check backend logs for details'
response_meta = {
'error': error_message,
'percentage': 0,
@@ -992,6 +1075,13 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
# Also include error_type if available in meta
if 'error_type' in meta and not error_type:
response_meta['error_type'] = meta['error_type']
# Also check for error in meta directly
if 'error' in meta and not error_message:
error_message = meta['error']
response_meta['error'] = error_message
if 'error_type' in meta and not error_type:
error_type = meta['error_type']
response_meta['error_type'] = error_type
return Response({
'state': task_state,