Set up Webber - multi-agent AI development system with: - Domain-based project structure (src/domains/, src/shared/) - BaseController pattern with lazy router instantiation - Pydantic Settings configuration with env file support - Logger decorator with temporal benchmarking and trace IDs - UserProvider singleton for request-scoped context - Custom exception hierarchy - Health endpoints (/, /health) Dependencies (CVE checked 2026-01-09): - FastAPI 0.128.0, Starlette 0.50.0, Uvicorn 0.40.0 - Pydantic 2.12.4, PydanticAI 1.40.0 - All packages at latest safe versions Placeholder domains for future implementation: - agents/ (explore, plan, task) - tools/ (file, shell, search) - auth/ (tatlock integration) Port: 8086 (per CONTAINERS.md allocation) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
75 lines
1.9 KiB
Python
75 lines
1.9 KiB
Python
"""
|
|
Base classes for controllers and schemas.
|
|
|
|
All domain controllers and Pydantic models should inherit from these.
|
|
"""
|
|
from abc import ABC, abstractmethod
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from fastapi import APIRouter
|
|
from pydantic import BaseModel, ConfigDict
|
|
|
|
|
|
class BaseController(ABC):
|
|
"""
|
|
Base controller with lazy router instantiation.
|
|
|
|
All domain controllers inherit from this and implement create_router().
|
|
|
|
Usage:
|
|
class UsersController(BaseController):
|
|
def __init__(self):
|
|
super().__init__(prefix="/users", tags=["Users"])
|
|
|
|
def create_router(self) -> APIRouter:
|
|
router = APIRouter(prefix=self.prefix, tags=self.tags)
|
|
|
|
@router.get("/")
|
|
async def list_users():
|
|
return []
|
|
|
|
return router
|
|
|
|
users_controller = UsersController()
|
|
"""
|
|
|
|
def __init__(self, prefix: str, tags: list[str]):
|
|
self.prefix = prefix
|
|
self.tags = tags
|
|
self._router = None
|
|
|
|
@abstractmethod
|
|
def create_router(self) -> APIRouter:
|
|
"""Create and configure the FastAPI router with all routes."""
|
|
pass
|
|
|
|
@property
|
|
def router(self) -> APIRouter:
|
|
"""Lazy router instantiation."""
|
|
if self._router is None:
|
|
self._router = self.create_router()
|
|
return self._router
|
|
|
|
|
|
class BaseSchema(BaseModel):
|
|
"""
|
|
Base Pydantic model with standardized configuration.
|
|
|
|
All domain schemas should inherit from this.
|
|
"""
|
|
|
|
model_config = ConfigDict(
|
|
strict=False,
|
|
populate_by_name=True,
|
|
use_enum_values=True,
|
|
validate_assignment=True,
|
|
json_encoders={
|
|
datetime: lambda v: v.isoformat() if v else None
|
|
}
|
|
)
|
|
|
|
def dict_without_none(self) -> dict[str, Any]:
|
|
"""Return model as dict, excluding None values."""
|
|
return {k: v for k, v in self.model_dump().items() if v is not None}
|