from datetime import datetime from enum import StrEnum from pydantic import BaseModel, ConfigDict, Field, model_validator class LeaveType(StrEnum): PERSONAL = "PERSONAL" SICK = "SICK" ANNUAL = "ANNUAL" class LeaveDraftSuggestionRequest(BaseModel): text: str = Field(min_length=1, max_length=2000) timezone: str = Field(default="Asia/Shanghai", min_length=1, max_length=64) now: datetime | None = None class LeaveDraftSuggestion(BaseModel): type: LeaveType | None = None startsAt: datetime | None = None endsAt: datetime | None = None reason: str | None = Field(default=None, max_length=2000) assumptions: list[str] = Field(default_factory=list, max_length=10) needsClarification: list[str] = Field(default_factory=list, max_length=10) @model_validator(mode="after") def validate_time_range(self) -> "LeaveDraftSuggestion": if self.startsAt is not None and self.endsAt is not None: if self.startsAt.tzinfo is None or self.endsAt.tzinfo is None: raise ValueError("startsAt and endsAt must include timezone offsets") if self.endsAt <= self.startsAt: raise ValueError("endsAt must be later than startsAt") if self.reason is not None: normalized = self.reason.strip() self.reason = normalized or None return self class LeaveDraftSuggestionResponse(BaseModel): suggestion: LeaveDraftSuggestion model: str requiresUserConfirmation: bool = True class LeaveProgressContext(BaseModel): model_config = ConfigDict(extra="forbid") requestId: str type: LeaveType status: str startsAt: datetime endsAt: datetime activeTaskNames: list[str] = Field(default_factory=list, max_length=20) completedTaskNames: list[str] = Field(default_factory=list, max_length=50) processEnded: bool timelineEventTypes: list[str] = Field(default_factory=list, max_length=50) class LeaveProgressAnswerRequest(BaseModel): question: str = Field(min_length=1, max_length=2000) timezone: str = Field(min_length=1, max_length=64) context: LeaveProgressContext class LeaveProgressAnswerResponse(BaseModel): answer: str = Field(min_length=1, max_length=2000) model: str # ── AI 对话式设计助手(多阶段交互) ────────────────────────────────── class DesignerStage(StrEnum): UNDERSTANDING = "UNDERSTANDING" CLARIFYING = "CLARIFYING" GENERATING = "GENERATING" VALIDATING = "VALIDATING" CONFIRMING = "CONFIRMING" class DesignerFieldType(StrEnum): TEXT = "text" TEXT_AREA = "textArea" SELECT = "select" DATE_TIME = "dateTime" NUMBER = "number" class DesignerFormField(BaseModel): key: str = Field(min_length=1, max_length=64) label: str = Field(min_length=1, max_length=100) control: DesignerFieldType required: bool = False placeholder: str | None = Field(default=None, max_length=200) options: list[str] | None = Field(default=None, max_length=20) helperText: str | None = Field(default=None, max_length=200) class DesignerProcessStep(BaseModel): name: str = Field(min_length=1, max_length=100) assigneeVariable: str = Field(min_length=1, max_length=64) class DesignerProcessSuggestion(BaseModel): mode: str = Field(default="SERIAL", max_length=20) steps: list[DesignerProcessStep] = Field(default_factory=list, max_length=10) conditionThresholdDays: float | None = None class SchemaValidationIssue(BaseModel): field: str = Field(min_length=1, max_length=100) issue: str = Field(min_length=1, max_length=300) severity: str = Field(default="WARNING", max_length=20) class DesignerSuggestion(BaseModel): stage: DesignerStage = DesignerStage.UNDERSTANDING formTitle: str | None = Field(default=None, max_length=100) formKey: str | None = Field(default=None, max_length=64) fields: list[DesignerFormField] = Field(default_factory=list, max_length=30) process: DesignerProcessSuggestion | None = None summary: str = Field(default="", max_length=500) understanding: str = Field(default="", max_length=800) assumptions: list[str] = Field(default_factory=list, max_length=10) needsClarification: list[str] = Field(default_factory=list, max_length=10) validationIssues: list[SchemaValidationIssue] = Field(default_factory=list, max_length=20) schemaReady: bool = False class ChatTurn(BaseModel): role: str = Field(min_length=1, max_length=20) content: str = Field(min_length=1, max_length=4000) class DesignerSuggestionRequest(BaseModel): message: str = Field(min_length=1, max_length=2000) history: list[ChatTurn] = Field(default_factory=list, max_length=20) currentSchema: str | None = Field(default=None, max_length=8000) timezone: str = Field(default="Asia/Shanghai", min_length=1, max_length=64) class DesignerSuggestionResponse(BaseModel): suggestion: DesignerSuggestion model: str requiresUserConfirmation: bool = True