File size: 1,819 Bytes
e787a71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
"""Backend factory — centralized creation of LLM backends.

Replaces scattered if/elif backend selection across mcp.py, routes.py, web.py.
"""

from __future__ import annotations

import logging

from core.types import LLMBackend

logger = logging.getLogger(__name__)


class BackendFactory:
    """Registry and factory for LLM backends."""

    _registry: dict[str, type[LLMBackend]] = {}

    @classmethod
    def register(cls, name: str, backend_cls: type[LLMBackend]) -> None:
        cls._registry[name] = backend_cls

    @classmethod
    def create(cls, name: str, **kwargs) -> LLMBackend:
        if name not in cls._registry:
            raise ValueError(f"Unknown backend: {name!r}. Available: {list(cls._registry.keys())}")
        return cls._registry[name](**kwargs)

    @classmethod
    def create_safe(cls, name: str, **kwargs) -> LLMBackend:
        """Create backend, falling back to mock on failure."""
        try:
            return cls.create(name, **kwargs)
        except Exception as exc:
            logger.warning("Backend %r unavailable (%s), falling back to mock", name, exc)
            return cls.create("mock")


def _register_defaults() -> None:
    """Register all built-in backends. Called at module load."""
    from core.backends import MockBackend
    BackendFactory.register("mock", MockBackend)

    try:
        from core.backends import AnthropicBackend
        BackendFactory.register("anthropic", AnthropicBackend)
    except Exception:
        pass

    try:
        from core.backends import OpenAIBackend
        BackendFactory.register("openai", OpenAIBackend)
    except Exception:
        pass

    try:
        from core.backends import GeminiBackend
        BackendFactory.register("gemini", GeminiBackend)
    except Exception:
        pass


_register_defaults()