"""detect() — the BackendStatus report for the hub's backend menu.""" from typing import List, Tuple from backends import (BackendStatus, ServerSpec, format_launch_hint, probe, servers) from converter import config from . import build as _build from . import models as _models def detect() -> BackendStatus: """Detect how far audio.cpp is set up, plus the command to start it.""" checkout = _build.find_local_checkout() details: List[str] = [] launch = "" if checkout is None: # No local checkout: only a remote server can make this usable. remote = _detect_remote() return BackendStatus("audiocpp", "audio.cpp", installed=False, configured=False, running=remote[0], remote=remote[0], remote_urls=remote[1], details=["not cloned — run setup to clone " "./app/audio.cpp"]) details.append(f"checkout: {checkout}") binary = _build.find_audiocpp_server_bin(checkout) built = binary is not None if built: details.append(f"built: {binary}") else: details.append("not built — run setup to build audiocpp_server") server_json = checkout / "server.json" configured = server_json.exists() specs: List[ServerSpec] = [] missing = _models.missing_model_entries(server_json) if configured else [] if configured: details.append(f"config: {server_json}") if missing: # The config references model files that are not on disk; a # conversion would fail at model-load time, so say so now. details.extend(_models.model_install_hints(checkout, missing)) if built: # Spawned from the checkout: audiocpp_server discovers # model_specs/.json relative to its working directory. specs = [ServerSpec( "audiocpp", config.AUDIOCPP_API_URL, [str(binary), "--config", str(server_json)], cwd=checkout, identity=probe.IDENTITY_AUDIOCPP)] else: launch = (f"cd {checkout} && ./build/--release" f"/bin/audiocpp_server --config {server_json}") else: details.append("no server.json — run setup to configure models") if specs: launch = format_launch_hint(specs) managed = servers.manages(specs) remote_running, remote_urls = _detect_remote(managed) running = managed or remote_running # A more specific "part-way set up" label than unavailable/installed: # cloned but never built, or built but not configured. Only meaningful # while the backend is not usable (a running server makes even a # non-built checkout usable remotely — see the BackendStatus docstring). partial = "" if not running: if not built: partial = "downloaded (not built)" elif not configured: partial = "built (not configured)" return BackendStatus("audiocpp", "audio.cpp", installed=built, configured=configured, running=running, details=details, launch_hint=launch, servers=specs, managed=managed, remote=remote_running, remote_urls=remote_urls, models_missing=bool(missing), partial=partial) def _detect_remote(managed: bool = False) -> Tuple[bool, dict]: """Detect an externally-run audiocpp_server at the remote URL. Returns ``(running, {spec_name: url})``; see probe.detect_remote_url for the shared semantics. """ return probe.detect_remote_url(config.AUDIOCPP_REMOTE_URL, config.AUDIOCPP_API_URL, probe.IDENTITY_AUDIOCPP, "audiocpp", managed)