from datetime import datetime from typing import Optional, Dict, List from sqlmodel import SQLModel, Field, Column, JSON, Text from enum import Enum class LogSource(str, Enum): RUNTIME = "runtime" CICD = "cicd" DEPLOYMENT = "deployment" class LogStatus(str, Enum): NEW = "NEW" VERIFYING = "VERIFYING" CANNOT_REPRODUCE = "CANNOT_REPRODUCE" PENDING_FIX = "PENDING_FIX" FIXING = "FIXING" FIXED = "FIXED" VERIFIED = "VERIFIED" DEPLOYED = "DEPLOYED" FIX_FAILED = "FIX_FAILED" class Project(SQLModel, table=True): """项目信息""" id: Optional[int] = Field(default=None, primary_key=True) project_id: str = Field(unique=True, index=True) name: Optional[str] = Field(default=None) repo_url: Optional[str] = Field(default=None) local_path: Optional[str] = Field(default=None) description: Optional[str] = Field(default=None) created_at: datetime = Field(default_factory=datetime.utcnow) updated_at: datetime = Field(default_factory=datetime.utcnow) class ProjectUpdate(SQLModel): """项目编辑 schema""" name: Optional[str] = None repo_url: Optional[str] = None local_path: Optional[str] = None description: Optional[str] = None class ErrorLog(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) project_id: str = Field(index=True) environment: str level: str # Source source: str = Field(default="runtime", index=True) # Error Details error_type: str error_message: str file_path: Optional[str] = None line_number: Optional[int] = None stack_trace: str = Field(sa_column=Column(JSON)) # Store full stack trace # Context context: Dict = Field(default={}, sa_column=Column(JSON)) # Versioning version: Optional[str] = None commit_hash: Optional[str] = None # Meta timestamp: datetime = Field(default_factory=datetime.utcnow) fingerprint: str = Field(unique=True, index=True) # project_id + error_type + file_path + line_number # Severity (1-10, AI 评估的严重等级,8+ 需人工审核) severity: Optional[int] = Field(default=None) severity_reason: Optional[str] = Field(default=None, sa_column=Column(Text, nullable=True)) # Status Tracking status: LogStatus = Field(default=LogStatus.NEW) retry_count: int = Field(default=0) # Repair Tracking failure_reason: Optional[str] = Field(default=None, sa_column=Column(Text, nullable=True)) # PR Tracking pr_number: Optional[int] = Field(default=None) pr_url: Optional[str] = Field(default=None) branch_name: Optional[str] = Field(default=None) # Rejection Tracking rejection_reason: Optional[str] = Field(default=None, sa_column=Column(Text, nullable=True)) rejection_count: int = Field(default=0) last_rejected_at: Optional[datetime] = None merged_at: Optional[datetime] = None # Pydantic Models for API class ErrorLogCreate(SQLModel): project_id: str environment: str level: str timestamp: Optional[datetime] = None version: Optional[str] = None commit_hash: Optional[str] = None repo_url: Optional[str] = None source: str = "runtime" error: Dict # {type, message, file_path, line_number, stack_trace} context: Optional[Dict] = {} class TaskStatusUpdate(SQLModel): status: LogStatus message: Optional[str] = None class RepairTask(SQLModel, table=True): """Record of a repair attempt (one per batch, may cover multiple bugs)""" id: Optional[int] = Field(default=None, primary_key=True) error_log_ids: List[int] = Field(sa_column=Column(JSON)) # 关联的 Bug ID 列表 status: LogStatus project_id: str # Repair Details ai_analysis: str = Field(sa_column=Column(Text)) fix_plan: str = Field(sa_column=Column(Text)) code_diff: str = Field(sa_column=Column(Text)) modified_files: List[str] = Field(sa_column=Column(JSON)) # Test Results test_output: str = Field(sa_column=Column(Text)) test_passed: bool # Repair Round Tracking repair_round: int = Field(default=1) failure_reason: Optional[str] = Field(default=None, sa_column=Column(Text, nullable=True)) # PR Info pr_url: Optional[str] = Field(default=None) pr_number: Optional[int] = Field(default=None) branch_name: Optional[str] = Field(default=None) created_at: datetime = Field(default_factory=datetime.utcnow) class RepairTaskCreate(SQLModel): """Schema for creating a repair report via API""" error_log_ids: List[int] status: LogStatus project_id: str ai_analysis: str fix_plan: str code_diff: str modified_files: List[str] test_output: str test_passed: bool repair_round: int = 1 failure_reason: Optional[str] = None pr_url: Optional[str] = None pr_number: Optional[int] = None branch_name: Optional[str] = None