Feat/ai reviewer: add AI review#3
Conversation
|
|
||
| def should_review(filename): | ||
| """Check if file should be reviewed based on extension and path.""" | ||
| if any(filename.endswith(ext) for ext in IGNORED_EXTENSIONS): |
There was a problem hiding this comment.
🤖 AI Review: MODEL_NAME sử dụng model không rõ ràng, nên xác minh tính khả dụng và chi phí trước khi sử dụng.
|
|
||
| Dữ liệu input là JSON list các file kèm patch. | ||
| Hãy trả về kết quả là một JSON list thuần túy (không markdown block, không giải thích thêm), mỗi item có format sau: | ||
| [ |
There was a problem hiding this comment.
🤖 AI Review: API key được lấy từ environment variable nhưng không có validation về định dạng hoặc tính hợp lệ.
| if content.startswith("```json"): | ||
| content = content[7:] | ||
| if content.startswith("```"): | ||
| content = content[3:] |
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp response.choices rỗng hoặc không tồn tại, có thể gây lỗi runtime.
| commit = pr.get_commits().reversed[0] # Get latest commit | ||
|
|
||
| if not comments: | ||
| logging.info("No issues found. LGTM!") |
There was a problem hiding this comment.
🤖 AI Review: Không có cơ chế retry hoặc fallback khi gọi API thất bại, ảnh hưởng đến độ tin cậy.
| logging.warning(f"Failed to post comment on {filename}:{line}. Error: {e}") | ||
| pr.create_issue_comment(f"Could not comment on line {line} of {filename}. \n\n{body}") | ||
|
|
||
| def main(): |
There was a problem hiding this comment.
🤖 AI Review: Sử dụng commit.reversed[0] có thể gây lỗi nếu danh sách commit rỗng, nên kiểm tra trước.
|
|
||
| with open(event_path, 'r') as f: | ||
| event_data = json.load(f) | ||
|
|
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp line_number không phải là số nguyên, có thể gây lỗi khi ép kiểu.
| def should_review(filename): | ||
| """Check if file should be reviewed based on extension and path.""" | ||
| if any(filename.endswith(ext) for ext in IGNORED_EXTENSIONS): | ||
| return False |
There was a problem hiding this comment.
🤖 AI Review: MODEL_NAME sử dụng model không rõ ràng, nên kiểm tra tính khả dụng và chi phí trước khi sử dụng.
|
|
||
| for file in pr.get_files(): | ||
| if not should_review(file.filename): | ||
| continue |
There was a problem hiding this comment.
🤖 AI Review: Hàm should_review không xử lý trường hợp filename là None hoặc rỗng, có thể gây lỗi.
| def analyze_code_with_openrouter(files_data): | ||
| """Send code diff to OpenRouter for review.""" | ||
| api_key = os.getenv("OPENROUTER_API_KEY") | ||
| if not api_key: |
There was a problem hiding this comment.
🤖 AI Review: Không có xử lý ngoại lệ khi gọi pr.get_files() hoặc file.patch, có thể gây crash nếu API trả về lỗi.
|
|
||
| Hãy chỉ ra các vấn đề nghiêm trọng: | ||
| 1. Lỗi Logic (Logic Errors) - Rất quan trọng. | ||
| 2. Vấn đề Bảo mật (Security Vulnerabilities) - Rất quan trọng. |
There was a problem hiding this comment.
🤖 AI Review: API key được lấy từ environment variable nhưng không có validation về định dạng hoặc tính hợp lệ.
|
|
||
| Nếu code tốt hoàn toàn, hãy trả về danh sách rỗng []. | ||
|
|
||
| CODE DIFF TO REVIEW: |
There was a problem hiding this comment.
🤖 AI Review: Không có giới hạn về kích thước của files_data khi gửi đến OpenRouter, có thể gây vượt quá giới hạn API.
| except json.JSONDecodeError: | ||
| logging.error(f"Failed to parse JSON response: {content}") | ||
| return [] | ||
| except Exception as e: |
There was a problem hiding this comment.
🤖 AI Review: Không có xử lý ngoại lệ khi gọi pr.get_commits().reversed[0], có thể gây lỗi nếu không có commit nào.
| logging.info(f"Posting {len(comments)} comments...") | ||
|
|
||
| for note in comments: | ||
| filename = note.get('filename') |
There was a problem hiding this comment.
🤖 AI Review: Line number từ AI có thể không chính xác, nên có cơ chế xác minh hoặc fallback.
|
|
||
| # Configure Logging | ||
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | ||
|
|
There was a problem hiding this comment.
🤖 AI Review: Hằng số MODEL_NAME sử dụng model không tồn tại (mistralai/devstral-2512:free), cần kiểm tra và sửa lại tên model chính xác.
| IGNORED_EXTENSIONS = ['.json', '.md', '.txt', '.yml', '.yaml', '.lock', '.png', '.jpg', '.jpeg', '.gif', '.svg'] | ||
| IGNORED_DIRS = ['dist', 'build', 'node_modules', '.github'] | ||
| MODEL_NAME = "mistralai/devstral-2512:free" | ||
| GITHUB_GRAPHQL_URL = "https://api.github.com/graphql" |
There was a problem hiding this comment.
🤖 AI Review: Hàm should_review không xử lý trường hợp filename là None hoặc rỗng, có thể gây lỗi khi truy cập thuộc tính.
| return False | ||
| return True | ||
|
|
||
| def get_pr_diff(repo, pr_number): |
There was a problem hiding this comment.
🤖 AI Review: Không kiểm tra quyền truy cập repo trước khi gọi repo.get_pull, có thể gây lỗi nếu token không có quyền.
| continue | ||
|
|
||
| # Only review added or modified files (not deleted) | ||
| if file.status == 'removed': |
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp file.patch là None, có thể gây lỗi khi thêm vào files_data.
| "Content-Type": "application/json" | ||
| } | ||
| payload = { | ||
| "query": mutation, |
There was a problem hiding this comment.
🤖 AI Review: Headers trong resolve_thread không chứa 'Accept: application/vnd.github.v3+json', có thể gây lỗi với một số API version.
| """ | ||
| query = """ | ||
| query($owner: String!, $repo: String!, $prNumber: Int!) { | ||
| repository(owner: $owner, name: $repo) { |
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp data['data'] là None trước khi truy cập các trường con, có thể gây KeyError.
| } | ||
| } | ||
| """ | ||
| headers = { |
There was a problem hiding this comment.
🤖 AI Review: Không giới hạn số lượng threads lấy về (last: 50), có thể gây quá tải nếu PR có nhiều threads.
| threads = data['data']['repository']['pullRequest']['reviewThreads']['nodes'] | ||
| bot_threads = [] | ||
|
|
||
| for thread in threads: |
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp author là None trước khi gọi author.get('login'), có thể gây AttributeError.
| except Exception as e: | ||
| logging.error(f"Failed to fetch/resolve threads: {e}") | ||
|
|
||
| def analyze_code_with_openrouter(files_data): |
There was a problem hiding this comment.
🤖 AI Review: Không kiểm tra OPENROUTER_API_KEY có hợp lệ hay không trước khi sử dụng, có thể gây lỗi kết nối.
| "X-Title": "Antigravity AI Reviewer" | ||
| } | ||
| ) | ||
|
|
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp response.choices là rỗng hoặc response.choices[0].message.content là None, có thể gây lỗi.
| Hãy trả về kết quả là một JSON list thuần túy (không markdown block, không giải thích thêm), mỗi item có format sau: | ||
| [ | ||
| { | ||
| "filename": "tên_file", |
There was a problem hiding this comment.
🤖 AI Review: Không validate định dạng JSON trả về từ OpenRouter, có thể gây lỗi nếu response không phải JSON hợp lệ.
| response = client.chat.completions.create( | ||
| model=MODEL_NAME, | ||
| messages=[ | ||
| {"role": "system", "content": "You are a helpful code reviewer. Always respond with valid JSON code only. No markdown formatting."}, |
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp commit là None khi gọi pr.get_commits().reversed[0], có thể gây lỗi.
| content = response.choices[0].message.content.strip() | ||
|
|
||
| # Strip markdown code blocks if present (common issue with LLMs) | ||
| if content.startswith("```json"): |
There was a problem hiding this comment.
🤖 AI Review: Không kiểm tra tính hợp lệ của line_number trước khi ép kiểu int(line), có thể gây ValueError.
| def post_comments(pr, comments): | ||
| """Post comments to the PR.""" | ||
| commit = pr.get_commits().reversed[0] # Get latest commit | ||
|
|
There was a problem hiding this comment.
🤖 AI Review: Không kiểm tra quyền truy cập repo trước khi gọi g.get_repo, có thể gây lỗi nếu token không có quyền.
| IGNORED_EXTENSIONS = ['.json', '.md', '.txt', '.yml', '.yaml', '.lock', '.png', '.jpg', '.jpeg', '.gif', '.svg'] | ||
| IGNORED_DIRS = ['dist', 'build', 'node_modules', '.github'] | ||
| # Free tier model from OpenRouter - may have rate limits or availability issues | ||
| MODEL_NAME = "mistralai/devstral-2512:free" |
There was a problem hiding this comment.
🤖 AI Review: Hàm should_review không kiểm tra các file không có phần mở rộng, có thể bỏ sót các file cần review.
|
|
||
| def get_pr_diff(repo, pr_number): | ||
| """Fetch PR diff using PyGithub.""" | ||
| pr = repo.get_pull(pr_number) |
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp file.patch là None, có thể gây lỗi khi truy cập.
| query = """ | ||
| query($owner: String!, $repo: String!, $prNumber: Int!) { | ||
| repository(owner: $owner, name: $repo) { | ||
| pullRequest(number: $prNumber) { |
There was a problem hiding this comment.
🤖 AI Review: Không có cơ chế retry khi gọi API GraphQL thất bại, có thể gây mất comments cũ không được resolve.
| threads = pr_data.get('reviewThreads', {}).get('nodes', []) | ||
| if not threads: | ||
| logging.info("No review threads found.") | ||
| return |
There was a problem hiding this comment.
🤖 AI Review: Không validate định dạng của files_data trước khi gửi đến OpenRouter, có thể gây lỗi nếu dữ liệu không hợp lệ.
| logging.error(f"Network error fetching threads: {e}") | ||
| except Exception as e: | ||
| logging.error(f"Failed to fetch/resolve threads: {e}") | ||
|
|
There was a problem hiding this comment.
🤖 AI Review: Không có cơ chế timeout hoặc retry khi gọi API OpenRouter, có thể gây treo nếu API không phản hồi.
| Hãy trả về kết quả là một JSON list thuần túy (không markdown block, không giải thích thêm), mỗi item có format sau: | ||
| [ | ||
| { | ||
| "filename": "tên_file", |
There was a problem hiding this comment.
🤖 AI Review: Không kiểm tra độ dài của comment_text trước khi post, có thể vượt quá giới hạn ký tự của GitHub.
| logging.warning("OpenRouter response has empty content.") | ||
| return [] | ||
|
|
||
| content = content.strip() |
There was a problem hiding this comment.
🤖 AI Review: Không xử lý trường hợp event_data không chứa đủ thông tin cần thiết, có thể gây lỗi khi truy cập các key không tồn tại.
- Add manifest v2 schema with runtime.files array (12 files) - Copy runtime files with short renamed paths (avoid copyright) - Implement settings.json merge preserving user config - Support install (skip existing) and upgrade (refresh) modes - Fix task ID tracking in parser.cjs (High Priority #3) - Fix hook deduplication to check all hooks (High Priority #1) - Add manifest v2 schema validation (High Priority #4) - Document statusline feature in README Runtime files: - status.cjs - Main statusline renderer - hooks/session.cjs - Session initialization - hooks/agent.cjs - Subagent context injection - hooks/usage.cjs - Usage tracking - hooks/lib/*.cjs - Shared utilities (color, parser, git, config, etc.) Installer features: - Idempotent by default (skip existing files) - Upgrade mode with --upgrade flag (refresh managed files) - Settings merge without overwriting user config - Hook deduplication by command identity Code review: 4,613 LOC reviewed, 0 critical issues, 3 high-priority fixed
No description provided.