"""Pydantic contracts for the flows API.""" from datetime import datetime from uuid import UUID from pydantic import BaseModel, Field class FlowDefinitionCreate(BaseModel): name: str = Field(min_length=1, max_length=200) description: str = Field(default="", max_length=2000) continuation_flow_id: UUID | None = None class FlowDefinitionRead(BaseModel): id: UUID name: str description: str status: str # backend/flows filename this definition syncs from (None if API-created). source_path: str | None = None continuation_flow_id: UUID | None created_at: datetime class FlowVersionCreate(BaseModel): langflow_json: dict author: str = Field(default="", max_length=200) class FlowVersionRead(BaseModel): id: UUID flow_id: UUID version_no: int langflow_json: dict lfx_flow_id: str | None deployed_at: datetime | None author: str created_at: datetime class RunRequest(BaseModel): """Start a flow run. `input` is the domain payload handed to the flow.""" input: dict = Field(default_factory=dict) version_no: int | None = None tenant_id: str = Field(default="default", max_length=200) session_id: str | None = None # Base URL the flow uses for callbacks (e.g. approval tasks). # Defaults to settings.callback_base_url; tests point it at a live server. callback_base_url: str | None = None continuation_flow_id: UUID | None = None class RunRead(BaseModel): id: UUID version_id: UUID tenant_id: str status: str input: dict | None output: dict | None session_id: str | None created_at: datetime finished_at: datetime | None class ApprovalCreate(BaseModel): """Callback contract: a flow reports a terminal approval state.""" run_id: UUID title: str = Field(default="", max_length=500) payload: dict = Field(default_factory=dict) continuation_flow_id: UUID | None = None class ApprovalRead(BaseModel): id: UUID run_id: UUID version_id: UUID tenant_id: str title: str payload: dict continuation_flow_id: UUID | None approver: str | None status: str decision_note: str created_at: datetime decided_at: datetime | None class FlowImportRequest(BaseModel): """Import a flow from the Langflow authoring server by its Langflow id.""" langflow_flow_id: str = Field(min_length=1) name: str | None = Field(default=None, max_length=200) author: str = Field(default="", max_length=200) deploy: bool = True class FlowImportRead(BaseModel): definition: FlowDefinitionRead version: FlowVersionRead class DecisionRequest(BaseModel): decision: str = Field(pattern="^(approve|reject)$") approver: str = Field(default="", max_length=200) note: str = Field(default="", max_length=2000) callback_base_url: str | None = None class DecisionRead(BaseModel): task: ApprovalRead continuation_run: RunRead | None class SyncReport(BaseModel): """Result of reconciling backend/flows/*.json into DB + LFX. Lists hold filename stems; errors maps filename to reason. """ added: list[str] = Field(default_factory=list) updated: list[str] = Field(default_factory=list) deleted: list[str] = Field(default_factory=list) skipped: list[str] = Field(default_factory=list) errors: dict[str, str] = Field(default_factory=dict)