Files
Hermes Agent d4ff622c51
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 13m57s
monitoring: Cody-Watchdog als no_agent-Script (keine LLM-Kosten)
- Ersetzt Agent-Watchdog (deepseek-v4-pro, alle 5 Min = teuer)
- Reines Python-Script: pgrep Hermes + Profil-Check
- Still bei OK, Alarm nur bei Problemen
- /usr/bin/bash.00 Kosten, Peak-Zeiten irrelevant
2026-06-29 14:26:42 +02:00

81 lines
2.6 KiB
Python

#!/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()