diff --git a/TODO_NEXT_STEPS.txt b/TODO_NEXT_STEPS.txt index 712870c..e533cd3 100644 --- a/TODO_NEXT_STEPS.txt +++ b/TODO_NEXT_STEPS.txt @@ -4,6 +4,7 @@ ================================================================================ 【已完成】 + - V10.221 補 `/observability/ppt_audit_history` AiderHeal 背景任務可見性:正在修復中的簡報會顯示於產線頁,並提供 JSON 狀態端點讓派工後即時刷新,避免重新整理後不知道是否已在修。 - V10.218 補 `/observability/ppt_audit_history` AiderHeal 去重鎖:同一份簡報已在背景修復時,再次點擊會回「已在執行中」,避免重複開 SSH / 模型 / git 修復流程。 - V10.217 讓 `/observability/ppt_audit_history` 的 AiderHeal 派工改為非阻塞背景任務:頁面立即回「已排入」,修復工作在背景執行,避免瀏覽器與 Gunicorn worker 等 SSH、模型與 git push 到超時。 - V10.216 修正 `/observability/ppt_audit_history` 的 AiderHeal 派工斷點:失敗簡報即使只有 `issues_found` 診斷摘要也能一鍵送修,並修正 `execute_code_fix` 參數與 dict 回傳解析,避免按鈕 400/500。 diff --git a/config.py b/config.py index 5697f01..ee7c6a0 100644 --- a/config.py +++ b/config.py @@ -320,7 +320,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.220" +SYSTEM_VERSION = "V10.221" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/routes/admin_observability_routes.py b/routes/admin_observability_routes.py index 4e52f82..5e8e5ed 100644 --- a/routes/admin_observability_routes.py +++ b/routes/admin_observability_routes.py @@ -36,7 +36,12 @@ admin_observability_bp = Blueprint( ) _PPT_AIDER_HEAL_LOCK = threading.Lock() -_PPT_AIDER_HEAL_ACTIVE = set() +_PPT_AIDER_HEAL_ACTIVE = {} + + +def _list_ppt_aider_heal_active_jobs(): + with _PPT_AIDER_HEAL_LOCK: + return [dict(job) for job in _PPT_AIDER_HEAL_ACTIVE.values()] # ───────────────────────────────────────────────────────────────────────────── @@ -1839,16 +1844,27 @@ def ppt_audit_trigger_aider_heal(): 'issue_summary': issue_summary[:500], } heal_key = pptx_filename or diagnosis[:160] or 'manual' + queued_at = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + active_job = { + 'key': heal_key, + 'pptx_filename': pptx_filename, + 'target_file': 'services/ppt_generator.py', + 'queued_at': queued_at, + 'diagnosis': diagnosis[:160], + } with _PPT_AIDER_HEAL_LOCK: if heal_key in _PPT_AIDER_HEAL_ACTIVE: + existing_job = dict(_PPT_AIDER_HEAL_ACTIVE.get(heal_key) or active_job) return jsonify({ 'ok': True, 'status': 'already_running', 'action': 'CODE_FIX', 'message': '這份簡報的 AiderHeal 已在背景執行中,請等 Telegram/Gitea/CD 結果回報。', 'target_file': 'services/ppt_generator.py', + 'active_count': len(_PPT_AIDER_HEAL_ACTIVE), + 'job': existing_job, }), 202 - _PPT_AIDER_HEAL_ACTIVE.add(heal_key) + _PPT_AIDER_HEAL_ACTIVE[heal_key] = active_job def _heal_worker(): try: @@ -1871,7 +1887,7 @@ def ppt_audit_trigger_aider_heal(): ) finally: with _PPT_AIDER_HEAL_LOCK: - _PPT_AIDER_HEAL_ACTIVE.discard(heal_key) + _PPT_AIDER_HEAL_ACTIVE.pop(heal_key, None) thread_key = ''.join(ch for ch in pptx_filename if ch.isalnum())[:24] or 'manual' threading.Thread( @@ -1886,11 +1902,24 @@ def ppt_audit_trigger_aider_heal(): 'action': 'CODE_FIX', 'message': 'AiderHeal 已排入背景執行;完成後會由 Telegram/Gitea/CD 結果回報。', 'target_file': 'services/ppt_generator.py', + 'active_count': len(_list_ppt_aider_heal_active_jobs()), + 'job': active_job, }), 202 except Exception as e: return jsonify({'ok': False, 'error': f'{type(e).__name__}: {str(e)[:200]}'}), 500 +@admin_observability_bp.route('/ppt_audit/aider_heal_status') +@login_required +def ppt_audit_aider_heal_status(): + jobs = _list_ppt_aider_heal_active_jobs() + return jsonify({ + 'ok': True, + 'active_count': len(jobs), + 'jobs': jobs, + }) + + @admin_observability_bp.route('/ppt_audit/generate_missing', methods=['POST']) @login_required def ppt_audit_generate_missing(): @@ -3134,6 +3163,7 @@ def ppt_audit_history(): for item in files if item.get('file_exists') and item.get('is_valid_ppt') and item.get('name') ][:10] + aider_heal_active_jobs = _list_ppt_aider_heal_active_jobs() return render_template( 'admin/ppt_audit_history.html', @@ -3160,6 +3190,8 @@ def ppt_audit_history(): vision_audit_filenames=vision_audit_filenames, issue_items=issue_items, issue_digest=issue_digest, + aider_heal_active_jobs=aider_heal_active_jobs, + aider_heal_active_count=len(aider_heal_active_jobs), error=error, ) diff --git a/templates/admin/ppt_audit_history.html b/templates/admin/ppt_audit_history.html index 96e28ec..a125e5a 100644 --- a/templates/admin/ppt_audit_history.html +++ b/templates/admin/ppt_audit_history.html @@ -66,6 +66,25 @@ {% endif %} {% if error %}
{{ job.pptx_filename or 'manual' }}
+ {{ job.queued_at }}
+ {{ job.diagnosis }}
+