from collections.abc import Generator from datetime import datetime from sqlalchemy import JSON, DateTime, Float, String, create_engine from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column, sessionmaker from app.config import get_settings class Base(DeclarativeBase): pass def json_type(): return JSON() class TimestampMixin: created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class Task(Base, TimestampMixin): __tablename__ = "tasks" id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] = mapped_column(String(240)) assignee: Mapped[str | None] = mapped_column(String(120), nullable=True) due_date: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) status: Mapped[str] = mapped_column(String(40), default="pending") class Note(Base, TimestampMixin): __tablename__ = "notes" id: Mapped[int] = mapped_column(primary_key=True) content: Mapped[str] = mapped_column(String(2000)) category: Mapped[str] = mapped_column(String(40), default="general") class Reservation(Base, TimestampMixin): __tablename__ = "reservations" id: Mapped[int] = mapped_column(primary_key=True) vendor: Mapped[str] = mapped_column(String(180)) reservation_date: Mapped[datetime] = mapped_column(DateTime) status: Mapped[str] = mapped_column(String(40), default="pending") class PendingAction(Base, TimestampMixin): __tablename__ = "pending_actions" id: Mapped[int] = mapped_column(primary_key=True) meeting_id: Mapped[str] = mapped_column(String(120), index=True) tool: Mapped[str] = mapped_column(String(120)) intent: Mapped[str] = mapped_column(String(120)) reasoning: Mapped[str] = mapped_column(String(1000)) confidence: Mapped[float] = mapped_column(Float) payload: Mapped[dict] = mapped_column(json_type()) extracted_entities: Mapped[dict] = mapped_column(json_type(), default=dict) validation: Mapped[dict] = mapped_column(json_type()) policy: Mapped[dict] = mapped_column(json_type()) status: Mapped[str] = mapped_column(String(40), default="pending_review") execution_result: Mapped[dict | None] = mapped_column(json_type(), nullable=True) engine = create_engine(get_settings().database_url, pool_pre_ping=True) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) def init_db() -> None: Base.metadata.create_all(bind=engine) def get_session() -> Generator[Session, None, None]: session = SessionLocal() try: yield session finally: session.close()