"""models — the ModelProvider abstraction (docs/V3-PLAN.md §4 P2).

One interface for every place Alexandria calls a model, so reasoning is
pluggable (Anthropic today; `library`/OpenAI-compatible land in V3.5) and every
call is meterable. App-side only — never rendered into a vault.

The engine's five call sites refactor onto this in PR-4; the vault-mcp agentic
tools (P3) and the research spider (P4) drive :func:`run_tool_loop`.
"""
from .base import (  # noqa: F401
    DEFAULT_MODEL,
    ModelProviderError,
    ModelReply,
    ModelProvider,
    resolve_model,
    resolve_model_tiered,
    strip_wrapping_fences,
)
from .loop import (  # noqa: F401
    MODEL_CONTEXT_CHARS,
    TOOL_RESULT_MAX_CHARS,
    ContextBudgetError,
    ToolLoopCancelled,
    ToolLoopLimitError,
    run_tool_loop,
)
from .anthropic_provider import AnthropicProvider  # noqa: F401

_REGISTRY = {
    "anthropic": AnthropicProvider,
    # "library" (the Alexandria gateway) and "openai" register here in V3.5.
}


def get_provider(name: str, **kwargs) -> ModelProvider:
    """Instantiate a provider by config name (``model.provider``)."""
    try:
        cls = _REGISTRY[name]
    except KeyError:
        raise KeyError(f"unknown model provider {name!r}; available: {sorted(_REGISTRY)}") from None
    return cls(**kwargs)
