from __future__ import annotations from datetime import datetime from sqlalchemy import DateTime, ForeignKey, Integer, JSON, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base, TimestampMixin, UUIDPrimaryKeyMixin, utcnow class AgentSession(UUIDPrimaryKeyMixin, TimestampMixin, Base): __tablename__ = "agent_sessions" mine_id: Mapped[str | None] = mapped_column( String(32), ForeignKey("mines.id", ondelete="SET NULL"), nullable=True, index=True ) user_name: Mapped[str] = mapped_column(String(128), default="default", index=True) thread_id: Mapped[str] = mapped_column(String(64), unique=True, index=True) title: Mapped[str] = mapped_column(String(255), default="") workflow: Mapped[str] = mapped_column(String(64), default="chat") status: Mapped[str] = mapped_column(String(32), default="active", index=True) context: Mapped[dict] = mapped_column(JSON, default=dict) last_message_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) class AgentRun(UUIDPrimaryKeyMixin, Base): __tablename__ = "agent_runs" session_id: Mapped[str] = mapped_column( String(32), ForeignKey("agent_sessions.id", ondelete="CASCADE"), index=True ) run_id: Mapped[str] = mapped_column(String(64), unique=True, index=True) workflow: Mapped[str] = mapped_column(String(64), index=True) status: Mapped[str] = mapped_column(String(32), default="running", index=True) input_payload: Mapped[dict] = mapped_column(JSON, default=dict) output_payload: Mapped[dict] = mapped_column(JSON, default=dict) error: Mapped[str] = mapped_column(Text, default="") model_name: Mapped[str] = mapped_column(String(128), default="") input_tokens: Mapped[int] = mapped_column(Integer, default=0) output_tokens: Mapped[int] = mapped_column(Integer, default=0) started_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow) finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)