"""Actual Computer provider profile.""" from __future__ import annotations import json import logging import os from urllib.parse import urlparse import urllib.request from providers import register_provider from providers.base import ProviderProfile, _profile_user_agent logger = logging.getLogger(__name__) DEFAULT_ACTUAL_BASE_URL = "https://api.actual.inc/v1" _LOCAL_HOSTS = {"localhost", "127.0.0.1", "::1", "0.0.0.0"} def _normalize_actual_base_url(base_url: str) -> str: """Append /v1 to a bare hosted or local host; pass anything else through.""" url = str(base_url or "").strip().rstrip("/") if not url: return DEFAULT_ACTUAL_BASE_URL try: parsed = urlparse(url) host = (parsed.hostname or "").lower().rstrip(".") path = parsed.path.rstrip("/") except Exception: return url if (host == "api.actual.inc" or host in _LOCAL_HOSTS) and path in {"", "/"}: return url + "/v1" return url class ActualProfile(ProviderProfile): """Actual Computer: hosted at api.actual.inc; local (offline-mode client) inference opted into via ACTUAL_BASE_URL.""" def fetch_models( self, *, api_key: str | None = None, base_url: str | None = None, timeout: float = 8.0 ) -> list[str] | None: from hermes_cli.urllib_security import open_credentialed_url base_url = _normalize_actual_base_url( os.getenv("ACTUAL_BASE_URL", "").strip() or base_url or self.base_url ) req = urllib.request.Request(base_url + "/models") if api_key: req.add_header("Authorization", f"Bearer {api_key}") req.add_header("Accept", "application/json") req.add_header("User-Agent", _profile_user_agent()) try: with open_credentialed_url(req, timeout=timeout) as resp: data = json.loads(resp.read().decode()) items = data if isinstance(data, list) else data.get("data", []) return [m["id"] for m in items if isinstance(m, dict) and "id" in m] except Exception as exc: logger.debug("fetch_models(actual): %s", exc) return None actual = ActualProfile( name="actual", aliases=("actual-computer", "actualcomputer", "aci"), display_name="Actual Computer", description=( "Actual Computer - hosted inference via api.actual.inc, or local " "offline inference via ACTUAL_BASE_URL" ), signup_url="https://actual.inc", env_vars=("ACTUAL_API_KEY", "ACTUAL_BASE_URL"), base_url=DEFAULT_ACTUAL_BASE_URL, auth_type="api_key", api_mode="codex_responses", ) register_provider(actual)