From 520faa7f2ce172fa50aebf01455989524f1d9ce4 Mon Sep 17 00:00:00 2001 From: dst03106 Date: Sun, 1 Jun 2025 00:36:25 +0900 Subject: [PATCH 1/3] feat: include item count in TODO sections summary --- pr_agent/algo/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index d89cb212..4ce4b389 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -274,7 +274,7 @@ def convert_to_markdown_v2(output_data: dict, if is_value_no(value): markdown_text += f"{emoji} No TODO sections" else: - markdown_text += f"
{emoji} TODO sections\n\n" + markdown_text += f"
{emoji} TODO sections ({len(value)} items)\n\n" if isinstance(value, list): markdown_text += "
    \n" for todo_item in value: From 3f9cade14db08406b2c83708d50392512e8f2ad5 Mon Sep 17 00:00:00 2001 From: dst03106 Date: Sun, 1 Jun 2025 14:14:18 +0900 Subject: [PATCH 2/3] feat: add todos_summary to review output in markdown conversion --- pr_agent/algo/utils.py | 5 +++-- pr_agent/settings/pr_reviewer_prompts.toml | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 4ce4b389..5eba1a91 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -164,6 +164,7 @@ def convert_to_markdown_v2(output_data: dict, if gfm_supported: markdown_text += "\n" + todos_summary = output_data['review'].pop('todos_summary', '') for key, value in output_data['review'].items(): if value is None or value == '' or value == {} or value == []: if key.lower() not in ['can_be_split', 'key_issues_to_review']: @@ -274,7 +275,7 @@ def convert_to_markdown_v2(output_data: dict, if is_value_no(value): markdown_text += f"{emoji} No TODO sections" else: - markdown_text += f"
    {emoji} TODO sections ({len(value)} items)\n\n" + markdown_text += f"{emoji} TODO sections ({len(value)} items)\n
    {todos_summary}\n\n" if isinstance(value, list): markdown_text += "
      \n" for todo_item in value: @@ -288,7 +289,7 @@ def convert_to_markdown_v2(output_data: dict, if is_value_no(value): markdown_text += f"### {emoji} No TODO sections\n\n" else: - markdown_text += f"
      ### {emoji} TODO sections\n\n" + markdown_text += f"### {emoji} TODO sections ({len(value)} items)\n
      {todos_summary}\n\n" if isinstance(value, list): for todo_item in value: markdown_text += f"- {format_todo_item(todo_item)}\n" diff --git a/pr_agent/settings/pr_reviewer_prompts.toml b/pr_agent/settings/pr_reviewer_prompts.toml index c0bb8b1b..6d94acd6 100644 --- a/pr_agent/settings/pr_reviewer_prompts.toml +++ b/pr_agent/settings/pr_reviewer_prompts.toml @@ -109,6 +109,18 @@ class Review(BaseModel): {%- endif %} {%- if require_todo_scan %} todo_sections: Union[List[TodoSection], str] = Field(description="A list of TODO comments found in the code. Return 'No' (as a string) if there are no TODO comments.") + todos_summary: str = Field(description="When writing TODO section summaries, use this format: + [count] TODOs found about [functional area based on TODO content] + + - The [count] is the number of TODO items, equal to the length of the `todo_sections` list. + - Functional areas describe what the TODOs are about: + testing, error handling, validation, documentation, performance, + security, logging, refactoring, API design, UI/UX + + Example: + 3 TODOs found about input validation and error handling + + Return 'No' (as a string) if there are no TODO comments.") {%- endif %} {%- if require_can_be_split_review %} can_be_split: List[SubPR] = Field(min_items=0, max_items=3, description="Can this PR, which contains {{ num_pr_files }} changed files in total, be divided into smaller sub-PRs with distinct tasks that can be reviewed and merged independently, regardless of the order ? Make sure that the sub-PRs are indeed independent, with no code dependencies between them, and that each sub-PR represent a meaningful independent task. Output an empty list if the PR code does not need to be split.") @@ -158,6 +170,8 @@ review: No todo_sections: No + todos_summary: + No {%- if require_can_be_split_review %} can_be_split: - relevant_files: @@ -278,6 +292,8 @@ review: No todo_sections: No + todos_summary: + No {%- if require_can_be_split_review %} can_be_split: - relevant_files: From d8fb24c971f3c2457902efb132f6c9ca8bd8fe12 Mon Sep 17 00:00:00 2001 From: dst03106 Date: Sun, 1 Jun 2025 14:14:38 +0900 Subject: [PATCH 3/3] refactor: remove unused HTML formatting function from utils --- pr_agent/algo/utils.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 5eba1a91..2550e1ee 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -224,16 +224,6 @@ 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_multiline_html_item(file: str, line_range: Tuple[int, int], content: str, url: str) -> str: - label = f"{file} [{line_range[0]}-{line_range[1]}]" if line_range[0] != line_range[1] else f"{file} [{line_range[0]}]" - first_line, *rest_lines = content.strip().split("\n") - if rest_lines: - rest = "
      ".join(rest_lines) - return f"
    • {label}: {first_line}
      {rest}
    • " - else: - return f"
    • {label}: {first_line}
    • " - def format_todo_item(todo_item: TodoItem) -> str: relevant_file = todo_item.get('relevant_file', '').strip() line_range = todo_item.get('line_range', [])