PMFlow/backend/app/schemas/common.py

69 lines
2.1 KiB
Python

"""通用 Pydantic 模型"""
from __future__ import annotations
from typing import Any, List, Optional
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, model_validator
class TaskBreakdownBusinessObject(BaseModel):
"""结构化任务拆解业务对象"""
model_config = ConfigDict(extra="ignore", populate_by_name=True)
task_key: str = Field(validation_alias=AliasChoices("task_key", "key"))
title: str = Field(validation_alias=AliasChoices("title", "task_name"))
description: Optional[str] = None
type: str = Field(validation_alias=AliasChoices("type", "task_type"))
estimated_hours: float
required_skill_names: List[str] = Field(default_factory=list)
required_skill_tag_ids: List[int] = Field(default_factory=list)
depends_on_task_keys: List[str] = Field(default_factory=list)
risk_level: str = "medium"
risk_notes: Optional[str] = None
confidence: float = 0.0
evidence_refs: List[str] = Field(default_factory=list)
priority: str = "medium"
@model_validator(mode="after")
def _fill_task_key(self) -> "TaskBreakdownBusinessObject":
key = str(self.task_key or "").strip()
if not key:
title = str(self.title or "").strip()
key = title.lower().replace(" ", "-") if title else "task"
self.task_key = key
return self
class TaskItem(TaskBreakdownBusinessObject):
"""兼容旧调用的任务项别名"""
pass
class TaskBreakdownPayload(BaseModel):
"""AI 任务拆解结构化载荷"""
model_config = ConfigDict(extra="ignore")
tasks: List[TaskBreakdownBusinessObject]
detected_skills: List[str] = Field(default_factory=list)
source_context: Optional[dict[str, Any]] = None
class TaskBreakdownRequest(BaseModel):
"""任务拆解请求"""
description: str
project_id: Optional[int] = None
charter_id: Optional[int] = None
sync_to_plane: bool = False
class TaskBreakdownResponse(BaseModel):
"""任务拆解响应"""
tasks: List[TaskBreakdownBusinessObject]
sync_result: Optional[dict] = None