"""Agent registry tests — register/get round-trip, error paths (G-4), builtins.""" import pytest from ai_service.agents.base import BaseAgent from ai_service.agents.coach import CoachAgent from ai_service.agents.registry import ( AgentRegistry, DuplicateAgentError, UnknownAgentError, register_builtin_agents, ) from ai_service.agents.tutor import TutorAgent from ai_service.config import Settings from ai_service.llm.mock import MockProvider class DummyAgent(BaseAgent): name = "dummy" def system_prompt(self, learner_context=None) -> str: return "dummy" def make_factory(): def factory(provider, settings): return DummyAgent(provider, settings) return factory def test_register_and_get(): registry = AgentRegistry() registry.register("dummy", make_factory()) agent = registry.get(MockProvider(), Settings(provider="mock"), "dummy") assert isinstance(agent, DummyAgent) assert agent.name == "dummy" def test_unknown_agent_raises(): registry = AgentRegistry() with pytest.raises(UnknownAgentError): registry.get(MockProvider(), Settings(provider="mock"), "ghost") def test_duplicate_registration_raises(): registry = AgentRegistry() registry.register("dummy", make_factory()) with pytest.raises(DuplicateAgentError): registry.register("dummy", make_factory()) def test_names_sorted(): registry = AgentRegistry() registry.register("zeta", make_factory()) registry.register("alpha", make_factory()) assert registry.names() == ["alpha", "zeta"] def test_builtin_agents_register_and_resolve(): registry = AgentRegistry() register_builtin_agents(registry) assert set(registry.names()) >= {"coach", "tutor"} settings = Settings(provider="mock") coach = registry.get(MockProvider(), settings, "coach") tutor = registry.get(MockProvider(), settings, "tutor") assert isinstance(coach, CoachAgent) assert isinstance(tutor, TutorAgent) def test_lab_and_assessor_resolve_via_registry(): """Phase 4: lab + assessor registered centrally (Task 4-3-01).""" from ai_service.agents.assessor import AssessorAgent from ai_service.agents.lab import LabAgent registry = AgentRegistry() register_builtin_agents(registry) assert {"lab", "assessor"} <= set(registry.names()) settings = Settings(provider="mock") lab = registry.get(MockProvider(), settings, "lab") assessor = registry.get(MockProvider(), settings, "assessor") assert isinstance(lab, LabAgent) assert isinstance(assessor, AssessorAgent) def test_proctor_and_mentor_resolve_via_registry(): """Phase 5: proctor + mentor registered centrally (Tasks 5-1-02/5-2-01).""" from ai_service.agents.mentor import MentorAgent from ai_service.agents.proctor import ProctorAgent registry = AgentRegistry() register_builtin_agents(registry) settings = Settings(provider="mock") proctor = registry.get(MockProvider(), settings, "proctor") mentor = registry.get(MockProvider(), settings, "mentor") assert isinstance(proctor, ProctorAgent) assert isinstance(mentor, MentorAgent) def test_registry_resolves_all_six_agents(): """Must-Have (Phase 5): the full roster — coach/tutor/lab/assessor/proctor/mentor.""" from ai_service.agents.assessor import AssessorAgent from ai_service.agents.coach import CoachAgent from ai_service.agents.lab import LabAgent from ai_service.agents.mentor import MentorAgent from ai_service.agents.proctor import ProctorAgent from ai_service.agents.tutor import TutorAgent registry = AgentRegistry() register_builtin_agents(registry) assert registry.names() == ["assessor", "coach", "lab", "mentor", "proctor", "tutor"] settings = Settings(provider="mock") expected = { "coach": CoachAgent, "tutor": TutorAgent, "lab": LabAgent, "assessor": AssessorAgent, "proctor": ProctorAgent, "mentor": MentorAgent, } for name, cls in expected.items(): agent = registry.get(MockProvider(), settings, name) assert isinstance(agent, cls), f"{name} resolved to {type(agent).__name__}" assert agent.name == name def test_builtin_registration_is_idempotent_safe(): """Duplicate registration raises — builtin bootstrap must be called once.""" registry = AgentRegistry() register_builtin_agents(registry) with pytest.raises(DuplicateAgentError): register_builtin_agents(registry)