from datetime import datetime, timezone from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column from db.base import Base def _utcnow() -> datetime: return datetime.now(timezone.utc) class IntentStepGraph(Base): """Версия графа шагов state machine ветки (Спринт 7.7). У одной ветки может быть несколько графов (исходный 6-шаговый, оптимизированный 4-шаговый Спринта 7.6 и т. п.). Активен ровно один (is_active=True): чат и Песочница используют только его. Остальные — резерв на случай отката или A/B-сравнения, в Песочнице не используются. Сами шаги (`intent_steps`) ссылаются на граф через `graph_id`. Один шаг принадлежит одному графу; чтобы шаг работал в нескольких версиях, он дублируется при создании копии графа. """ __tablename__ = "intent_step_graphs" __table_args__ = ( UniqueConstraint("intent_id", "version", name="uq_intent_step_graph_version"), ) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) intent_id: Mapped[int] = mapped_column( ForeignKey("intents.id", ondelete="CASCADE"), nullable=False, index=True ) version: Mapped[int] = mapped_column(Integer, nullable=False) name: Mapped[str] = mapped_column(String(200), nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=_utcnow, nullable=False )