"""Query a running audiocpp_server for its models and voices.""" import json import urllib.parse import urllib.request from typing import Dict, List, Optional def fetch_server_models(api_url: str) -> Optional[List[Dict[str, str]]]: """List a running audiocpp_server's model entries via GET /v1/models. Returns ``[{id, family, task}, ...]`` — the same shape the converter's client resolves at startup — or None when URL does not answer with a valid document (wrong server, still starting, older audio.cpp). Used by the hub to drive the convert menus against a remote server that has no local server.json describing it. """ try: with urllib.request.urlopen( f"{api_url.rstrip('/')}/v1/models", timeout=10) as response: payload = json.loads(response.read().decode("utf-8")) except (OSError, ValueError): # URLError/HTTPError/socket errors are OSErrors; a non-JSON body is # a ValueError. Anything else means "not an audiocpp_server". return None entries = payload.get("data") if isinstance(payload, dict) else None models: List[Dict[str, str]] = [] for entry in entries or []: if isinstance(entry, dict) and entry.get("id"): models.append({ "id": str(entry["id"]), "family": str(entry.get("family") or ""), "task": str(entry.get("task") or ""), }) return models def fetch_server_voices(api_url: str, model_id: str) -> Optional[List[str]]: """List a running audiocpp_server's voices for MODEL_ID. Queries ``GET /v1/audio/voices?model=`` — the endpoint the converter validates ``--voice`` against — and returns its voice-name list, or None when the server cannot be queried. Lets the hub offer a remote server's voices without reading its configuration locally. """ query = urllib.parse.urlencode({"model": model_id}) try: with urllib.request.urlopen( f"{api_url.rstrip('/')}/v1/audio/voices?{query}", timeout=10) as response: payload = json.loads(response.read().decode("utf-8")) except (OSError, ValueError): return None voices = payload.get("voices") if isinstance(payload, dict) else None if not isinstance(voices, list): return None return [str(voice) for voice in voices]