diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 87411430..9a150864 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -474,4 +474,13 @@ def clip_tokens(text: str, max_tokens: int, add_three_dots=True) -> str: return clipped_text except Exception as e: get_logger().warning(f"Failed to clip tokens: {e}") - return text \ No newline at end of file + return text + +def replace_code_tags(text): + """ + Replace odd instances of ` with and even instances of ` with + """ + parts = text.split('`') + for i in range(1, len(parts), 2): + parts[i] = '' + parts[i] + '' + return ''.join(parts) \ No newline at end of file diff --git a/pr_agent/settings/pr_code_suggestions_prompts.toml b/pr_agent/settings/pr_code_suggestions_prompts.toml index 5aa3cce2..2fb224c7 100644 --- a/pr_agent/settings/pr_code_suggestions_prompts.toml +++ b/pr_agent/settings/pr_code_suggestions_prompts.toml @@ -47,14 +47,15 @@ Extra instructions from the user: ====== {%- endif %} -The output must be a YAML object equivalent to type PRCodeSuggestions, according to the following Pydantic definitions: +The output must be a YAML object equivalent to type $PRCodeSuggestions, according to the following Pydantic definitions: ===== class CodeSuggestion(BaseModel): relevant_file: str = Field(description="the relevant file full path") suggestion_content: str = Field(description="an actionable suggestion for meaningfully improving the new code introduced in the PR") {%- if summarize_mode %} - existing_code: str = Field(description="a short code snippet from a '__new hunk__' section to illustrate the relevant existing code. Don't show the line numbers. Shorten parts of the code ('...') if needed") - improved_code: str = Field(description="a short code snippet to illustrate the improved code, after applying the suggestion. Shorten parts of the code ('...') if needed") + existing_code: str = Field(description="a short code snippet from a '__new hunk__' section to illustrate the relevant existing code. Don't show the line numbers.") + improved_code: str = Field(description="a short code snippet to illustrate the improved code, after applying the suggestion.") + one_sentence_summary:str = Field(description="a short summary of the suggestion action, in a single sentence. Focus on the 'what'. Be general, and avoid method or variable names.") {%- else %} existing_code: str = Field(description="a code snippet, demonstrating the relevant code lines from a '__new hunk__' section. It must be contiguous, correctly formatted and indented, and without line numbers") improved_code: str = Field(description="a new code snippet, that can be used to replace the relevant lines in '__new hunk__' code. Replacement suggestions should be complete, correctly formatted and indented, and without line numbers") @@ -75,12 +76,23 @@ code_suggestions: src/file1.py suggestion_content: |- Add a docstring to func1() +{%- if summarize_mode %} + existing_code: |- + def func1(): + improved_code: |- + ... + one_sentence_summary: |- + ... + relevant_lines_start: 12 + relevant_lines_end: 12 +{%- else %} existing_code: |- def func1(): relevant_lines_start: 12 relevant_lines_end: 12 improved_code: |- ... +{%- endif %} label: |- ... ``` diff --git a/pr_agent/tools/pr_code_suggestions.py b/pr_agent/tools/pr_code_suggestions.py index b3929df5..2b143905 100644 --- a/pr_agent/tools/pr_code_suggestions.py +++ b/pr_agent/tools/pr_code_suggestions.py @@ -8,7 +8,7 @@ from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.pr_processing import get_pr_diff, get_pr_multi_diffs, retry_with_fallback_models from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import load_yaml +from pr_agent.algo.utils import load_yaml, replace_code_tags from pr_agent.config_loader import get_settings from pr_agent.git_providers import get_git_provider from pr_agent.git_providers.git_provider import get_main_pr_language @@ -327,7 +327,7 @@ class PRCodeSuggestions: for label, suggestions in suggestions_labels.items(): pr_body += f"""{label}""" pr_body += f"""""" - pr_body += f"""
{len(suggestions)} suggestions""" + # pr_body += f"""
{len(suggestions)} suggestions""" pr_body += f"""""" for suggestion in suggestions: @@ -344,83 +344,43 @@ class PRCodeSuggestions: # add html table for each suggestion suggestion_content = suggestion['suggestion_content'].rstrip().rstrip() + # backticks + suggestion_content = replace_code_tags(suggestion_content) + suggestion_content = insert_br_after_x_chars(suggestion_content, 90) # pr_body += f" - - - +{example_code} """ + pr_body += f"" + pr_body += f"" pr_body += """
{suggestion_content}" existing_code = suggestion['existing_code'].rstrip()+"\n" improved_code = suggestion['improved_code'].rstrip()+"\n" - language_name = "python" - diff = difflib.unified_diff(existing_code.split('\n'), - improved_code.split('\n')) - patch_orig = "\n".join(diff) - print(patch_orig) - patch = "\n".join(patch_orig.splitlines()[5:]).strip('\n') - extension_s = suggestion['relevant_file'].rsplit('.')[-1] - if extension_s and (extension_s in extension_to_language): - language_name = extension_to_language[extension_s] - if len(suggestions) > 1: - example_code = "
Preview code:\n\n" - else: - example_code = "" - example_code += f"___\n\n" - if len(suggestions) == 1: - example_code +="Preview code:\n" + diff = difflib.unified_diff(existing_code.split('\n'), + improved_code.split('\n'), n=999) + patch_orig = "\n".join(diff) + patch = "\n".join(patch_orig.splitlines()[5:]).strip('\n') + + example_code = "" example_code += f"```diff\n{patch}\n```\n" - # example_code += f"Existing code:\n```{language_name}\n{existing_code}\n```\n" - # example_code += f"Improved code:\n```{language_name}\n{improved_code}\n```\n" - if len(suggestions) > 1: - example_code += "
\n" + + pr_body += f"""
""" + suggestion_summary = suggestion['one_sentence_summary'].strip() + suggestion_summary= suggestion_summary + max((77-len(suggestion_summary)), 0)*" " + pr_body += f"""\n\n
{suggestion_summary}\n\n___\n\n""" pr_body += f""" -
**{suggestion_content}** [{relevant_file} {range_str}]({code_snippet_link}) -{example_code} -
""" - pr_body += "
" + # pr_body += "
" pr_body += """""" pr_body += """""" - # for s in data['code_suggestions']: - # try: - # extension_s = s['relevant_file'].rsplit('.')[-1] - # code_snippet_link = self.git_provider.get_line_link(s['relevant_file'], s['relevant_lines_start'], - # s['relevant_lines_end']) - # label = s['label'].strip() - # data_markdown += f"\n💡 [{label}]\n\n**{s['suggestion_content'].rstrip().rstrip()}**\n\n" - # if code_snippet_link: - # data_markdown += f" File: [{s['relevant_file']} ({s['relevant_lines_start']}-{s['relevant_lines_end']})]({code_snippet_link})\n\n" - # else: - # data_markdown += f"File: {s['relevant_file']} ({s['relevant_lines_start']}-{s['relevant_lines_end']})\n\n" - # if self.git_provider.is_supported("gfm_markdown"): - # data_markdown += "
Example code:\n\n" - # data_markdown += f"___\n\n" - # language_name = "python" - # if extension_s and (extension_s in extension_to_language): - # language_name = extension_to_language[extension_s] - # data_markdown += f"Existing code:\n```{language_name}\n{s['existing_code'].rstrip()}\n```\n" - # data_markdown += f"Improved code:\n```{language_name}\n{s['improved_code'].rstrip()}\n```\n" - # if self.git_provider.is_supported("gfm_markdown"): - # data_markdown += "
\n" - # data_markdown += "\n___\n\n" - # - # pr_body += f"""{label}{s['relevant_file']}""" - # # in the right side of the table, add two collapsable sections with the existing and improved code - # pr_body += f"""
Existing code
{s['existing_code'].rstrip()}
""" - # pr_body += f"""
Improved code
{s['improved_code'].rstrip()}
""" - # - # - # except Exception as e: - # get_logger().error(f"Could not parse suggestion: {s}, error: {e}") self.git_provider.publish_comment(pr_body) except Exception as e: get_logger().info(f"Failed to publish summarized code suggestions, error: {e}")