"""LLMProvider contract - every adapter must conform. Phase 1 generalisation: makes local LLM (Ollama, LM Studio, vLLM, llamafile, llama.cpp HTTP server) a one-config-line drop-in via the OpenAI-compatible HTTP API surface that all of them expose. """ class LLMProvider: """Contract every LLM backend must satisfy. Adapters declare capabilities as class attributes; the engine inspects them before calling optional methods.""" supports_tool_calling: bool = False supports_streaming: bool = False max_context_tokens: int = 4096 supports_embeddings: bool = False def __init__(self, env): self.env = env def complete(self, *, system, messages, max_tokens=2048, temperature=0.0) -> dict: """Plain text completion. Required for ALL providers. Returns: {'content': str, 'tokens_used': int, 'model': str} """ raise NotImplementedError def complete_with_tools(self, *, system, messages, tools, max_tokens=2048) -> dict: """Tool-calling completion. Optional - caller checks supports_tool_calling first. Returns: {'content': str, 'tool_calls': [{'name': str, 'arguments': dict}], ...} """ raise NotImplementedError( f"{type(self).__name__} does not support tool-calling. " f"Check supports_tool_calling before calling.") def embed(self, texts: list[str]) -> list[list[float]]: """Embeddings. Optional - caller checks supports_embeddings first. Returns: list of float vectors, one per input text. """ raise NotImplementedError( f"{type(self).__name__} does not support embeddings. " f"Check supports_embeddings before calling.")