""" Helfer rund um llama-swap und dessen config.yaml. - _swap_get: liest llama-swap-Endpoints (/running, /v1/models, ...) - read_config / write_config: lesen/schreiben der config.yaml ueber ruamel.yaml, sodass Kommentare und Quotes erhalten bleiben. """ import os import httpx from config import CONFIG_PATH, LLAMA_SWAP_URL, yaml def _swap_get(path: str): with httpx.Client(timeout=5.0) as c: r = c.get(f"{LLAMA_SWAP_URL}{path}") r.raise_for_status() return r.json() def read_config() -> dict: if not CONFIG_PATH.exists(): return {"models": {}} with CONFIG_PATH.open("r", encoding="utf-8") as f: data = yaml.load(f) or {} if "models" not in data or data["models"] is None: data["models"] = {} return data def write_config(cfg: dict) -> None: """Schreibt die config.yaml atomar (tmp-Datei + os.replace), damit llama-swap mit -watch-config nie eine halb geschriebene Datei sieht. Fehlende Schreibrechte werden in eine klare Meldung uebersetzt statt als roher Traceback zu landen.""" try: CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True) tmp = CONFIG_PATH.with_name(CONFIG_PATH.name + ".tmp") with tmp.open("w", encoding="utf-8") as f: yaml.dump(cfg, f) os.replace(tmp, CONFIG_PATH) except PermissionError as exc: raise PermissionError( f"Mission Control darf '{CONFIG_PATH}' nicht schreiben. " f"Einmalig Besitz uebergeben: sudo chown -R hitonabi:hitonabi {CONFIG_PATH.parent}" ) from exc