From ad88d25d15d6ad041432efd148920c4430dc0dbb Mon Sep 17 00:00:00 2001 From: latte Date: Sun, 28 Dec 2025 18:45:28 +0000 Subject: [PATCH] fix: Handle new label dict format in PRAgent PRAgent was trying to use dict as hashable key, causing TypeError. Added _get_label_config() helper to support both old string and new dict format, matching the fix in IssueAgent. --- tools/ai-review/agents/pr_agent.py | 56 ++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/tools/ai-review/agents/pr_agent.py b/tools/ai-review/agents/pr_agent.py index a2b1f43..a431cf8 100644 --- a/tools/ai-review/agents/pr_agent.py +++ b/tools/ai-review/agents/pr_agent.py @@ -40,6 +40,37 @@ class PRAgent(BaseAgent): # Marker specific to PR reviews PR_AI_MARKER = "" + def _get_label_config(self, category: str, key: str) -> dict: + """Get full label configuration from config. + + Args: + category: Label category (type, priority, status) + key: Label key within category (bug, high, ai_approved, etc.) + + Returns: + Dict with name, color, description, aliases + """ + labels_config = self.config.get("labels", {}) + category_config = labels_config.get(category, {}) + label_config = category_config.get(key, {}) + + # Handle old string format + if isinstance(label_config, str): + return { + "name": label_config, + "color": "1d76db", # Default blue + "description": "", + "aliases": [], + } + + # Handle new dict format + return { + "name": label_config.get("name", ""), + "color": label_config.get("color", "1d76db"), + "description": label_config.get("description", ""), + "aliases": label_config.get("aliases", []), + } + def can_handle(self, event_type: str, event_data: dict) -> bool: """Check if this agent handles the given event.""" # Check if agent is enabled @@ -185,7 +216,7 @@ class PRAgent(BaseAgent): }, { "name": "Hardcoded IP", - "pattern": r'\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b', + "pattern": r"\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b", "severity": "LOW", "category": "Security", "description": "Hardcoded IP address detected", @@ -193,7 +224,7 @@ class PRAgent(BaseAgent): }, { "name": "Eval Usage", - "pattern": r'\beval\s*\(', + "pattern": r"\beval\s*\(", "severity": "HIGH", "category": "Security", "description": "Use of eval() detected - potential code injection risk", @@ -201,7 +232,7 @@ class PRAgent(BaseAgent): }, { "name": "Shell Injection", - "pattern": r'(?i)(?:subprocess\.call|os\.system|shell\s*=\s*True)', + "pattern": r"(?i)(?:subprocess\.call|os\.system|shell\s*=\s*True)", "severity": "MEDIUM", "category": "Security", "description": "Potential shell command execution - verify input is sanitized", @@ -373,7 +404,9 @@ class PRAgent(BaseAgent): lines.append("### Security Issues") lines.append("") for issue in review.security_issues[:5]: - lines.append(f"- **[{issue.severity}]** `{issue.file}:{issue.line}` - {issue.description}") + lines.append( + f"- **[{issue.severity}]** `{issue.file}:{issue.line}` - {issue.description}" + ) lines.append("") # Other issues (limit display) @@ -382,7 +415,9 @@ class PRAgent(BaseAgent): lines.append("### Review Findings") lines.append("") for issue in other_issues[:10]: - loc = f"`{issue.file}:{issue.line}`" if issue.line else f"`{issue.file}`" + loc = ( + f"`{issue.file}:{issue.line}`" if issue.line else f"`{issue.file}`" + ) lines.append(f"- **[{issue.severity}]** {loc} - {issue.description}") if len(other_issues) > 10: lines.append(f"- ...and {len(other_issues) - 10} more issues") @@ -406,8 +441,6 @@ class PRAgent(BaseAgent): review: PRReviewResult, ) -> list[str]: """Apply labels based on review result.""" - labels_config = self.config.get("labels", {}).get("status", {}) - try: repo_labels = self.gitea.get_repo_labels(owner, repo) label_map = {l["name"]: l["id"] for l in repo_labels} @@ -418,12 +451,15 @@ class PRAgent(BaseAgent): labels_to_add = [] # Add approval/changes required label + # Use helper to support both old string and new dict format if review.approval: - label_name = labels_config.get("ai_approved", "ai-approved") + label_config = self._get_label_config("status", "ai_approved") else: - label_name = labels_config.get("ai_changes_required", "ai-changes-required") + label_config = self._get_label_config("status", "ai_changes_required") - if label_name in label_map: + label_name = label_config.get("name", "") + + if label_name and label_name in label_map: labels_to_add.append(label_map[label_name]) if labels_to_add: