from __future__ import annotations import uuid from datetime import datetime from typing import Any from sqlalchemy import DateTime, ForeignKey, String, Text, UniqueConstraint, func from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.types import JSON from app.db.base_class import Base class AgentAsset(Base): __tablename__ = "agent_assets" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) asset_type: Mapped[str] = mapped_column(String(20), index=True) code: Mapped[str] = mapped_column(String(100), unique=True, index=True) name: Mapped[str] = mapped_column(String(200)) description: Mapped[str] = mapped_column(Text(), default="") domain: Mapped[str] = mapped_column(String(50), index=True) scenario_json: Mapped[list[Any]] = mapped_column(JSON, default=list) owner: Mapped[str] = mapped_column(String(100)) reviewer: Mapped[str | None] = mapped_column(String(100), nullable=True) status: Mapped[str] = mapped_column(String(20), index=True, default="draft") current_version: Mapped[str | None] = mapped_column(String(30), nullable=True) published_version: Mapped[str | None] = mapped_column(String(30), nullable=True) working_version: Mapped[str | None] = mapped_column(String(30), nullable=True) config_json: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now() ) versions = relationship( "AgentAssetVersion", back_populates="asset", cascade="all, delete-orphan", order_by="desc(AgentAssetVersion.created_at)", ) reviews = relationship( "AgentAssetReview", back_populates="asset", cascade="all, delete-orphan", order_by="desc(AgentAssetReview.created_at)", ) scheduled_runs = relationship("AgentRun", back_populates="task_asset") class AgentAssetVersion(Base): __tablename__ = "agent_asset_versions" __table_args__ = ( UniqueConstraint("asset_id", "version", name="uq_agent_asset_versions_asset_version"), ) id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) asset_id: Mapped[str] = mapped_column(ForeignKey("agent_assets.id"), index=True) version: Mapped[str] = mapped_column(String(30)) content: Mapped[str] = mapped_column(Text()) content_type: Mapped[str] = mapped_column(String(20)) change_note: Mapped[str | None] = mapped_column(Text(), nullable=True) created_by: Mapped[str] = mapped_column(String(100)) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) asset = relationship("AgentAsset", back_populates="versions") class AgentAssetReview(Base): __tablename__ = "agent_asset_reviews" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) asset_id: Mapped[str] = mapped_column(ForeignKey("agent_assets.id"), index=True) version: Mapped[str] = mapped_column(String(30)) reviewer: Mapped[str] = mapped_column(String(100)) review_status: Mapped[str] = mapped_column(String(20), index=True) review_note: Mapped[str | None] = mapped_column(Text(), nullable=True) reviewed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) asset = relationship("AgentAsset", back_populates="reviews")