from typing import Dict, Any, Optional, List from pydantic import BaseModel, Field from typing import Literal class ParsedComment(BaseModel): """ Represents a single parsed comment from the LLM's review, intended for grouping by file/function. """ message: str suggestion: Optional[str] = None def __repr__(self): return f"ParsedComment(msg='{self.message[:50]}...', has_suggestion={self.suggestion is not None})" class ParsedReviewSection(BaseModel): """ Represents a categorized section of the review, e.g., 'Potential Issues'. """ title: str content: str def __repr__(self): return f"ParsedReviewSection(title='{self.title}', content='{self.content[:50]}...')" class FileReviewComments(BaseModel): """ Represents comments specific to a file, potentially grouped by function or general file comments. """ file_path: str sections: Dict[str, List[ParsedComment]] = Field(default_factory=dict) class LLMReviewOutput(BaseModel): """ Structured data representing the comprehensive review output from the LLM. """ overall_impression: Optional[str] = None file_reviews: List[FileReviewComments] = Field(default_factory=list) general_sections: List[ParsedReviewSection] = Field(default_factory=list) summary: Optional[str] = None approval_status: str = "Comment" class PRReviewState(BaseModel): repo_name: str pr_id: int pr_title: Optional[str] code_diff: Optional[str] file_contents: Optional[Dict[str, str]] llm_markdown_review: Optional[str] parsed_llm_review_data: Optional[LLMReviewOutput] = None main_comment_body: Optional[str] review_status: Literal[ "initiated", "code_fetched", "code_reviewed", "review_parsed", "initial_review_posted", "awaiting_human_approval", "review_submitted", "review_dismissed", "error" ] require_human_approval: bool human_approval_status: Optional[bool] human_feedback_message: Optional[str] original_review_id: Optional[int] original_review_url: Optional[str] final_review_id: Optional[int] final_review_url: Optional[str] last_error: Optional[str]