""" llm_adapter.py — Abstract base class for all LLM adapters. V3 (Sidecar): adds stream_chat() abstract method. """ from abc import ABC, abstractmethod from typing import AsyncGenerator, Optional class LLMAdapter(ABC): """ Minimal interface that all LLM adapters must implement. Methods ------- chat(prompt, system_prompt) -> str Blocking single-turn call. Returns full response text. stream_chat(prompt, system_prompt) -> AsyncGenerator[str, None] Async streaming call. Yields token chunks as they arrive. get_model_name() -> str Returns the model identifier string. """ @abstractmethod def chat(self, prompt: str, system_prompt: Optional[str] = None) -> str: """Blocking call — return full response as a string.""" ... @abstractmethod async def stream_chat( self, prompt: str, system_prompt: Optional[str] = None, ) -> AsyncGenerator[str, None]: """Async generator — yield token chunks as they arrive.""" ... # Make this an async generator (required by ABC) # Concrete classes must use `yield` in their implementation yield # type: ignore[misc] @abstractmethod def get_model_name(self) -> str: """Return the model identifier (e.g. 'gemini-2.0-flash-lite').""" ...