Files
agent1/skills/daily_report.py
sylvain 60a216d565 Batch 3 : commandes !agentON/OFF, mode veille, rapports journaliers
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>
2026-03-08 15:41:54 +00:00

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)