""" Skill : REPORT / REPORT_ERRORS Historique des exécutions et des erreurs de tous les agents. Commandes : REPORT: → rapport complet des 20 dernières exécutions REPORT: → rapport filtré par agent REPORT_ERRORS: → uniquement les erreurs récentes REPORT_ERRORS: → erreurs d'un agent spécifique """ import sqlite3 from pathlib import Path from datetime import datetime SKILL_NAME = "reporting" TRIGGER = None TRIGGERS = { "REPORT:": "report", "REPORT_ERRORS:": "report_errors", } DB_PATH = Path("/opt/agent/executions.db") def _get_conn(): conn = sqlite3.connect(DB_PATH) conn.execute(""" CREATE TABLE IF NOT EXISTS executions ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT NOT NULL, source TEXT NOT NULL, agent TEXT NOT NULL, task TEXT NOT NULL, status TEXT NOT NULL, result TEXT, duration_s REAL ) """) conn.commit() return conn def log_execution(source: str, agent: str, task: str, status: str, result: str, duration_s: float = 0.0): """Enregistre une exécution dans la base. Appelé par delegate et schedule.""" try: with _get_conn() as conn: conn.execute(""" INSERT INTO executions (timestamp, source, agent, task, status, result, duration_s) VALUES (?, ?, ?, ?, ?, ?, ?) """, ( datetime.now().strftime("%Y-%m-%d %H:%M:%S"), source, agent, task[:200], status, result[:1000] if result else "", round(duration_s, 2) )) except Exception as e: print("[Reporting] Erreur log : {}".format(e)) def _format_rows(rows) -> str: if not rows: return "Aucune exécution trouvée." lines = [] for r in rows: id_, ts, source, agent, task, status, result, dur = r icon = "✓" if status == "success" else "✗" lines.append("{} [{}] {} | {} → {} ({:.1f}s)".format( icon, ts, agent, task[:50], status, dur or 0)) if status != "success" and result: lines.append(" └ {}".format(result[:150])) return "\n".join(lines) def report(args: str) -> str: agent_filter = args.strip() or None try: with _get_conn() as conn: if agent_filter: rows = conn.execute(""" SELECT id, timestamp, source, agent, task, status, result, duration_s FROM executions WHERE agent = ? ORDER BY id DESC LIMIT 20 """, (agent_filter,)).fetchall() else: rows = conn.execute(""" SELECT id, timestamp, source, agent, task, status, result, duration_s FROM executions ORDER BY id DESC LIMIT 20 """).fetchall() header = "Rapport d'exécution{} (20 dernières) :".format( " [{}]".format(agent_filter) if agent_filter else "") return header + "\n" + _format_rows(rows) except Exception as e: return "Erreur REPORT : {}".format(e) def report_errors(args: str) -> str: agent_filter = args.strip() or None try: with _get_conn() as conn: if agent_filter: rows = conn.execute(""" SELECT id, timestamp, source, agent, task, status, result, duration_s FROM executions WHERE status != 'success' AND agent = ? ORDER BY id DESC LIMIT 20 """, (agent_filter,)).fetchall() else: rows = conn.execute(""" SELECT id, timestamp, source, agent, task, status, result, duration_s FROM executions WHERE status != 'success' ORDER BY id DESC LIMIT 20 """).fetchall() header = "Erreurs{} (20 dernières) :".format( " [{}]".format(agent_filter) if agent_filter else "") return header + "\n" + _format_rows(rows) except Exception as e: return "Erreur REPORT_ERRORS : {}".format(e)