mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-12 16:50:37 +08:00
Merge branch 'main' into mrT23-patch-1
This commit is contained in:
13
README.md
13
README.md
@ -32,11 +32,9 @@ Making pull requests less painful with an AI agent
|
|||||||
- [Why use PR-Agent?](#why-use-pr-agent)
|
- [Why use PR-Agent?](#why-use-pr-agent)
|
||||||
|
|
||||||
## News and Updates
|
## News and Updates
|
||||||
### Jan 18, 2024
|
### Jan 21, 2024
|
||||||
We are very happy to share our new paper:
|
- 💎 Custom suggestions - A new tool, `/custom_suggestions`, was added to PR-Agent Pro. The tool will propose only suggestions that follow specific guidelines defined by the user.
|
||||||
**"Code Generation with AlphaCodium: From Prompt Engineering to Flow Engineering".**
|
See [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/CUSTOM_SUGGESTIONS.md) for more details.
|
||||||
|
|
||||||
Go checkout our official implementation [here](https://github.com/Codium-ai/AlphaCodium)
|
|
||||||
|
|
||||||
### Jan 17, 2024
|
### Jan 17, 2024
|
||||||
- 💎 Inline file summary - The `describe` tool has a new option `--pr_description.inline_file_summary`, which allows to add a summary of each file changes to the Diffview page. See [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-)
|
- 💎 Inline file summary - The `describe` tool has a new option `--pr_description.inline_file_summary`, which allows to add a summary of each file changes to the Diffview page. See [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-)
|
||||||
@ -75,6 +73,8 @@ CodiumAI PR-Agent is an open-source tool to help efficiently review and handle p
|
|||||||
‣ **Generate Custom Labels 💎 ([`/generate_labels`](./docs/GENERATE_CUSTOM_LABELS.md))**: Automatically suggests custom labels based on the PR code changes.
|
‣ **Generate Custom Labels 💎 ([`/generate_labels`](./docs/GENERATE_CUSTOM_LABELS.md))**: Automatically suggests custom labels based on the PR code changes.
|
||||||
\
|
\
|
||||||
‣ **Analyze 💎 ([`/analyze`](./docs/Analyze.md))**: Automatically analyzes the PR, and presents changes walkthrough for each component.
|
‣ **Analyze 💎 ([`/analyze`](./docs/Analyze.md))**: Automatically analyzes the PR, and presents changes walkthrough for each component.
|
||||||
|
\
|
||||||
|
‣ **Custom Suggestions 💎 ([`/custom_suggestions`](./docs/CUSTOM_SUGGESTIONS.md))**: Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user.
|
||||||
|
|
||||||
|
|
||||||
See the [Installation Guide](./INSTALL.md) for instructions on installing and running the tool on different git platforms.
|
See the [Installation Guide](./INSTALL.md) for instructions on installing and running the tool on different git platforms.
|
||||||
@ -89,7 +89,7 @@ See the [Tools Guide](./docs/TOOLS_GUIDE.md) for a detailed description of the d
|
|||||||
<h4><a href="https://github.com/Codium-ai/pr-agent/pull/530">/describe</a></h4>
|
<h4><a href="https://github.com/Codium-ai/pr-agent/pull/530">/describe</a></h4>
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<p float="center">
|
<p float="center">
|
||||||
<img src="https://www.codium.ai/images/pr_agent/describe_short_main.png" width="800">
|
<img src="https://www.codium.ai/images/pr_agent/describe_new_short_main.png" width="800">
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
@ -164,6 +164,7 @@ See the [Tools Guide](./docs/TOOLS_GUIDE.md) for a detailed description of the d
|
|||||||
| | ⮑ [Inline file summary](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-) 💎 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| | ⮑ [Inline file summary](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#inline-file-summary-) 💎 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| | Improve | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| | Improve | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| | ⮑ Extended | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| | ⮑ Extended | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
|
| | [Custom Suggestions](https://github.com/Codium-ai/pr-agent/blob/main/docs/CUSTOM_SUGGESTIONS.md) 💎 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| | Reflect and Review | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| | Reflect and Review | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| | Update CHANGELOG.md | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| | Update CHANGELOG.md | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| | Find Similar Issue | :white_check_mark: | | |
|
| | Find Similar Issue | :white_check_mark: | | |
|
||||||
|
65
docs/CUSTOM_SUGGESTIONS.md
Normal file
65
docs/CUSTOM_SUGGESTIONS.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Custom Suggestions Tool 💎
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Example usage](#example-usage)
|
||||||
|
- [Configuration options](#configuration-options)
|
||||||
|
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
The `custom_suggestions` tool scans the PR code changes, and automatically generates custom suggestions for improving the PR code.
|
||||||
|
It shares similarities with the `improve` tool, but with one main difference: the `custom_suggestions` tool will only propose suggestions that follow specific guidelines defined by the prompt in: `pr_custom_suggestions.prompt` configuration.
|
||||||
|
|
||||||
|
The tool can be triggered [automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) every time a new PR is opened, or can be invoked manually by commenting on a PR.
|
||||||
|
|
||||||
|
When commenting, use the following template:
|
||||||
|
|
||||||
|
```
|
||||||
|
/custom_suggestions --pr_custom_suggestions.prompt="The suggestions should focus only on the following:\n-...\n-...\n-..."
|
||||||
|
```
|
||||||
|
|
||||||
|
With a [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app), use the following template:
|
||||||
|
|
||||||
|
```
|
||||||
|
[pr_custom_suggestions]
|
||||||
|
prompt="""\
|
||||||
|
The suggestions should focus only on the following:
|
||||||
|
-...
|
||||||
|
-...
|
||||||
|
-...
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
Using a configuration file is recommended, since it allows to use multi-line instructions.
|
||||||
|
|
||||||
|
Don't forget - with this tool, you are the prompter. Be specific, clear, and concise in the instructions. Specify relevant aspects that you want the model to focus on. \
|
||||||
|
You might benefit from several trial-and-error iterations, until you get the correct prompt for your use case.
|
||||||
|
|
||||||
|
## Example usage
|
||||||
|
|
||||||
|
Here is an example of a possible prompt:
|
||||||
|
```
|
||||||
|
[pr_custom_suggestions]
|
||||||
|
prompt="""\
|
||||||
|
The suggestions should focus only on the following:
|
||||||
|
- look for edge cases when implementing a new function
|
||||||
|
- make sure every variable has a meaningful name
|
||||||
|
- make sure the code is efficient
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
The instructions above are just an example. We want to emphasize that the prompt should be specific and clear, and be tailored to the needs of your project.
|
||||||
|
|
||||||
|
Results obtained with the prompt above:
|
||||||
|
___
|
||||||
|
<kbd><img src=https://codium.ai/images/pr_agent/custom_suggestions_prompt.png width="512"></kbd>
|
||||||
|
___
|
||||||
|
<kbd><img src=https://codium.ai/images/pr_agent/custom_suggestions_result.png width="768"></kbd>
|
||||||
|
___
|
||||||
|
|
||||||
|
## Configuration options
|
||||||
|
|
||||||
|
`prompt`: the prompt for the tool. It should be a multi-line string.
|
||||||
|
|
||||||
|
`num_code_suggestions`: number of code suggestions provided by the 'custom_suggestions' tool. Default is 4.
|
||||||
|
|
||||||
|
`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true.
|
@ -20,7 +20,7 @@ For example:
|
|||||||
___
|
___
|
||||||
<kbd><img src=https://codium.ai/images/pr_agent/describe_comment.png width="768"></kbd>
|
<kbd><img src=https://codium.ai/images/pr_agent/describe_comment.png width="768"></kbd>
|
||||||
___
|
___
|
||||||
<kbd><img src=https://codium.ai/images/pr_agent/describe.png width="768"></kbd>
|
<kbd><img src=https://codium.ai/images/pr_agent/describe_new.png width="768"></kbd>
|
||||||
___
|
___
|
||||||
|
|
||||||
### Configuration options
|
### Configuration options
|
||||||
@ -50,12 +50,15 @@ To edit [configurations](./../pr_agent/settings/configuration.toml#L46) related
|
|||||||
- `collapsible_file_list`: if set to true, the file list in the "Changes walkthrough" section will be collapsible. If set to "adaptive", the file list will be collapsible only if there are more than 8 files. Default is "adaptive".
|
- `collapsible_file_list`: if set to true, the file list in the "Changes walkthrough" section will be collapsible. If set to "adaptive", the file list will be collapsible only if there are more than 8 files. Default is "adaptive".
|
||||||
|
|
||||||
### Inline file summary 💎
|
### Inline file summary 💎
|
||||||
To enable inline file summary, set `pr_description.inline_file_summary=true` in the configuration file.
|
> This feature is available only in PR-Agent Pro
|
||||||
|
|
||||||
When the feature is enabled, PR-Agent Pro will add a collapsable summary of each file change in the "Files changed" tab.
|
|
||||||
This will enable you to quickly understand the changes in each file, while reviewing the code changes (diff view).
|
This will enable you to quickly understand the changes in each file, while reviewing the code changes (diff view).
|
||||||
|
To enable inline file summary, set `pr_description.inline_file_summary` in the configuration file, possible values are:
|
||||||
|
- `'table'`: File changes walkthrough table will be displayed on the top of the "Files changed" tab, in addition to the "Conversation" tab.
|
||||||
|
<kbd><img src=https://codium.ai/images/pr_agent/diffview-table.png width="1024"></kbd>
|
||||||
|
- `true`: A collapsable file comment with changes title and a changes summary for each file in the PR.
|
||||||
<kbd><img src=https://codium.ai/images/pr_agent/diffview_changes.png width="1024"></kbd>
|
<kbd><img src=https://codium.ai/images/pr_agent/diffview_changes.png width="1024"></kbd>
|
||||||
|
- `false` (`default`): File changes walkthrough will be added only to the "Conversation" tab.
|
||||||
|
|
||||||
*Note that this feature is currently available only for GitHub.
|
*Note that this feature is currently available only for GitHub.
|
||||||
|
|
||||||
|
@ -175,6 +175,17 @@ Make sure to provide proper title, and a detailed and well-phrased description f
|
|||||||
"""
|
"""
|
||||||
output += "\n\n</details></td></tr>\n\n"
|
output += "\n\n</details></td></tr>\n\n"
|
||||||
|
|
||||||
|
# Inline File Walkthrough
|
||||||
|
output += "<tr><td><details> <summary><strong> Inline File Walkthrough 💎</strong></summary><hr>\n\n"
|
||||||
|
output += """\
|
||||||
|
For enhanced user experience, the `describe` tool can add file summaries directly to the "Files changed" tab in the PR page.
|
||||||
|
This will enable you to quickly understand the changes in each file, while reviewing the code changes (diffs).
|
||||||
|
|
||||||
|
To enable inline file summary, set `pr_description.inline_file_summary` in the configuration file, possible values are:
|
||||||
|
- `'table'`: File changes walkthrough table will be displayed on the top of the "Files changed" tab, in addition to the "Conversation" tab.
|
||||||
|
- `true`: A collapsable file comment with changes title and a changes summary for each file in the PR.
|
||||||
|
- `false` (default): File changes walkthrough will be added only to the "Conversation" tab.
|
||||||
|
"""
|
||||||
# extra instructions
|
# extra instructions
|
||||||
output += "<tr><td><details> <summary><strong> Utilizing extra instructions</strong></summary><hr>\n\n"
|
output += "<tr><td><details> <summary><strong> Utilizing extra instructions</strong></summary><hr>\n\n"
|
||||||
output += '''\
|
output += '''\
|
||||||
|
@ -56,7 +56,7 @@ enable_help_text=true
|
|||||||
## changes walkthrough section
|
## changes walkthrough section
|
||||||
enable_semantic_files_types=true
|
enable_semantic_files_types=true
|
||||||
collapsible_file_list='adaptive' # true, false, 'adaptive'
|
collapsible_file_list='adaptive' # true, false, 'adaptive'
|
||||||
inline_file_summary=true # Pro feature
|
inline_file_summary=false # false, true, 'table'
|
||||||
# markers
|
# markers
|
||||||
use_description_markers=false
|
use_description_markers=false
|
||||||
include_generated_by_header=true
|
include_generated_by_header=true
|
||||||
|
@ -39,7 +39,8 @@ class PRType(str, Enum):
|
|||||||
|
|
||||||
Class FileDescription(BaseModel):
|
Class FileDescription(BaseModel):
|
||||||
filename: str = Field(description="the relevant file full path")
|
filename: str = Field(description="the relevant file full path")
|
||||||
changes_summary: str = Field(description="minimal and concise summary of the changes in the relevant file")
|
changes_summary: str = Field(description="concise summary of the changes in the relevant file, in bullet points (1-4 bullet points).")
|
||||||
|
changes_title: str = Field(description="an informative title for the changes in the files, describing its main theme (5-10 words).")
|
||||||
label: str = Field(description="a single semantic label that represents a type of code changes that occurred in the File. Possible values (partial list): 'bug fix', 'tests', 'enhancement', 'documentation', 'error handling', 'configuration changes', 'dependencies', 'formatting', 'miscellaneous', ...")
|
label: str = Field(description="a single semantic label that represents a type of code changes that occurred in the File. Possible values (partial list): 'bug fix', 'tests', 'enhancement', 'documentation', 'error handling', 'configuration changes', 'dependencies', 'formatting', 'miscellaneous', ...")
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
@ -68,6 +69,8 @@ pr_files:
|
|||||||
...
|
...
|
||||||
changes_summary: |
|
changes_summary: |
|
||||||
...
|
...
|
||||||
|
changes_title: |
|
||||||
|
...
|
||||||
label: |
|
label: |
|
||||||
...
|
...
|
||||||
...
|
...
|
||||||
|
@ -333,10 +333,11 @@ class PRDescription:
|
|||||||
try:
|
try:
|
||||||
filename = file['filename'].replace("'", "`").replace('"', '`')
|
filename = file['filename'].replace("'", "`").replace('"', '`')
|
||||||
changes_summary = file['changes_summary']
|
changes_summary = file['changes_summary']
|
||||||
|
changes_title = file['changes_title'].strip()
|
||||||
label = file.get('label')
|
label = file.get('label')
|
||||||
if label not in self.file_label_dict:
|
if label not in self.file_label_dict:
|
||||||
self.file_label_dict[label] = []
|
self.file_label_dict[label] = []
|
||||||
self.file_label_dict[label].append((filename, changes_summary))
|
self.file_label_dict[label].append((filename, changes_title, changes_summary))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
get_logger().error(f"Error preparing file label dict {self.pr_id}: {e}")
|
get_logger().error(f"Error preparing file label dict {self.pr_id}: {e}")
|
||||||
pass
|
pass
|
||||||
@ -357,9 +358,9 @@ class PRDescription:
|
|||||||
try:
|
try:
|
||||||
pr_body += "<table>"
|
pr_body += "<table>"
|
||||||
header = f"Relevant files"
|
header = f"Relevant files"
|
||||||
delta = 65
|
delta = 77
|
||||||
header += " " * delta
|
# header += " " * delta
|
||||||
pr_body += f"""<thead><tr><th></th><th>{header}</th></tr></thead>"""
|
pr_body += f"""<thead><tr><th></th><th align="left">{header}</th></tr></thead>"""
|
||||||
pr_body += """<tbody>"""
|
pr_body += """<tbody>"""
|
||||||
for semantic_label in value.keys():
|
for semantic_label in value.keys():
|
||||||
s_label = semantic_label.strip("'").strip('"')
|
s_label = semantic_label.strip("'").strip('"')
|
||||||
@ -370,19 +371,24 @@ class PRDescription:
|
|||||||
pr_body += f"""<td><details><summary>{len(list_tuples)} files</summary><table>"""
|
pr_body += f"""<td><details><summary>{len(list_tuples)} files</summary><table>"""
|
||||||
else:
|
else:
|
||||||
pr_body += f"""<td><table>"""
|
pr_body += f"""<td><table>"""
|
||||||
for filename, file_change_description in list_tuples:
|
for filename, file_changes_title, file_change_description in list_tuples:
|
||||||
filename = filename.replace("'", "`")
|
filename = filename.replace("'", "`")
|
||||||
filename_publish = filename.split("/")[-1]
|
filename_publish = filename.split("/")[-1]
|
||||||
filename_publish = f"{filename_publish}"
|
file_changes_title_br = insert_br_after_x_chars(file_changes_title, x=(delta - 5),
|
||||||
if len(filename_publish) < (delta - 5):
|
new_line_char="\n\n")
|
||||||
filename_publish += " " * ((delta - 5) - len(filename_publish))
|
file_changes_title_extended = file_changes_title_br.strip() + "</code>"
|
||||||
|
if len(file_changes_title_extended) < (delta - 5):
|
||||||
|
file_changes_title_extended += " " * ((delta - 5) - len(file_changes_title_extended))
|
||||||
|
filename_publish = f"<strong>{filename_publish}</strong><dd><code>{file_changes_title_extended}</dd>"
|
||||||
diff_plus_minus = ""
|
diff_plus_minus = ""
|
||||||
|
delta_nbsp = ""
|
||||||
diff_files = self.git_provider.diff_files
|
diff_files = self.git_provider.diff_files
|
||||||
for f in diff_files:
|
for f in diff_files:
|
||||||
if f.filename.lower() == filename.lower():
|
if f.filename.lower() == filename.lower():
|
||||||
num_plus_lines = f.num_plus_lines
|
num_plus_lines = f.num_plus_lines
|
||||||
num_minus_lines = f.num_minus_lines
|
num_minus_lines = f.num_minus_lines
|
||||||
diff_plus_minus += f"+{num_plus_lines}/-{num_minus_lines}"
|
diff_plus_minus += f"+{num_plus_lines}/-{num_minus_lines}"
|
||||||
|
delta_nbsp = " " * max(0, (8 - len(diff_plus_minus)))
|
||||||
break
|
break
|
||||||
|
|
||||||
# try to add line numbers link to code suggestions
|
# try to add line numbers link to code suggestions
|
||||||
@ -391,21 +397,19 @@ class PRDescription:
|
|||||||
filename = filename.strip()
|
filename = filename.strip()
|
||||||
link = self.git_provider.get_line_link(filename, relevant_line_start=-1)
|
link = self.git_provider.get_line_link(filename, relevant_line_start=-1)
|
||||||
|
|
||||||
file_change_description = insert_br_after_x_chars(file_change_description, x=(delta - 5))
|
file_change_description_br = insert_br_after_x_chars(file_change_description, x=(delta - 5))
|
||||||
pr_body += f"""
|
pr_body += f"""
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<details>
|
<details>
|
||||||
<summary><strong>{filename_publish}</strong></summary>
|
<summary>{filename_publish}</summary>
|
||||||
<ul>
|
<hr>
|
||||||
{filename}<br><br>
|
|
||||||
|
|
||||||
**{file_change_description}**
|
{filename}
|
||||||
</ul>
|
{file_change_description_br}
|
||||||
</details>
|
</details>
|
||||||
</td>
|
</td>
|
||||||
<td><a href="{link}"> {diff_plus_minus}</a></td>
|
<td><a href="{link}">{diff_plus_minus}</a>{delta_nbsp}</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
"""
|
"""
|
||||||
if use_collapsible_file_list:
|
if use_collapsible_file_list:
|
||||||
@ -419,25 +423,48 @@ class PRDescription:
|
|||||||
pass
|
pass
|
||||||
return pr_body
|
return pr_body
|
||||||
|
|
||||||
def insert_br_after_x_chars(text, x=70):
|
def insert_br_after_x_chars(text, x=70, new_line_char="<br> "):
|
||||||
"""
|
"""
|
||||||
Insert <br> into a string after a word that increases its length above x characters.
|
Insert <br> into a string after a word that increases its length above x characters.
|
||||||
"""
|
"""
|
||||||
if len(text) < x:
|
if len(text) < x:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
words = text.split(' ')
|
lines = text.splitlines()
|
||||||
|
words = []
|
||||||
|
for i,line in enumerate(lines):
|
||||||
|
words += line.split(' ')
|
||||||
|
if i<len(lines)-1:
|
||||||
|
words[-1] += "\n"
|
||||||
|
|
||||||
|
|
||||||
|
# words = text.split(' ')
|
||||||
|
|
||||||
new_text = ""
|
new_text = ""
|
||||||
current_length = 0
|
current_length = 0
|
||||||
|
is_inside_code = False
|
||||||
for word in words:
|
for word in words:
|
||||||
# Check if adding this word exceeds x characters
|
# Check if adding this word exceeds x characters
|
||||||
if current_length + len(word) > x:
|
if current_length + len(word) > x:
|
||||||
new_text += "<br>" # Insert line break
|
if not is_inside_code:
|
||||||
|
new_text += f"{new_line_char} " # Insert line break
|
||||||
current_length = 0 # Reset counter
|
current_length = 0 # Reset counter
|
||||||
|
else:
|
||||||
|
new_text += f"`{new_line_char} `"
|
||||||
|
# check if inside <code> tag
|
||||||
|
if word.startswith("`") and not is_inside_code and not word.endswith("`"):
|
||||||
|
is_inside_code = True
|
||||||
|
if word.endswith("`"):
|
||||||
|
is_inside_code = False
|
||||||
|
|
||||||
# Add the word to the new text
|
# Add the word to the new text
|
||||||
|
if word.endswith("\n"):
|
||||||
|
new_text += word
|
||||||
|
else:
|
||||||
new_text += word + " "
|
new_text += word + " "
|
||||||
current_length += len(word) + 1 # Add 1 for the space
|
current_length += len(word) + 1 # Add 1 for the space
|
||||||
|
|
||||||
|
|
||||||
|
if word.endswith("\n"):
|
||||||
|
current_length = 0
|
||||||
return new_text.strip() # Remove trailing space
|
return new_text.strip() # Remove trailing space
|
||||||
|
Reference in New Issue
Block a user