"""Divination AI — runtime client for the Modal backend.""" from __future__ import annotations import os import httpx API_URL = os.environ.get( "DIVINATION_AI_API_URL", "https://rafalbogusdxc--divination-ai-api.modal.run", ).rstrip("/") TIMEOUT_S = 900 class BackendError(RuntimeError): pass def health() -> dict: try: resp = httpx.get(f"{API_URL}/health", timeout=10, follow_redirects=True) resp.raise_for_status() return resp.json() except Exception: return {"status": "unreachable"} def intake(messages: list[dict]) -> dict: try: resp = httpx.post( f"{API_URL}/intake", json={"messages": messages}, timeout=TIMEOUT_S, follow_redirects=True, ) resp.raise_for_status() return resp.json() except httpx.ConnectError as e: raise BackendError("Cannot reach the Oracle backend — is the Modal app deployed?") from e except httpx.ReadTimeout as e: raise BackendError("The Oracle is taking too long to respond (cold start). Try again in ~1 minute.") from e except httpx.HTTPStatusError as e: raise BackendError(f"Backend error {e.response.status_code}: {e.response.text[:300]}") from e def generate(messages: list[dict]) -> dict: try: resp = httpx.post( f"{API_URL}/generate", json={"messages": messages}, timeout=TIMEOUT_S, follow_redirects=True, ) resp.raise_for_status() return resp.json() except httpx.ConnectError as e: raise BackendError("Cannot reach the Oracle backend — is the Modal app deployed?") from e except httpx.ReadTimeout as e: raise BackendError("The Oracle is taking too long (generation in progress). Please wait...") from e except httpx.HTTPStatusError as e: raise BackendError(f"Backend error {e.response.status_code}: {e.response.text[:300]}") from e def share_trace(messages: list[dict]) -> dict: try: resp = httpx.post( f"{API_URL}/share", json={"messages": messages}, timeout=30, follow_redirects=True, ) resp.raise_for_status() return resp.json() except Exception: return {"shared": False, "reason": "Network error"}