scrapeRL / backend /app /api /deps.py
NeerajCodz's picture
feat: add API routes and utility modules
27cde0c
"""Dependency injection utilities for API routes."""
from typing import Annotated, Generator
from fastapi import Depends, HTTPException, status
from app.config import Settings, get_settings
from app.core.env import WebScraperEnv
from app.memory.manager import MemoryManager
from app.models.router import SmartModelRouter
from app.tools.registry import MCPToolRegistry
# Settings dependency
SettingsDep = Annotated[Settings, Depends(get_settings)]
# Store for active environments
_active_environments: dict[str, WebScraperEnv] = {}
def get_environment(episode_id: str) -> WebScraperEnv:
"""Get an active environment by episode ID."""
if episode_id not in _active_environments:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Episode {episode_id} not found",
)
return _active_environments[episode_id]
def create_environment(episode_id: str, settings: Settings) -> WebScraperEnv:
"""Create a new environment for an episode."""
if episode_id in _active_environments:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=f"Episode {episode_id} already exists",
)
env = WebScraperEnv(episode_id=episode_id, settings=settings)
_active_environments[episode_id] = env
return env
def remove_environment(episode_id: str) -> bool:
"""Remove an environment from active storage."""
if episode_id in _active_environments:
del _active_environments[episode_id]
return True
return False
def list_environments() -> list[str]:
"""List all active episode IDs."""
return list(_active_environments.keys())
class DependencyContainer:
"""Container for dependency injection across the application."""
def __init__(self) -> None:
self._memory_manager: MemoryManager | None = None
self._model_router: SmartModelRouter | None = None
self._tool_registry: MCPToolRegistry | None = None
def set_memory_manager(self, manager: MemoryManager) -> None:
"""Set the memory manager instance."""
self._memory_manager = manager
def set_model_router(self, router: SmartModelRouter) -> None:
"""Set the model router instance."""
self._model_router = router
def set_tool_registry(self, registry: MCPToolRegistry) -> None:
"""Set the tool registry instance."""
self._tool_registry = registry
def get_memory_manager(self) -> MemoryManager:
"""Get the memory manager instance."""
if self._memory_manager is None:
raise RuntimeError("Memory manager not initialized")
return self._memory_manager
def get_model_router(self) -> SmartModelRouter:
"""Get the model router instance."""
if self._model_router is None:
raise RuntimeError("Model router not initialized")
return self._model_router
def get_tool_registry(self) -> MCPToolRegistry:
"""Get the tool registry instance."""
if self._tool_registry is None:
raise RuntimeError("Tool registry not initialized")
return self._tool_registry
# Global container instance
container = DependencyContainer()
def get_memory_manager() -> MemoryManager:
"""Dependency for memory manager."""
return container.get_memory_manager()
def get_model_router() -> SmartModelRouter:
"""Dependency for model router."""
return container.get_model_router()
def get_tool_registry() -> MCPToolRegistry:
"""Dependency for tool registry."""
return container.get_tool_registry()
# Type aliases for dependency injection
MemoryManagerDep = Annotated[MemoryManager, Depends(get_memory_manager)]
ModelRouterDep = Annotated[SmartModelRouter, Depends(get_model_router)]
ToolRegistryDep = Annotated[MCPToolRegistry, Depends(get_tool_registry)]