Source code for chat2query.service

"""Service helper for Chat2Query application API key integrations."""

from __future__ import annotations

from typing import Any, Dict, Optional

import requests

from chat2query.exceptions import APIError, AuthenticationError
from chat2query._database_service import _DatabaseService
from chat2query._chat_service import _ChatService
from chat2query._message_service import _MessageService


[docs] class Chat2QueryService: """ Lightweight service for integrating with the Chat2Query backend via application API keys. The service pings the backend on initialization to verify the key and cache the user id. """ DEFAULT_BASE_URL = "https://chat2query.com" def __init__(self, api_key: str, base_url: Optional[str] = None): self.api_key = api_key resolved_base_url = base_url or self.DEFAULT_BASE_URL self.base_url = resolved_base_url.rstrip("/") self.session = requests.Session() self.session.headers.update( { "APPLICATION-API-KEY": api_key, "APPLICATION_API_KEY": api_key, "Content-Type": "application/json", } ) self.user_id: Optional[int] = None self.databases = _DatabaseService(self) self.chats = _ChatService(self) self.messages = _MessageService(self) # Verify connectivity immediately so failures surface early. self._verify_connection() def _request( self, method: str, endpoint: str, *, data: Optional[Dict[str, Any]] = None, params: Optional[Dict[str, Any]] = None, ) -> Dict[str, Any]: """Perform an HTTP request with application API key authentication.""" url = f"{self.base_url}{endpoint}" try: response = self.session.request( method=method, url=url, json=data, params=params, ) except requests.exceptions.RequestException as exc: raise APIError(f"Request failed: {exc}") from exc if response.status_code == 401: raise AuthenticationError("Invalid application API key") if response.status_code >= 400: message: str try: payload = response.json() message = payload.get("ui_message") or payload.get("message", "Unknown error") except ValueError: message = response.text or "Unknown error" raise APIError(message, status_code=response.status_code) try: return response.json() except ValueError as exc: raise APIError(f"Invalid JSON response: {exc}") from exc def _verify_connection(self) -> None: """Ping the backend to confirm the key is valid and cache the user id.""" user_id = self.ping() self.user_id = user_id
[docs] def ping(self) -> int: """ Hit the SDK ping endpoint and return the authenticated user's id. Returns: int: The user id associated with the API key. Raises: APIError: If the response does not contain a user id. """ response = self._request("GET", "/api/v1/sdk/ping") data = response.get("data") or {} user_id = data.get("user_id") if user_id is None: raise APIError("SDK ping response did not include a user id") self.user_id = user_id return user_id