"""Agent models for database storage.""" from datetime import datetime, timezone from typing import Any from uuid import UUID, uuid4 from sqlalchemy import DateTime, Enum, Index, String, Text, func from sqlalchemy.dialects.postgresql import JSONB, UUID as PGUUID from sqlalchemy.orm import Mapped, mapped_column from app.core.base import SQLBase, TimestampMixin, UUIDMixin class AgentState(SQLBase, UUIDMixin, TimestampMixin): """Agent state tracking.""" __tablename__ = "agent_states" agent_id: Mapped[str] = mapped_column(String(50), unique=True, nullable=False) status: Mapped[str] = mapped_column(String(20), nullable=False, default="idle") last_run: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) current_task: Mapped[str | None] = mapped_column(Text, nullable=True) extra: Mapped[dict | None] = mapped_column(JSONB, nullable=True) __table_args__ = ( Index("ix_agent_states_agent_id", "agent_id"), ) class AgentReport(SQLBase, UUIDMixin, TimestampMixin): """Agent execution reports.""" __tablename__ = "agent_reports" agent_id: Mapped[str] = mapped_column(String(50), nullable=False, index=True) status: Mapped[str] = mapped_column(String(20), nullable=False) message: Mapped[str] = mapped_column(Text, nullable=True) details: Mapped[dict | None] = mapped_column(JSONB, nullable=True) duration_ms: Mapped[int] = mapped_column(default=0) errors: Mapped[list | None] = mapped_column(JSONB, nullable=True) context: Mapped[dict | None] = mapped_column(JSONB, nullable=True) success: Mapped[bool] = mapped_column(default=True) __table_args__ = ( Index("ix_agent_reports_agent_timestamp", "agent_id", "created_at"), ) class AgentMetric(SQLBase, UUIDMixin): """Agent performance metrics.""" __tablename__ = "agent_metrics" agent_id: Mapped[str] = mapped_column(String(50), nullable=False, index=True) metric_name: Mapped[str] = mapped_column(String(100), nullable=False) value: Mapped[float] = mapped_column(default=0.0) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), ) __table_args__ = ( Index("ix_agent_metrics_agent_metric", "agent_id", "metric_name"), ) class BacklogItem(SQLBase, UUIDMixin, TimestampMixin): """Backlog items for tracking ideas, tasks, plans.""" __tablename__ = "backlog_items" item_type: Mapped[str] = mapped_column(String(20), nullable=False) title: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[str | None] = mapped_column(Text, nullable=True) priority: Mapped[str] = mapped_column(String(20), nullable=False, default="medium") status: Mapped[str] = mapped_column(String(20), nullable=False, default="pending") source: Mapped[str] = mapped_column(String(50), nullable=False) created_by: Mapped[str] = mapped_column(String(100), nullable=False) parent_id: Mapped[UUID | None] = mapped_column(PGUUID, nullable=True) tags: Mapped[list | None] = mapped_column(JSONB, nullable=True) block_ref: Mapped[str | None] = mapped_column(String(255), nullable=True) extra: Mapped[dict | None] = mapped_column(JSONB, nullable=True) __table_args__ = ( Index("ix_backlog_items_type_status", "item_type", "status"), Index("ix_backlog_items_priority", "priority"), ) class Observation(SQLBase, UUIDMixin, TimestampMixin): """User observations from ObserverAgent.""" __tablename__ = "observations" observation_type: Mapped[str] = mapped_column(String(50), nullable=False) user_id: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True) metric_name: Mapped[str] = mapped_column(String(100), nullable=False) metric_value: Mapped[float] = mapped_column(default=0.0) extra: Mapped[dict | None] = mapped_column(JSONB, nullable=True) session_id: Mapped[str | None] = mapped_column(String(100), nullable=True) __table_args__ = ( Index("ix_observations_type_user", "observation_type", "user_id"), )