"""Koppel cockpit Herman-chat aan Hermes/Telegram memory.""" from __future__ import annotations import logging from typing import Any import httpx from app.config import settings log = logging.getLogger("cockpit.hermes_memory") _USERNAME_MAP = { "aissa": "ceo", "aïssa": "ceo", "aissa zarioh": "ceo", "mo": "cto", "mohamed": "cto", } def resolve_hermes_user( *, username: str | None = None, role: str | None = None, channel: str | None = None, ) -> str: """OpenAI-compatible `user` field = Telegram chat_id for Hermes memory.""" uname = (username or "").strip().lower() r = (role or "").strip().lower() mapped = _USERNAME_MAP.get(uname) if mapped == "ceo" or r in ("ceo", "admin") or uname in ("aissa", "aïssa"): return str(settings.HERMES_CEO_CHAT_ID or "8859782446") if mapped == "cto" or r == "cto" or uname in ("mo", "mohamed"): return str(settings.HERMES_CTO_CHAT_ID or "789036463") return str(settings.HERMES_CEO_CHAT_ID or "8859782446") async def fetch_recent_feed(chat_id: str | int, limit: int | None = None) -> list[dict[str, Any]]: limit = limit or int(getattr(settings, "HERMES_MEMORY_LIMIT", 24) or 24) base = (settings.HERMES_FEED_URL or "").rstrip("/") if not base: return [] try: async with httpx.AsyncClient(timeout=12.0) as client: r = await client.get(f"{base}/feed", params={"chat_id": int(chat_id), "limit": limit}) if r.status_code != 200: return [] items = (r.json() or {}).get("items") or [] return list(reversed(items)) except Exception as exc: log.warning("hermes feed fetch failed: %s", exc) return [] def feed_to_messages(items: list[dict[str, Any]], *, max_chars: int = 12000) -> list[dict[str, str]]: out: list[dict[str, str]] = [] total = 0 for it in items: text = (it.get("content_text") or "").strip() if not text: continue role_raw = (it.get("role") or "").lower() role = "assistant" if role_raw in ("assistant", "hermes", "herman") else "user" if role == "assistant" and (it.get("direction") or "") == "in": role = "user" entry = {"role": role, "content": text[:2000]} total += len(entry["content"]) if total > max_chars: break out.append(entry) return out def continuity_system(chat_id: str, display_name: str | None = None) -> str: name = display_name or ("Aïssa" if str(chat_id) == str(settings.HERMES_CEO_CHAT_ID) else "de gebruiker") return ( "Je bent Herman / Hermes, dezelfde AI Co-CEO als in Telegram. " f"Deze cockpit-chat is gekoppeld aan Telegram-sessie chat_id={chat_id} ({name}). " "Gebruik je bestaande Hermes-memory en recente Telegram-geschiedenis. " "Doe alsof dit dezelfde doorlopende conversatie is — geen nieuw persoon, geen amnesie. " "Antwoord in het Nederlands, bondig en actiegericht." )