"""Pydantic schemas for FlowPilot Phase 6 draft templates. A draft is the engineer's "Run now, templatize after resolve" path output: the script ran for the ticket, and the AI proposed a parameterization. Post-resolve, the engineer accepts (promotes to a real template) or rejects. See FLOWPILOT-MIGRATION.md Section 5.3. """ from __future__ import annotations from datetime import datetime from typing import Any, Literal from uuid import UUID from pydantic import BaseModel, Field DraftStatus = Literal["pending", "accepted", "rejected"] class DraftTemplateResponse(BaseModel): id: UUID account_id: UUID source_session_id: UUID source_user_id: UUID script_body: str proposed_parameters: dict[str, Any] proposed_name: str | None proposed_category_id: UUID | None status: DraftStatus resolved_at: datetime | None promoted_template_id: UUID | None created_at: datetime model_config = {"from_attributes": True} class DraftTemplateListResponse(BaseModel): drafts: list[DraftTemplateResponse] class DraftTemplateAcceptRequest(BaseModel): """Engineer's confirmation that this draft should become a real template. Engineer may override the AI's proposed name / category and edit the parameter schema before promotion. Body and parameters_schema are persisted to the new `script_templates` row. """ name: str = Field(..., min_length=1, max_length=200) category_id: UUID description: str | None = Field(None, max_length=2000) # Final parameter schema in the Script Generator's standard shape. # See ScriptTemplate.parameters_schema for the contract. parameters_schema: dict[str, Any] # Optional last-minute edits to the script body. Defaults to the draft's # `script_body` (which TemplateExtractionService produced as the templated # form with `{{ key }}` placeholders). edited_body: str | None = Field(None, min_length=1, max_length=50_000) class DraftTemplateAcceptResponse(BaseModel): draft_id: UUID promoted_template_id: UUID template_slug: str class DraftTemplateRejectResponse(BaseModel): draft_id: UUID status: Literal["rejected"]