""" Hermes-Agent-Status (Control-Plane-Read). MC betreibt Hermes NICHT — es zeigt nur Status + verlinkt das standalone hermes-webui. Voller Zugriff + Tools/MCP werden in Hermes' eigener Config verdrahtet (siehe docs/HERMES_SETUP.md). """ import logging import os import httpx from config import ANYTHINGLLM_URL, HERMES_API_URL, HERMES_HOME, PC_EXECUTOR_URL log = logging.getLogger(__name__) def _reach(url: str, path: str = "") -> bool: try: with httpx.Client(timeout=3.0) as c: return c.get(f"{url}{path}").status_code < 500 except httpx.HTTPError: return False def _count_enabled_mcp_servers() -> int: config_path = HERMES_HOME / "config.yaml" if not config_path.exists(): return 0 try: from ruamel.yaml import YAML r_yaml = YAML() with config_path.open("r", encoding="utf-8") as f: cfg = r_yaml.load(f) or {} mcp_servers = cfg.get("mcp_servers", {}) if isinstance(cfg, dict) else {} if not isinstance(mcp_servers, dict): return 0 return sum(1 for v in mcp_servers.values() if isinstance(v, dict) and v.get("enabled", True)) except Exception: log.debug("_count_enabled_mcp_servers: Fehler", exc_info=True) return 0 def agent_status() -> dict: """Erreichbarkeit von Gateway (:8642) + WebUI (:8787) + lokale Hinweise.""" home = HERMES_HOME brain_model = "auto" config_path = home / "config.yaml" if config_path.exists(): try: from ruamel.yaml import YAML r_yaml = YAML() with config_path.open("r", encoding="utf-8") as f: cfg = r_yaml.load(f) or {} if isinstance(cfg, dict): brain_model = cfg.get("model", {}).get("model", "auto") except Exception: log.debug("agent_status: Hermes-config.yaml nicht lesbar", exc_info=True) return { "gateway_url": HERMES_API_URL, # Chat-WebUI ist jetzt AnythingLLM (eigener Host), nicht mehr hermes-webui :8787. "webui_url": ANYTHINGLLM_URL, "gateway_reachable": _reach(HERMES_API_URL, "/health"), "webui_reachable": _reach(ANYTHINGLLM_URL, "/api/ping"), "home_exists": home.exists(), "brain_model": brain_model, # Best-effort: welche Verdrahtung lokal sichtbar ist (auf der Box aussagekräftig). "has_config": (home / "config.yaml").exists() or (home / "config.json").exists(), "has_skills": (home / "skills").exists(), "has_memories": (home / "memories").exists(), # Neue Felder: Telegram, MCP-Server-Anzahl, PC-Executor-Erreichbarkeit. "telegram_enabled": bool(os.environ.get("TELEGRAM_BOT_TOKEN", "")), "mcp_server_count": _count_enabled_mcp_servers(), "pc_executor_reachable": _reach(PC_EXECUTOR_URL, "/health"), } def update_brain_model(new_model: str) -> bool: from config import HERMES_HOME home = HERMES_HOME config_path = home / "config.yaml" # Ensure home directory exists home.mkdir(parents=True, exist_ok=True) cfg = {} if config_path.exists(): try: from ruamel.yaml import YAML r_yaml = YAML() with config_path.open("r", encoding="utf-8") as f: cfg = r_yaml.load(f) or {} except Exception: log.debug("update_brain_model: bestehende config.yaml nicht lesbar", exc_info=True) cfg = {} if not isinstance(cfg, dict): cfg = {} if "model" not in cfg or not isinstance(cfg["model"], dict): cfg["model"] = {} cfg["model"]["model"] = new_model try: from ruamel.yaml import YAML r_yaml = YAML() with config_path.open("w", encoding="utf-8") as f: r_yaml.dump(cfg, f) # Restart the user-space service to apply changes try: import services.maintenance as maintenance maintenance.restart_service("hermes-gateway") except Exception: log.warning("update_brain_model: hermes-gateway-Restart fehlgeschlagen", exc_info=True) return True except Exception: log.warning("update_brain_model: Schreiben der config.yaml fehlgeschlagen", exc_info=True) return False