diff --git a/main.py b/main.py index 32aea01..5d0e966 100644 --- a/main.py +++ b/main.py @@ -18,7 +18,7 @@ from modules.auth_manager import IDENTIFIANTS_ADMIN, verifier_mot_de_passe from modules.logger import log_event from modules.billing_manager import charger_soldes, sauvegarder_soldes from modules.rag_manager import auto_apprendre_rag -from modules.vector_rag import indexer_dossier_thematique +from modules.vector_rag import indexer_dossier_thematique, indexer_tout_le_rag from modules.user_db import load_users, save_users, changer_nom_utilisateur, mettre_a_jour_mot_de_passe from modules.system_utils import obtenir_infos_serveur @@ -186,6 +186,20 @@ async def post(request, session): return RedirectResponse('/backoffice', status_code=303) +# --- ROUTE POUR FORCER LA VECTORISATION GLOBALE DU RAG --- +@rt('/backoffice/forcer_vectorisation') +def post(session): + utilisateur = session.get('user') or request.cookies.get('aethas_user') + users = load_users() + if not utilisateur or users.get(utilisateur, {}).get("role") != "Super Admin": + return HTMLResponse("Accès refusé. Réservé au Super Admin.", status_code=403) + + # Lancement de l'indexation globale en arrière-plan pour ne pas bloquer l'interface + threading.Thread(target=indexer_tout_le_rag).start() + + log_event("INFO", "RAG", f"Vectorisation globale forcée manuellement par {utilisateur}") + return RedirectResponse('/backoffice', status_code=303) + # --- ROUTES PROTÉGÉES --- @rt('/') def get(session, request): diff --git a/modules/system_utils.py b/modules/system_utils.py index d10685c..a56ead3 100644 --- a/modules/system_utils.py +++ b/modules/system_utils.py @@ -1,10 +1,48 @@ +import os import shutil +import requests def obtenir_infos_serveur(): + # Espace disque racine / total, used, free = shutil.disk_usage("/") + + # Espace disque /DATA (partition principale / RAID) + data_stats = {} + if os.path.exists("/DATA"): + dt, du, df = shutil.disk_usage("/DATA") + data_stats = { + "total_gb": round(dt / (2**30), 2), + "utilise_gb": round(du / (2**30), 2), + "libre_gb": round(df / (2**30), 2), + "pourcentage": round((du / dt) * 100, 1) + } + + # État du RAID logiciel (/proc/mdstat) + raid_status = "RAID non actif ou non détecté" + if os.path.exists("/proc/mdstat"): + try: + with open("/proc/mdstat", "r") as f: + raid_status = f.read().strip() + except Exception as e: + raid_status = f"Erreur de lecture mdstat : {e}" + + # État de l'Agent Vectoriel (Ollama) + agent_status = "Injoignable" + try: + resp = requests.get("http://172.19.0.1:11434/api/tags", timeout=2) + if resp.status_code == 200: + agent_status = "Actif (Ollama & Embeddings en ligne)" + else: + agent_status = f"Répond (Code HTTP {resp.status_code})" + except Exception: + agent_status = "Hors ligne / Injoignable" + return { "disque_total_gb": round(total / (2**30), 2), "disque_utilise_gb": round(used / (2**30), 2), "disque_libre_gb": round(free / (2**30), 2), - "pourcentage_utilise": round((used / total) * 100, 1) + "pourcentage_utilise": round((used / total) * 100, 1), + "data_stats": data_stats, + "raid_status": raid_status, + "agent_status": agent_status } \ No newline at end of file diff --git a/modules/ui_components.py b/modules/ui_components.py index 2b7d654..591e627 100644 --- a/modules/ui_components.py +++ b/modules/ui_components.py @@ -153,6 +153,9 @@ def render_main_page(chat_id, utilisateur_nom="xavier", role="Super Admin"): A("+ Nouvelle discussion", href="/new_chat", cls="new-chat-btn"), A("💾 Exporter JSON", href="/export_json", target="_blank", cls="export-btn"), + # Bouton d'accès rapide au Back Office (FO -> BO) + A("⚙️ Back Office", href="/backoffice", cls="export-btn", style="background-color: #3f51b5; color: white; border-color: #3f51b5; margin-top: 5px; text-decoration: none; text-align: center; font-weight: bold;"), + # Bouton de recharger les crédits Button("💳 Recharger des crédits", onclick="document.getElementById('modal-recharge-paypal').style.display='flex'", cls="export-btn", style="background-color: #00e5ff; color: black; border: none; margin-top: 5px; font-weight: bold; cursor: pointer;"), @@ -316,12 +319,21 @@ def render_backoffice_page(utilisateur, role, tous_les_utilisateurs, stats_serve style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 1px solid #333; margin-bottom: 20px;" )) - # Spécificités Super Admin uniquement + # Spécificités Super Admin uniquement (Supervision Système, RAID & Agent Vectoriel + Bouton de Vectorisation Globale) if role == "Super Admin" and stats_serveur: + data_st = stats_serveur.get('data_stats', {}) sections.append(Div( - H3("🖥️ Supervision Système & Serveur", style="color: #ff9800;"), - P(f"💾 Espace disque utilisé : {stats_serveur['disque_utilise_gb']} Go / {stats_serveur['disque_total_gb']} Go ({stats_serveur['pourcentage_utilise']}%)"), - P(f"📂 Espace libre : {stats_serveur['disque_libre_gb']} Go"), + H3("🖥️ Supervision Système, RAID & Agent Vectoriel", style="color: #ff9800;"), + P(f"💾 Espace disque racine : {stats_serveur['disque_utilise_gb']} Go / {stats_serveur['disque_total_gb']} Go ({stats_serveur['pourcentage_utilise']}%)"), + (P(f"🗄️ Partition RAID (/DATA) : {data_st.get('utilise_gb', 0)} Go / {data_st.get('total_gb', 0)} Go ({data_st.get('pourcentage', 0)}% utilisés, {data_st.get('libre_gb', 0)} Go libres)") if data_st else P("🗄️ Partition RAID (/DATA) : Non montée ou non détectée")), + P(f"📡 État du RAID (mdstat) : {stats_serveur.get('raid_status', 'N/A')}", style="font-size: 0.85em; background: #222; padding: 8px; border-radius: 4px; white-space: pre-wrap;"), + P(f"🤖 Agent Vectoriel (Ollama) : {stats_serveur.get('agent_status', 'N/A')}"), + Hr(style="border-color: #444; margin: 15px 0;"), + H4("⚡ Actions Globales RAG", style="color: #00e5ff; font-size: 1em;"), + Form( + Button("Forcer la vectorisation globale de tout le RAG", type="submit", cls="btn-submit", style="background-color: #e91e63; color: white; width: 100%; font-weight: bold; cursor: pointer;"), + method="post", action="/backoffice/forcer_vectorisation" + ), style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 1px solid #333;" ))