"""Fake provider stubs for BDD and benchmark tests. These lightweight stand-ins avoid importing the real ``ProviderInfo`` (which pulls in heavy dependencies) while satisfying ``ActorRegistry``'s duck-typed contract for provider discovery. """ from __future__ import annotations from dataclasses import dataclass, field from typing import Any from unittest.mock import MagicMock from cleveragents.actor.registry import ActorRegistry from cleveragents.domain.models.core.actor import Actor from cleveragents.providers.registry import ProviderCapabilities @dataclass class FakeProviderInfo: """Minimal stand-in for ``ProviderInfo``.""" name: str default_model: str provider_type: Any = None capabilities: Any = None api_key_env_var: str = "" def __post_init__(self) -> None: if self.provider_type is None: self.provider_type = MagicMock(value=self.name) if self.capabilities is None: self.capabilities = ProviderCapabilities() @dataclass class FakeProviderRegistry: """Stand-in for ``ProviderRegistry``.""" providers: list[FakeProviderInfo] = field(default_factory=list) def get_configured_providers(self) -> list[FakeProviderInfo]: return self.providers def make_registry( providers: list[FakeProviderInfo] | None = None, ) -> tuple[MagicMock, ActorRegistry]: """Build a real ``ActorRegistry`` with mocked service/settings. The ``ActorService`` is mocked so there is no database dependency, but the ``ActorRegistry`` code (including ``_actor_name()``) runs for real. Actors successfully created by ``upsert_actor`` are captured so that ``list_actors`` returns them — ensuring Scenario 3 ("valid JSON") can detect when the bug is actually fixed. """ provider_reg = FakeProviderRegistry(providers=providers or []) captured_actors: list[Actor] = [] def _capturing_upsert(**kwargs: Any) -> Actor: actor = Actor( name=kwargs.get("name", "mock/actor"), provider=kwargs.get("provider", "mock"), model=kwargs.get("model", "actor"), config_blob={}, config_hash=Actor.compute_hash({}), ) captured_actors.append(actor) return actor mock_service = MagicMock() mock_service.list_actors.side_effect = lambda: list(captured_actors) mock_service.get_default_actor.return_value = None mock_service.upsert_actor.side_effect = _capturing_upsert mock_settings = MagicMock() mock_settings.resolve_provider_defaults.return_value = MagicMock( provider=None, model=None ) registry = ActorRegistry( actor_service=mock_service, provider_registry=provider_reg, settings=mock_settings, ) return mock_service, registry