diff --git a/pythonbridge/core/review.py b/pythonbridge/core/review.py index ec9e5d8..211b4f9 100644 --- a/pythonbridge/core/review.py +++ b/pythonbridge/core/review.py @@ -1,6 +1,9 @@ import json import logging +from pygments.lexers import get_lexer_for_filename +from pygments.util import ClassNotFound + from pythonbridge.core.config import load_environment from pythonbridge.core.diff_parser import parse_patch, clamp_to_valid from pythonbridge.gh.client import get_pr, post_review, create_reaction @@ -21,6 +24,13 @@ def _severity_emoji(severity: str) -> str: return _SEVERITY_EMOJI.get(severity.lower(), "") +def _detect_language(filename: str) -> str: + try: + return get_lexer_for_filename(filename).name + except ClassNotFound: + return "Unknown" + + def _build_pr_context(title: str, body: str) -> str: return f"\n\n## PR Context\n\n**Title:** {title}\n\n**Description:**\n{body or '_No description provided._'}\n" @@ -68,8 +78,10 @@ def review_pr(payload: dict) -> list[dict]: # Annotate the diff with real line numbers so the LLM can reference them accurately annotated_patch, valid_lines = parse_patch(file.patch) + language = _detect_language(file.filename) + llm_input = f"Language: {language}\nFile: {file.filename}\n\n{annotated_patch}" - result = agent_graph.invoke({"pr_input": annotated_patch}) + result = agent_graph.invoke({"pr_input": llm_input}) raw_review = result.get("pr_review") if result else None comments = _parse_comments(raw_review, file.filename) if raw_review else [] diff --git a/pythonbridge/pyproject.toml b/pythonbridge/pyproject.toml index 6153a02..a1c6f0f 100644 --- a/pythonbridge/pyproject.toml +++ b/pythonbridge/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ "langgraph>=1.0.7", "pydantic>=2.12.5", "pygithub>=2.8.1", + "pygments>=2.20.0", "python-dotenv>=1.0.0", "tree-sitter>=0.25.2", "tree-sitter-python>=0.25.0", diff --git a/pythonbridge/uv.lock b/pythonbridge/uv.lock index edcda83..7b5e064 100644 --- a/pythonbridge/uv.lock +++ b/pythonbridge/uv.lock @@ -602,6 +602,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/07/ba/7049ce39f653f6140aac4beb53a5aaf08b4407b6a3019aae394c1c5244ff/pygithub-2.8.1-py3-none-any.whl", hash = "sha256:23a0a5bca93baef082e03411bf0ce27204c32be8bfa7abc92fe4a3e132936df0", size = 432709, upload-time = "2025-09-02T17:41:52.947Z" }, ] +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + [[package]] name = "pyjwt" version = "2.10.1" @@ -777,6 +786,7 @@ dependencies = [ { name = "langgraph" }, { name = "pydantic" }, { name = "pygithub" }, + { name = "pygments" }, { name = "python-dotenv" }, { name = "tree-sitter" }, { name = "tree-sitter-python" }, @@ -793,6 +803,7 @@ requires-dist = [ { name = "langgraph", specifier = ">=1.0.7" }, { name = "pydantic", specifier = ">=2.12.5" }, { name = "pygithub", specifier = ">=2.8.1" }, + { name = "pygments", specifier = ">=2.20.0" }, { name = "python-dotenv", specifier = ">=1.0.0" }, { name = "tree-sitter", specifier = ">=0.25.2" }, { name = "tree-sitter-python", specifier = ">=0.25.0" },