"""Thin httpx wrapper for the FastAPI backend. The browser never talks to FastAPI directly — Flet's Python process is the only client of the API. So no CORS, no auth surface exposed publicly. """ from __future__ import annotations import httpx from web.config import API_BASE_URL, HTTP_TIMEOUT class ApiError(RuntimeError): pass class ApiClient: def __init__(self, base_url: str = API_BASE_URL, timeout: float = HTTP_TIMEOUT): self._client = httpx.Client(base_url=base_url, timeout=timeout) def close(self) -> None: self._client.close() # --- LLM --- def llm_status(self) -> dict: return self._get("/llm/config") def llm_models(self, base_url: str, api_key: str) -> list[dict]: data = self._post( "/llm/models", {"base_url": base_url, "api_key": api_key}, ) return data.get("models", []) def llm_test(self, base_url: str, api_key: str, model: str) -> dict: return self._post( "/llm/test", {"base_url": base_url, "api_key": api_key, "model": model}, ) # --- Pipeline / videos --- def pipeline_process(self, payload: dict) -> dict: return self._post("/pipeline/process", payload) def list_videos(self) -> list[dict]: return self._get("/videos/") # --- internals --- def _get(self, path: str) -> dict | list: try: r = self._client.get(path) except httpx.HTTPError as e: raise ApiError(f"Сеть: {e}") return self._unwrap(r) def _post(self, path: str, json: dict | None) -> dict: try: r = self._client.post(path, json=json) except httpx.HTTPError as e: raise ApiError(f"Сеть: {e}") return self._unwrap(r) @staticmethod def _unwrap(r: httpx.Response): try: data = r.json() except Exception: data = None if r.is_success: return data detail = "" if isinstance(data, dict): detail = str(data.get("detail") or data.get("message") or "") if not detail: detail = r.text[:300] if r.text else r.reason_phrase raise ApiError(f"HTTP {r.status_code}: {detail}")