"""Provider-agnostic async completion interface.

A provider turns a list of ``{"role", "content"}`` messages plus an optional
system instruction into assistant text. Conversation state, history trimming and
the synchronous ``send_*`` API the core relies on all live one level up, in
:class:`~pentestgpt_legacy.llm.client.LLMClient`.
"""

from __future__ import annotations

from abc import ABC, abstractmethod

from pentestgpt_legacy.llm.registry import ModelSpec, ProviderInfo

# A chat message: {"role": "user"|"assistant", "content": str}
Message = dict[str, str]


class BaseProvider(ABC):
    """Base class for native provider connectors."""

    def __init__(self, info: ProviderInfo, api_key: str | None, base_url: str | None):
        self.info = info
        self.api_key = api_key
        self.base_url = base_url

    @property
    def label(self) -> str:
        return self.info.label

    @abstractmethod
    async def acomplete(
        self,
        messages: list[Message],
        system: str | None,
        spec: ModelSpec,
        *,
        max_output_tokens: int | None = None,
        temperature: float | None = None,
    ) -> str:
        """Return the assistant's reply for ``messages`` (user/assistant turns only).

        ``system`` is the system instruction (handled per provider). ``spec``
        carries the wire ``api_id`` and capability flags. ``temperature`` is only
        sent when explicitly provided (reasoning models reject it).
        """
        ...
