from __future__ import annotations
import json
from typing import Any
import httpx
from pydantic import BaseModel
from ai_memory.errors import TransportError, raise_for_status
DEFAULT_BASE_URL = "http://localhost:9077"
DEFAULT_TIMEOUT = 30.0
def build_httpx_kwargs(
*,
base_url: str,
api_key: str | None,
agent_id: str | None,
timeout: float,
verify: bool | str | None,
cert: str | tuple[str, str] | None,
extra_headers: dict[str, str] | None,
) -> dict[str, Any]:
headers: dict[str, str] = {
"User-Agent": "ai-memory-python/0.6.0-alpha.0",
"Accept": "application/json",
}
if api_key:
headers["X-API-Key"] = api_key
if agent_id:
headers["X-Agent-Id"] = agent_id
if extra_headers:
headers.update(extra_headers)
kwargs: dict[str, Any] = {
"base_url": base_url.rstrip("/"),
"headers": headers,
"timeout": timeout,
}
if verify is not None:
kwargs["verify"] = verify
if cert is not None:
kwargs["cert"] = cert
return kwargs
def prep_json(body: Any) -> Any:
if isinstance(body, BaseModel):
return {k: v for k, v in body.model_dump(by_alias=True).items() if v is not None}
if isinstance(body, dict):
return {k: v for k, v in body.items() if v is not None}
return body
def handle_response(response: httpx.Response) -> Any:
content_type = response.headers.get("content-type", "")
if response.status_code >= 400:
payload: Any
try:
payload = response.json()
except (ValueError, json.JSONDecodeError):
payload = response.text or None
raise_for_status(response.status_code, payload)
if "application/json" in content_type:
return response.json()
return response.text
def wrap_transport_error(exc: Exception) -> TransportError:
return TransportError(f"transport error: {exc}", payload=None)