from dataclasses import dataclass from typing import Protocol from .config import ProviderConfig @dataclass(frozen=True) class ProviderResponse: document: dict model: str input_tokens: int | None = None output_tokens: int | None = None diagnostics: dict | None = None cached_input_tokens: int | None = None reasoning_tokens: int | None = None normalization: dict | None = None response_capture: dict | None = None class LLMProvider(Protocol): async def generate(self, config: ProviderConfig, request: dict, *, max_response_bytes: int) -> ProviderResponse: """One generation attempt; optional cache setup/fallback stays transport-only. Adapters never retry model answers or change case lifecycle state. """ ...