""" Factory for creating LLM adapters by provider name. """ from typing import Optional, Dict, Any from markitect.prompts.execution.llm_adapter import LLMAdapter from markitect.llm.exceptions import LLMConfigurationError # Lazy imports to avoid pulling in every adapter at module load time. _PROVIDERS: Dict[str, str] = { "openrouter": "markitect.llm.openrouter.OpenRouterAdapter", "claude-code": "markitect.llm.claude_code.ClaudeCodeAdapter", } def create_adapter( provider: str = "openrouter", model: Optional[str] = None, api_key: Optional[str] = None, system_prompt: Optional[str] = None, **kwargs: Any, ) -> LLMAdapter: """Instantiate an :class:`LLMAdapter` for the given *provider*. Args: provider: ``"openrouter"`` or ``"claude-code"``. model: Model name (passed to the adapter constructor). api_key: Explicit API key (OpenRouter only). system_prompt: Optional system prompt (OpenRouter only). **kwargs: Extra keyword arguments forwarded to the adapter. Returns: A ready-to-use :class:`LLMAdapter` instance. Raises: LLMConfigurationError: If *provider* is not recognised. """ if provider not in _PROVIDERS: known = ", ".join(sorted(_PROVIDERS)) raise LLMConfigurationError( f"Unknown LLM provider {provider!r}. Choose from: {known}", context={"provider": provider}, ) # Lazy import fqn = _PROVIDERS[provider] module_path, class_name = fqn.rsplit(".", 1) import importlib mod = importlib.import_module(module_path) cls = getattr(mod, class_name) if provider == "openrouter": return cls(model=model, api_key=api_key, system_prompt=system_prompt, **kwargs) elif provider == "claude-code": return cls(model=model, **kwargs) else: return cls(**kwargs) # pragma: no cover