#!/usr/bin/env python3 """Cody-Watchdog — Prüft ob das Cody-Profil läuft (Hermes Daemon + Profil intakt). Ausgabe: LEER wenn alles OK. Nur bei Problemen wird ein Alarm-Text ausgegeben. Läuft als Hermes-Cronjob (no_agent=True, alle 5 Minuten). Kostet $0.00 — kein LLM-Aufruf. """ import os import subprocess from datetime import datetime, timezone CODY_PROFILE = os.path.expanduser("~/.hermes/profiles/cody") CONFIG_FILE = os.path.join(CODY_PROFILE, "config.yaml") def check_hermes_daemon(): """Prüfe ob mindestens ein Hermes-Prozess läuft.""" try: result = subprocess.run( ["pgrep", "-f", "hermes"], capture_output=True, text=True, timeout=5 ) pids = [p for p in result.stdout.strip().split("\n") if p] return len(pids) > 0, pids except Exception as e: return False, [] def check_profile(): """Prüfe ob Cody-Profil existiert und Config lesbar ist.""" if not os.path.isdir(CODY_PROFILE): return False, f"Profil-Verzeichnis fehlt: {CODY_PROFILE}" if not os.path.isfile(CONFIG_FILE): return False, f"Config fehlt: {CONFIG_FILE}" try: with open(CONFIG_FILE, "r") as f: content = f.read() if not content.strip(): return False, "Config ist leer" # Minimaler YAML-Check: muss "profile" oder "model" enthalten if "cody" not in content.lower() and "model" not in content.lower(): return False, "Config scheint nicht für Cody-Profil" return True, None except Exception as e: return False, f"Config nicht lesbar: {e}" def main(): now = datetime.now(timezone.utc).strftime("%d.%m.%Y %H:%M UTC") alerts = [] # 1. Hermes-Daemon daemon_ok, pids = check_hermes_daemon() if not daemon_ok: alerts.append("❌ Kein Hermes-Prozess gefunden — Daemon down") # 2. Cody-Profil profile_ok, profile_err = check_profile() if not profile_ok: alerts.append(f"❌ Cody-Profil fehlerhaft: {profile_err}") # 3. Gateway (optional: nur prüfen wenn Daemon läuft) if daemon_ok: try: gw = subprocess.run( ["pgrep", "-f", "hermes.*gateway.*cody"], capture_output=True, text=True, timeout=5 ) if not gw.stdout.strip(): # Gateway nicht aktiv — bei on-demand normal, nur warnen wenn Profil da ist pass # Cody ist on-demand, kein Alarm except Exception: pass if alerts: print(f"🚨 Cody-Watchdog-Alarm {now}\n" + "\n".join(alerts)) if __name__ == "__main__": main()