diff --git a/rhodecode/apps/ai_agents/models/base.py b/rhodecode/apps/ai_agents/models/base.py index 76db12bb..360e438c 100644 --- a/rhodecode/apps/ai_agents/models/base.py +++ b/rhodecode/apps/ai_agents/models/base.py @@ -95,19 +95,21 @@ class AIServiceBase: ) return user_msg - def numbered_code_block(self, review_content: list[dict[str, str]]) -> str: + def numbered_code_block(self, review_content: list[dict]) -> str: """ Render code with explicit 1-based line numbers so the model can reference them precisely. - We keep original content for returning 'line_text' in suggestions. """ parts: list[str] = [] for content in review_content: - lines = content["changes"].splitlines() - width = max(2, len(str(len(lines)))) if lines else 2 + full_code = content["content"].splitlines() + only_include_lines: list[int] = content["changed_lines"] + width = max(2, len(str(len(full_code)))) if full_code else 2 parts.append("FILE: %s\nTYPE: %s" % (content["file_name"], content["file_type"])) - if lines: - for i, line in enumerate(lines, start=1): - parts.append(f"{str(i).rjust(width)} | {line}") + if full_code: + for i, line in enumerate(full_code, start=1): + if i in only_include_lines: + # include only changes without losing index + parts.append(f"{str(i).rjust(width)} | {line}") else: parts.append("(empty file)") parts.append("") # blank line between files diff --git a/rhodecode/apps/ai_agents/models/gpt.py b/rhodecode/apps/ai_agents/models/gpt.py index 031725be..de9eae7b 100644 --- a/rhodecode/apps/ai_agents/models/gpt.py +++ b/rhodecode/apps/ai_agents/models/gpt.py @@ -8,6 +8,7 @@ from openai import OpenAI from rhodecode.apps.ai_agents.ai_settings import AISettings from rhodecode.apps.ai_agents.models.base import AIServiceBase, Request from rhodecode.lib.codeblocks import DiffSet +from rhodecode.lib.vcs.nodes import FileNode @dataclass @@ -44,7 +45,7 @@ class GPTService(AIServiceBase): ) -> Request: review_content = [] for f in pr_diffset.files: - target_file_node = f.get("target_filenode", None) + target_file_node: FileNode = f.get("target_filenode", None) if not target_file_node: self.log.warning("No target file node, skipping it") continue @@ -54,8 +55,15 @@ class GPTService(AIServiceBase): self.log.debug("No content, skipping file: %s", file_name) continue + modified_lines_nums = [] + for hunk in f.get("hunks", []): + for line in hunk.get("lines", []): + if line.get("modified") and line.get("modified", {}).get("action", "").strip(): + modified_lines_nums.append(line.get("modified", {}).get("lineno")) + file_content = { - "changes": target_file_node.str_content, + "content": target_file_node.str_content, + "changed_lines": modified_lines_nums, "file_name": file_name, "file_type": f.target_file_type, }