-
Notifications
You must be signed in to change notification settings - Fork 719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhancement of PR Agent with User Interaction #78
Changes from all commits
fa90b24
f8f415e
c866288
ea27c63
539edca
aee08eb
5fbaa43
4c29ff2
51e08c3
e5259e2
a994ec1
fdeae9c
f77a5f6
b3a1d45
6d2673f
fe0058f
62f08f4
87ea017
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,19 +18,22 @@ def run(): | |
- cli.py --pr-url=... describe | ||
- cli.py --pr-url=... improve | ||
- cli.py --pr-url=... ask "write me a poem about this PR" | ||
- cli.py --pr-url=... reflect | ||
Supported commands: | ||
review / review_pr - Add a review that includes a summary of the PR and specific suggestions for improvement. | ||
ask / ask_question [question] - Ask a question about the PR. | ||
describe / describe_pr - Modify the PR title and description based on the PR's contents. | ||
improve / improve_code - Suggest improvements to the code in the PR as pull request comments ready to commit. | ||
reflect - Ask the PR author questions about the PR. | ||
""") | ||
parser.add_argument('--pr_url', type=str, help='The URL of the PR to review', required=True) | ||
parser.add_argument('command', type=str, help='The', choices=['review', 'review_pr', | ||
'ask', 'ask_question', | ||
'describe', 'describe_pr', | ||
'improve', 'improve_code', | ||
'user_questions'], default='review') | ||
'reflect', 'review_after_reflect'], | ||
default='review') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using an enum or constants for command names instead of hardcoding them in multiple places. This can reduce the risk of typos and make the code easier to maintain. [medium] |
||
parser.add_argument('rest', nargs=argparse.REMAINDER, default=[]) | ||
args = parser.parse_args() | ||
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) | ||
|
@@ -56,10 +59,14 @@ def run(): | |
print(f"Reviewing PR: {args.pr_url}") | ||
reviewer = PRReviewer(args.pr_url, cli_mode=True) | ||
asyncio.run(reviewer.review()) | ||
elif command in ['user_questions']: | ||
elif command in ['reflect']: | ||
print(f"Asking the PR author questions: {args.pr_url}") | ||
reviewer = PRInformationFromUser(args.pr_url) | ||
asyncio.run(reviewer.generate_questions()) | ||
elif command in ['review_after_reflect']: | ||
print(f"Processing author's answers and sending review: {args.pr_url}") | ||
reviewer = PRReviewer(args.pr_url, cli_mode=True, is_answer=True) | ||
asyncio.run(reviewer.review()) | ||
else: | ||
print(f"Unknown command: {command}") | ||
parser.print_help() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,12 +15,16 @@ | |
|
||
|
||
class PRReviewer: | ||
def __init__(self, pr_url: str, cli_mode=False): | ||
def __init__(self, pr_url: str, cli_mode=False, is_answer: bool = False): | ||
|
||
self.git_provider = get_git_provider()(pr_url) | ||
self.main_language = get_main_pr_language( | ||
self.git_provider.get_languages(), self.git_provider.get_files() | ||
) | ||
self.is_answer = is_answer | ||
if self.is_answer and not self.git_provider.is_supported("get_issue_comments"): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be beneficial to handle the case where the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably do that |
||
raise Exception(f"Answer mode is not supported for {settings.config.git_provider} for now") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using a more specific exception type instead of the generic Exception. This can help with debugging and error handling. For example, you could define a custom exception for this specific error case. [important] |
||
answer_str = question_str = self._get_user_answers() | ||
self.ai_handler = AiHandler() | ||
self.patches_diff = None | ||
self.prediction = None | ||
|
@@ -35,6 +39,9 @@ def __init__(self, pr_url: str, cli_mode=False): | |
"require_security": settings.pr_reviewer.require_security_review, | ||
"require_focused": settings.pr_reviewer.require_focused_review, | ||
'num_code_suggestions': settings.pr_reviewer.num_code_suggestions, | ||
# | ||
'question_str': question_str, | ||
'answer_str': answer_str, | ||
} | ||
self.token_handler = TokenHandler(self.git_provider.pr, | ||
self.vars, | ||
|
@@ -118,9 +125,26 @@ def _publish_inline_code_comments(self): | |
except json.decoder.JSONDecodeError: | ||
data = try_fix_json(review) | ||
|
||
for d in data['PR Feedback']['Code suggestions']: | ||
relevant_file = d['relevant file'].strip() | ||
relevant_line_in_file = d['relevant line in file'].strip() | ||
content = d['suggestion content'] | ||
|
||
self.git_provider.publish_inline_comment(content, relevant_file, relevant_line_in_file) | ||
if settings.pr_reviewer.num_code_suggestions > 0: | ||
try: | ||
for d in data['PR Feedback']['Code suggestions']: | ||
relevant_file = d['relevant file'].strip() | ||
relevant_line_in_file = d['relevant line in file'].strip() | ||
content = d['suggestion content'] | ||
|
||
self.git_provider.publish_inline_comment(content, relevant_file, relevant_line_in_file) | ||
except KeyError: | ||
pass | ||
|
||
def _get_user_answers(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding a docstring to the '_get_user_answers' method to explain its purpose, inputs, and outputs. This can improve code readability and maintainability. [medium] |
||
answer_str = question_str = "" | ||
if self.is_answer: | ||
discussion_messages = self.git_provider.get_issue_comments() | ||
for message in discussion_messages.reversed: | ||
if "Questions to better understand the PR:" in message.body: | ||
question_str = message.body | ||
elif '/answer' in message.body: | ||
answer_str = message.body | ||
if answer_str and question_str: | ||
break | ||
return question_str, answer_str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider refactoring the
handle_request
method to reduce its complexity and improve readability. You could extract the logic for each command into separate methods. [important]