d4ff622c51
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 13m57s
- 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
81 lines
2.6 KiB
Python
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()
|