diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 1f00b5e1..00d52a14 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -224,81 +224,22 @@ def convert_to_markdown_v2(output_data: dict, value = emphasize_header(value.strip(), only_markdown=True) markdown_text += f"{value}\n\n" elif 'todo sections' in key_nice.lower(): - def format_todo_item(todo_item: TodoItem) -> str: - relevant_file = todo_item.get('relevant_file', '').strip() - line_range = todo_item.get('line_range', []) - content = todo_item.get('content', '') - reference_link = None - - if isinstance(line_range, str): - line_range = ast.literal_eval(line_range.strip()) - try: - if git_provider and relevant_file and line_range: - reference_link = git_provider.get_line_link(relevant_file, line_range[0], line_range[1]) - except Exception as e: - get_logger().exception(f"Error generating link: {e}") - line_str = f"[{line_range[0]}]" if line_range[0] == line_range[1] else f"[{line_range[0]}-{line_range[1]}]" - return f"{relevant_file} {line_str}: {content}" - - line_str = f"[{line_range[0]}]" if line_range[0] == line_range[1] else f"[{line_range[0]}-{line_range[1]}]" - file_ref = f"{relevant_file} {line_str}" - if reference_link: - if gfm_supported: - file_ref = f"{file_ref}" - else: - file_ref = f"[{file_ref}]({reference_link})" - - content_lines = content.strip().split("\n") - # if TODO content is single-line : - if len(content_lines) == 1: - return f"{file_ref}: {content_lines[0]}" - # else if TODO content is multi-line: - elif len(content_lines) > 1: - content_lines = "
".join(content_lines) - return f"{file_ref}:
\n{content_lines}\n
" - # else if TODO content is empty: - else: - return file_ref - - def format_todo_items(value: list[TodoItem] | TodoItem) -> str: - markdown_text = "" - if gfm_supported: - if isinstance(value, list): - markdown_text += "\n" - else: - markdown_text += f"

{format_todo_item(value)}

\n" - else: - if isinstance(value, list): - for todo_item in value: - markdown_text += f"- {format_todo_item(todo_item)}\n" - else: - markdown_text += f"- {format_todo_item(value)}\n" - return markdown_text - if gfm_supported: markdown_text += "" if is_value_no(value): - markdown_text += f"{emoji} No TODO sections" + markdown_text += f"✅ No TODO sections" else: - markdown_todo_items = format_todo_items(value) - + markdown_todo_items = format_todo_items(value, git_provider, gfm_supported) markdown_text += f"{emoji} TODO sections\n

\n" - markdown_text += f"
{todo_summary}\n\n" markdown_text += markdown_todo_items - markdown_text += "\n
\n" markdown_text += "\n" else: if is_value_no(value): - markdown_text += f"### {emoji} No TODO sections\n\n" + markdown_text += f"### ✅ No TODO sections\n\n" else: - markdown_todo_items = format_todo_items(value) - - markdown_text += f"### {emoji} TODO sections\n
{todo_summary}\n\n" + markdown_todo_items = format_todo_items(value, git_provider, gfm_supported) + markdown_text += f"### {emoji} TODO sections\n\n" markdown_text += markdown_todo_items - markdown_text += "\n
\n\n" elif 'can be split' in key_nice.lower(): if gfm_supported: markdown_text += f"" @@ -1457,3 +1398,47 @@ def set_file_languages(diff_files) -> List[FilePatchInfo]: get_logger().exception(f"Failed to set file languages: {e}") return diff_files + +def format_todo_item(todo_item: TodoItem, git_provider, gfm_supported) -> str: + relevant_file = todo_item.get('relevant_file', '').strip() + line_number = todo_item.get('line_number', '') + content = todo_item.get('content', '') + reference_link = git_provider.get_line_link(relevant_file, line_number, line_number) + file_ref = f"{relevant_file} [{line_number}]" + if reference_link: + if gfm_supported: + file_ref = f"{file_ref}" + else: + file_ref = f"[{file_ref}]({reference_link})" + + if content: + return f"{file_ref}: {content.strip()}" + else: + # if content is empty, return only the file reference + return file_ref + + +def format_todo_items(value: list[TodoItem] | TodoItem, git_provider, gfm_supported) -> str: + markdown_text = "" + MAX_ITEMS = 5 # limit the number of items to display + if gfm_supported: + if isinstance(value, list): + markdown_text += "\n" + else: + markdown_text += f"

{format_todo_item(value, git_provider, gfm_supported)}

\n" + else: + if isinstance(value, list): + if len(value) > MAX_ITEMS: + get_logger().debug(f"Truncating todo items to {MAX_ITEMS} items") + value = value[:MAX_ITEMS] + for todo_item in value: + markdown_text += f"- {format_todo_item(todo_item, git_provider, gfm_supported)}\n" + else: + markdown_text += f"- {format_todo_item(value, git_provider, gfm_supported)}\n" + return markdown_text \ No newline at end of file diff --git a/pr_agent/settings/pr_reviewer_prompts.toml b/pr_agent/settings/pr_reviewer_prompts.toml index 8c69e612..a6ef82c2 100644 --- a/pr_agent/settings/pr_reviewer_prompts.toml +++ b/pr_agent/settings/pr_reviewer_prompts.toml @@ -74,9 +74,9 @@ class KeyIssuesComponentLink(BaseModel): {%- if require_todo_scan %} class TodoSection(BaseModel): - relevant_file: str = Field(description="The file containing the TODO comment") - line_range: Tuple[int, int] = Field(description="Start and end line numbers of the TODO comment (inclusive). Must be a tuple of two integers, e.g., (7, 7) for a single line or (7, 10) for a range. Do not use list format [7, 7].") - content: str = Field(description="The content of the TODO comment. Only include actual TODO comments within code comments (e.g., lines starting with '#', '//', '/*', '