60a216d565
agent1.py : - !agentOFF/ON <nom> : pause/resume d'un agent via MQTT control - !agentsOFF/ON : mode veille agent1 + pause/resume tous les agents - Confirmation en attente pour modif config (PENDING_CONFIG) - !reports / !tasks / !blackout : afficher les configs - APScheduler : sollicitation rapports + rapport journalier automatique - Souscription agents/daily_report : stockage des rapports reçus - on_mqtt_register : préserve work_hours lors des mises à jour registre skills/daily_report.py : - DAILY_REPORT: [agent] : compile les rapports journaliers reçus - Formatage uptime, stats, taux de succès Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
103 lines
3.5 KiB
Python
103 lines
3.5 KiB
Python
"""
|
|
Skill : DAILY_REPORT
|
|
Compile et formate le rapport journalier de tous les agents.
|
|
|
|
Commande :
|
|
DAILY_REPORT: → rapport du jour
|
|
DAILY_REPORT: <agent> → rapport d'un agent spécifique
|
|
"""
|
|
from datetime import datetime, timedelta
|
|
|
|
SKILL_NAME = "daily_report"
|
|
TRIGGER = "DAILY_REPORT:"
|
|
|
|
|
|
def _fmt_uptime(seconds: int) -> str:
|
|
if seconds < 60:
|
|
return "{}s".format(seconds)
|
|
elif seconds < 3600:
|
|
return "{}m{}s".format(seconds // 60, seconds % 60)
|
|
else:
|
|
h = seconds // 3600
|
|
m = (seconds % 3600) // 60
|
|
return "{}h{}m".format(h, m)
|
|
|
|
|
|
def compile_report(daily_reports: dict, agent_filter: str = None) -> str:
|
|
"""
|
|
Compile les rapports reçus des agents en un texte formaté.
|
|
daily_reports : {agent_name: {tasks_today, success, errors, avg_duration_s,
|
|
last_error, pending, uptime_s, paused, timestamp}}
|
|
"""
|
|
now = datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
lines = ["=== RAPPORT JOURNALIER — {} ===".format(now), ""]
|
|
|
|
if not daily_reports:
|
|
lines.append("Aucun rapport reçu des agents.")
|
|
return "\n".join(lines)
|
|
|
|
agents = {k: v for k, v in daily_reports.items()
|
|
if agent_filter is None or k == agent_filter}
|
|
|
|
if not agents:
|
|
return "Aucun rapport pour l'agent '{}'.".format(agent_filter)
|
|
|
|
total_tasks = 0
|
|
total_errors = 0
|
|
|
|
for agent_name, data in sorted(agents.items()):
|
|
tasks = data.get("tasks_today", 0)
|
|
success = data.get("success", 0)
|
|
errors = data.get("errors", 0)
|
|
avg_dur = data.get("avg_duration_s", 0)
|
|
pending = data.get("pending", 0)
|
|
uptime = data.get("uptime_s", 0)
|
|
paused = data.get("paused", False)
|
|
last_err= data.get("last_error")
|
|
ts = data.get("timestamp", "?")
|
|
|
|
total_tasks += tasks
|
|
total_errors += errors
|
|
|
|
state = "[EN PAUSE]" if paused else "[ACTIF]"
|
|
lines.append("── {} {} ──".format(agent_name, state))
|
|
lines.append(" Rapport : {}".format(ts))
|
|
lines.append(" Uptime : {}".format(_fmt_uptime(uptime)))
|
|
lines.append(" Tâches : {} total, {} succès, {} erreurs".format(tasks, success, errors))
|
|
if pending:
|
|
lines.append(" En attente : {}".format(pending))
|
|
if avg_dur:
|
|
lines.append(" Durée moy : {:.1f}s".format(avg_dur))
|
|
if last_err:
|
|
lines.append(" Dernière erreur : {}".format(str(last_err)[:150]))
|
|
lines.append("")
|
|
|
|
if len(agents) > 1:
|
|
lines.append("── TOTAL ──")
|
|
lines.append(" Tâches : {} | Erreurs : {}".format(total_tasks, total_errors))
|
|
if total_tasks > 0:
|
|
rate = round((total_tasks - total_errors) / total_tasks * 100, 1)
|
|
lines.append(" Taux de succès : {}%".format(rate))
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def execute(args: str) -> str:
|
|
"""
|
|
Appelé par le LLM via DAILY_REPORT:.
|
|
Lit les rapports stockés dans agent1.daily_reports.
|
|
"""
|
|
import sys
|
|
# Accéder aux rapports stockés dans agent1 (module principal)
|
|
agent_filter = args.strip() or None
|
|
daily_reports = {}
|
|
try:
|
|
# agent1.py est le __main__, on récupère ses daily_reports via sys.modules
|
|
main_mod = sys.modules.get("__main__")
|
|
if main_mod and hasattr(main_mod, "daily_reports"):
|
|
daily_reports = main_mod.daily_reports
|
|
except Exception:
|
|
pass
|
|
|
|
return compile_report(daily_reports, agent_filter)
|