wrolpi/modules/ai/controller_client.py
Roland b07672b976
ai: system endpoints — aggregate status, services, logs, disks
Proxy the Controller under /api/ai so the model sees one API: an
aggregate /status to start every diagnosis, lean service list, recent
service logs (lines clamped), and disks + SMART.  One controller_client
helper resolves the Controller base URL (docker service name vs
localhost).  Every proxy degrades to an `errors` entry when the
Controller is unreachable — never a 500.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-24 14:09:53 -06:00

27 lines
1.1 KiB
Python

"""One helper for API -> Controller requests.
Existing call sites disagree on the base URL (wrolpi/common.py uses http://127.0.0.1, the zim
module uses the docker service name); this module resolves it once: the docker service name when
DOCKERIZED, else localhost, overridable with the CONTROLLER_URL environment variable.
"""
import os
from typing import Tuple
from urllib.parse import urlencode
from wrolpi.common import aiohttp_get, logger
from wrolpi.vars import DOCKERIZED
logger = logger.getChild(__name__)
CONTROLLER_URL = os.environ.get('CONTROLLER_URL') or ('http://controller' if DOCKERIZED else 'http://127.0.0.1')
async def controller_get(path: str, params: dict = None, timeout: int = 10) -> Tuple[int, dict]:
"""GET a Controller endpoint, returning (status, JSON body). Raises on connection errors."""
url = f'{CONTROLLER_URL}{path}'
if params:
params = {k: v for k, v in params.items() if v is not None}
if params:
url = f'{url}?{urlencode(params)}'
async with aiohttp_get(url, timeout=timeout) as response:
return response.status, await response.json()