"""Daily Herman War Room digest → Telegram (Aïssa + Mo).""" from __future__ import annotations import logging from datetime import datetime, timezone from typing import Any import httpx from app.config import settings from app.db import execute, fetch_all, fetch_one from app.services import llm_router log = logging.getLogger("cockpit.warroom_digest") def _recipients() -> list[tuple[str, str]]: """(chat_id, display_name)""" return [ (str(getattr(settings, "HERMES_CEO_CHAT_ID", None) or "8859782446"), "Aïssa"), (str(getattr(settings, "HERMES_CTO_CHAT_ID", None) or "789036463"), "Mo"), ] def collect_warroom_day(*, hours: int = 24, limit: int = 120) -> list[dict[str, Any]]: hours = max(1, min(int(hours), 72)) rows = fetch_all( """ SELECT m.id, m.sender_type, m.agent_key, m.username, m.content, m.created_at, r.kind, r.title FROM warroom_messages m JOIN warroom_rooms r ON r.id = m.room_id WHERE m.created_at >= NOW() - make_interval(hours => %s) AND r.kind = 'warroom' ORDER BY m.created_at ASC LIMIT %s """, (hours, limit), ) out = [] for r in rows or []: item = dict(r) if item.get("created_at") and hasattr(item["created_at"], "isoformat"): item["created_at"] = item["created_at"].isoformat() out.append(item) return out def _transcript(messages: list[dict[str, Any]], *, max_chars: int = 6000) -> str: lines: list[str] = [] for m in messages: st = m.get("sender_type") if st == "user": who = m.get("username") or "user" elif st == "agent": who = m.get("agent_key") or "agent" else: who = "system" content = (m.get("content") or "").strip().replace("\n", " ") if not content: continue lines.append(f"- {who}: {content[:280]}") text = "\n".join(lines) return text[-max_chars:] async def generate_digest_text(messages: list[dict[str, Any]]) -> str: day = datetime.now(timezone.utc).strftime("%Y-%m-%d") if not messages: return ( f"📋 War Room dagrapport {day}\n\n" "Geen activiteit in #war-room vandaag. Agents stonden klaar; geen overleg gelogd." ) transcript = _transcript(messages) system = ( "Je bent Herman, Co-CEO van Foodlinkk. Schrijf een beknopte Nederlandse " "Telegram-samenvatting van het War Room-overleg voor Aïssa (CEO) en Mo (CTO).\n" "Structuur:\n" f"1) Kop: 📋 War Room dagrapport {day}\n" "2) 3–6 bullets: wat agents bespraken (pipeline, deals, acties, blockers)\n" "3) Sectie 'Acties / open punten' met concrete next steps\n" "4) 1 zin afsluiting\n" "Max ~350 woorden. Geen @zelf-prefix. Geen 'agents staan uit'." ) user = f"War Room transcript (nieuwste onderaan):\n{transcript}" reply, _meta = await llm_router.chat_messages( [{"role": "system", "content": system}, {"role": "user", "content": user}], timeout=90.0, user=str(getattr(settings, "HERMES_CEO_CHAT_ID", None) or "8859782446"), max_tokens=900, temperature=0.3, ) text = (reply or "").strip() if not text.startswith("📋"): text = f"📋 War Room dagrapport {day}\n\n{text}" return text[:3500] async def _deliver_telegram(chat_id: str, name: str, digest: str) -> dict[str, Any]: """Ask Hermes agent to deliver the digest into that Telegram chat.""" system = ( f"Je bent Herman. Bezorg het volgende War Room-dagrapport NU via Telegram " f"aan {name} (chat_id={chat_id}). Stuur de tekst zo letterlijk mogelijk. " "Bevestig kort of verzonden." ) try: reply, meta = await llm_router.chat_messages( [ {"role": "system", "content": system}, {"role": "user", "content": digest}, ], timeout=120.0, user=str(chat_id), max_tokens=200, temperature=0.1, ) return { "ok": True, "chat_id": chat_id, "name": name, "confirm": (reply or "")[:240], "provider": (meta or {}).get("provider_type"), } except Exception as exc: log.exception("warroom digest deliver failed %s", chat_id) return {"ok": False, "chat_id": chat_id, "name": name, "error": str(exc)} def _persist(digest: str, message_count: int, deliveries: list[dict[str, Any]]) -> None: try: execute( """ INSERT INTO agent_events (agent_name, agent_type, event_type, title, body, status, channel, metadata) VALUES (%s, %s, %s, %s, %s, %s, %s, %s::jsonb) """, ( "herman", "warroom_digest", "warroom_daily_digest", "War Room dagrapport verstuurd", digest[:4000], "completed", "telegram", __import__("json").dumps( { "message_count": message_count, "deliveries": deliveries, } ), ), ) except Exception: log.exception("persist digest event failed") try: from app.services import agent_chat agent_chat.post_system_line( "📤 Dagrapport verstuurd naar Aïssa + Mo via Telegram.\n\n" + digest[:1500], agent_key="herman", metadata={"kind": "warroom_digest", "deliveries": deliveries}, ) except Exception: log.exception("post digest to warroom failed") async def run_daily_digest(*, hours: int = 24, deliver: bool = True) -> dict[str, Any]: messages = collect_warroom_day(hours=hours) digest = await generate_digest_text(messages) deliveries: list[dict[str, Any]] = [] if deliver: for chat_id, name in _recipients(): deliveries.append(await _deliver_telegram(chat_id, name, digest)) _persist(digest, len(messages), deliveries) return { "ok": True, "message_count": len(messages), "digest": digest, "deliveries": deliveries, "generated_at": datetime.now(timezone.utc).isoformat(), }