"""Base protocols and shared types for orchestrators. This module defines the interfaces that orchestrators depend on, following the Interface Segregation Principle (ISP) and Dependency Inversion Principle (DIP). """ from collections.abc import AsyncGenerator from typing import Protocol, runtime_checkable from src.utils.models import AgentEvent, Evidence, JudgeAssessment, SearchResult class SearchHandlerProtocol(Protocol): """Protocol for search handler. Defines the interface for executing searches across biomedical databases. Implementations include SearchHandler (scatter-gather across PubMed, ClinicalTrials.gov, Europe PMC). """ async def execute(self, query: str, max_results_per_tool: int = 10) -> SearchResult: """Execute a search query. Args: query: The search query string max_results_per_tool: Maximum results to fetch per search tool Returns: SearchResult containing evidence and metadata """ ... class JudgeHandlerProtocol(Protocol): """Protocol for judge handler. Defines the interface for assessing evidence quality and sufficiency. Implementations include JudgeHandler (pydantic-ai), HFInferenceJudgeHandler, and MockJudgeHandler. """ async def assess( self, question: str, evidence: list[Evidence], iteration: int = 0, max_iterations: int = 10, ) -> JudgeAssessment: """Assess whether collected evidence is sufficient. Args: question: The original research question evidence: List of evidence items to assess iteration: Current iteration number max_iterations: Maximum allowed iterations Returns: JudgeAssessment with sufficiency determination and next steps """ ... @runtime_checkable class OrchestratorProtocol(Protocol): """Protocol for orchestrators. All orchestrators (Simple, Advanced, Hierarchical) implement this interface, allowing them to be used interchangeably by the factory and UI. """ def run(self, query: str) -> AsyncGenerator[AgentEvent, None]: """Run the orchestrator workflow. Args: query: User's research question Yields: AgentEvent objects for real-time UI updates """ ...