Files
2026-03-17 18:32:44 +03:00

86 lines
2.8 KiB
Python

import enum
import uuid
from typing import Any
from sqlalchemy import Enum, ForeignKey, String, Text
from sqlalchemy.dialects.postgresql import JSON, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import Base, TimestampMixin
class PipelineStatus(str, enum.Enum):
DRAFT = "DRAFT"
READY = "READY"
ARCHIVED = "ARCHIVED"
class Pipeline(TimestampMixin, Base):
"""
Сценарный слой.
Коллекция нод и связей между ними — полная структура графа,
сгенерированного SynthesisService и отображаемого на канвасе (React Flow).
"""
__tablename__ = "pipelines"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
name: Mapped[str] = mapped_column(
String(512),
nullable=False,
comment="Человекочитаемое название пайплайна",
)
description: Mapped[str | None] = mapped_column(
Text,
nullable=True,
comment="Подробное описание того, что делает этот сценарий",
)
user_prompt: Mapped[str | None] = mapped_column(
Text,
nullable=True,
comment="Оригинальный текстовый запрос PM из чата, породивший этот граф",
)
nodes: Mapped[list[dict[str, Any]]] = mapped_column(
JSON,
nullable=False,
default=list,
comment="Список нод графа. Каждая нода ссылается на Capability и хранит индивидуальные параметры",
)
edges: Mapped[list[dict[str, Any]]] = mapped_column(
JSON,
nullable=False,
default=list,
comment="Список рёбер графа. Определяет порядок выполнения нод (DAG)",
)
status: Mapped[PipelineStatus] = mapped_column(
Enum(PipelineStatus, name="pipeline_status"),
nullable=False,
default=PipelineStatus.DRAFT,
server_default=PipelineStatus.DRAFT.value,
comment="Статус пайплайна: DRAFT → READY → ARCHIVED",
)
created_by: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id", ondelete="SET NULL"),
nullable=True,
index=True,
comment="UUID пользователя (PM), создавшего или запустившего генерацию",
)
creator = relationship("User", lazy="select")
dialogs = relationship(
"PipelineDialog",
back_populates="last_pipeline",
passive_deletes=True,
lazy="selectin",
)