"""API client for making requests to backend endpoints from tools.""" import os import logging from typing import Any, Dict, Optional import httpx logger = logging.getLogger(__name__) # Get the base URL for the backend API # In development, this is typically http://localhost:7860 # In production (HF Spaces), it's the same host API_BASE_URL = os.environ.get("API_BASE_URL", "http://localhost:7860") class APIClient: """Simple HTTP client for backend API calls from tools.""" def __init__(self, base_url: str = API_BASE_URL): self.base_url = base_url.rstrip("/") self.client = httpx.AsyncClient(timeout=300.0) # 5 min timeout async def post( self, endpoint: str, json: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None ) -> Dict[str, Any]: """Make a POST request to the backend API.""" url = f"{self.base_url}/api{endpoint}" # Get token from environment (set by session_manager) hf_token = os.environ.get("HF_TOKEN", "") request_headers = { "Content-Type": "application/json", } # In dev mode, auth is bypassed so we don't need a real token # But we'll include it if available if hf_token: request_headers["Authorization"] = f"Bearer {hf_token}" if headers: request_headers.update(headers) try: response = await self.client.post( url, json=json, headers=request_headers, ) response.raise_for_status() return response.json() except httpx.HTTPError as e: logger.error(f"API request failed: {e}") return {"success": False, "error": str(e)} except Exception as e: logger.error(f"Unexpected error in API request: {e}") return {"success": False, "error": str(e)} async def close(self): """Close the HTTP client.""" await self.client.aclose() # Global instance api_client = APIClient()