"""Thin HTTP client for the control plane API.""" from __future__ import annotations from typing import Any import httpx class ApiError(RuntimeError): def __init__(self, status: int, message: str) -> None: self.status = status super().__init__(f"API {status}: {message}") class ControlPlaneClient: def __init__(self, api_url: str, token: str | None = None) -> None: self.api_url = api_url.rstrip("/") self.token = token def _headers(self) -> dict[str, str]: h = {"content-type": "application/json"} if self.token: h["authorization"] = f"bearer {self.token}" return h def _request(self, method: str, path: str, **kw: Any) -> Any: url = f"{self.api_url}{path}" with httpx.Client(timeout=30.0) as c: resp = c.request(method, url, headers=self._headers(), **kw) if resp.status_code >= 400: try: detail = resp.json().get("detail", resp.text) except Exception: # noqa: BLE001 detail = resp.text raise ApiError(resp.status_code, str(detail)) if resp.status_code == 204 or not resp.content: return None return resp.json() def signup(self, email: str, password: str) -> dict[str, Any]: return self._request("POST", "/v1/auth/signup", json={"email": email, "password": password}) def login(self, email: str, password: str) -> dict[str, Any]: return self._request("POST", "/v1/auth/login", json={"email": email, "password": password}) def me(self) -> dict[str, Any]: return self._request("GET", "/v1/me") def register_agent( self, *, name: str, description: str, version: str, image: str, public: bool, card: dict[str, Any], ) -> dict[str, Any]: return self._request( "POST", "/v1/agents", json={ "name": name, "description": description, "version": version, "image": image, "public": public, "card": card, }, ) def from_source( self, *, name: str, description: str, version: str, public: bool, ) -> dict[str, Any]: return self._request( "POST", "/v1/agents/from-source", json={ "name": name, "description": description, "version": version, "public": public, }, ) def list_agents(self) -> list[dict[str, Any]]: return self._request("GET", "/v1/agents") def get_agent(self, name: str) -> dict[str, Any]: return self._request("GET", f"/v1/agents/{name}") def delete_agent(self, name: str) -> None: self._request("DELETE", f"/v1/agents/{name}")