mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-09 07:10:37 +08:00
Support context aware settings (for each incoming request), support override of settings, refactor CLI to use pr_agent.py
This commit is contained in:
@ -8,8 +8,8 @@ from jinja2 import Environment, StrictUndefined
|
||||
from pr_agent.algo.ai_handler import AiHandler
|
||||
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
||||
from pr_agent.algo.token_handler import TokenHandler
|
||||
from pr_agent.algo.utils import try_fix_json, update_settings_from_args
|
||||
from pr_agent.config_loader import settings
|
||||
from pr_agent.algo.utils import try_fix_json
|
||||
from pr_agent.config_loader import get_settings
|
||||
from pr_agent.git_providers import BitbucketProvider, get_git_provider
|
||||
from pr_agent.git_providers.git_provider import get_main_pr_language
|
||||
|
||||
@ -21,7 +21,6 @@ class PRCodeSuggestions:
|
||||
self.main_language = get_main_pr_language(
|
||||
self.git_provider.get_languages(), self.git_provider.get_files()
|
||||
)
|
||||
update_settings_from_args(args)
|
||||
|
||||
self.ai_handler = AiHandler()
|
||||
self.patches_diff = None
|
||||
@ -33,24 +32,24 @@ class PRCodeSuggestions:
|
||||
"description": self.git_provider.get_pr_description(),
|
||||
"language": self.main_language,
|
||||
"diff": "", # empty diff for initial calculation
|
||||
"num_code_suggestions": settings.pr_code_suggestions.num_code_suggestions,
|
||||
"extra_instructions": settings.pr_code_suggestions.extra_instructions,
|
||||
"num_code_suggestions": get_settings().pr_code_suggestions.num_code_suggestions,
|
||||
"extra_instructions": get_settings().pr_code_suggestions.extra_instructions,
|
||||
}
|
||||
self.token_handler = TokenHandler(self.git_provider.pr,
|
||||
self.vars,
|
||||
settings.pr_code_suggestions_prompt.system,
|
||||
settings.pr_code_suggestions_prompt.user)
|
||||
get_settings().pr_code_suggestions_prompt.system,
|
||||
get_settings().pr_code_suggestions_prompt.user)
|
||||
|
||||
async def suggest(self):
|
||||
async def run(self):
|
||||
assert type(self.git_provider) != BitbucketProvider, "Bitbucket is not supported for now"
|
||||
|
||||
logging.info('Generating code suggestions for PR...')
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
self.git_provider.publish_comment("Preparing review...", is_temporary=True)
|
||||
await retry_with_fallback_models(self._prepare_prediction)
|
||||
logging.info('Preparing PR review...')
|
||||
data = self._prepare_pr_code_suggestions()
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
logging.info('Pushing PR review...')
|
||||
self.git_provider.remove_initial_comment()
|
||||
logging.info('Pushing inline code comments...')
|
||||
@ -71,9 +70,9 @@ class PRCodeSuggestions:
|
||||
variables = copy.deepcopy(self.vars)
|
||||
variables["diff"] = self.patches_diff # update diff
|
||||
environment = Environment(undefined=StrictUndefined)
|
||||
system_prompt = environment.from_string(settings.pr_code_suggestions_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(settings.pr_code_suggestions_prompt.user).render(variables)
|
||||
if settings.config.verbosity_level >= 2:
|
||||
system_prompt = environment.from_string(get_settings().pr_code_suggestions_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(get_settings().pr_code_suggestions_prompt.user).render(variables)
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"\nSystem prompt:\n{system_prompt}")
|
||||
logging.info(f"\nUser prompt:\n{user_prompt}")
|
||||
response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2,
|
||||
@ -86,7 +85,7 @@ class PRCodeSuggestions:
|
||||
try:
|
||||
data = json.loads(review)
|
||||
except json.decoder.JSONDecodeError:
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"Could not parse json response: {review}")
|
||||
data = try_fix_json(review, code_suggestions=True)
|
||||
return data
|
||||
@ -95,7 +94,7 @@ class PRCodeSuggestions:
|
||||
code_suggestions = []
|
||||
for d in data['Code suggestions']:
|
||||
try:
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"suggestion: {d}")
|
||||
relevant_file = d['relevant file'].strip()
|
||||
relevant_lines_str = d['relevant lines'].strip()
|
||||
@ -113,8 +112,8 @@ class PRCodeSuggestions:
|
||||
code_suggestions.append({'body': body, 'relevant_file': relevant_file,
|
||||
'relevant_lines_start': relevant_lines_start,
|
||||
'relevant_lines_end': relevant_lines_end})
|
||||
except:
|
||||
if settings.config.verbosity_level >= 2:
|
||||
except Exception:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"Could not parse suggestion: {d}")
|
||||
|
||||
self.git_provider.publish_code_suggestions(code_suggestions)
|
||||
@ -136,7 +135,7 @@ class PRCodeSuggestions:
|
||||
if delta_spaces > 0:
|
||||
new_code_snippet = textwrap.indent(new_code_snippet, delta_spaces * " ").rstrip('\n')
|
||||
except Exception as e:
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"Could not dedent code snippet for file {relevant_file}, error: {e}")
|
||||
|
||||
return new_code_snippet
|
||||
|
@ -1,15 +1,14 @@
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
from typing import Tuple, List
|
||||
from typing import List, Tuple
|
||||
|
||||
from jinja2 import Environment, StrictUndefined
|
||||
|
||||
from pr_agent.algo.ai_handler import AiHandler
|
||||
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
||||
from pr_agent.algo.token_handler import TokenHandler
|
||||
from pr_agent.algo.utils import update_settings_from_args
|
||||
from pr_agent.config_loader import settings
|
||||
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
|
||||
|
||||
@ -17,13 +16,12 @@ from pr_agent.git_providers.git_provider import get_main_pr_language
|
||||
class PRDescription:
|
||||
def __init__(self, pr_url: str, args: list = None):
|
||||
"""
|
||||
Initialize the PRDescription object with the necessary attributes and objects for generating a PR description using an AI model.
|
||||
Initialize the PRDescription object with the necessary attributes and objects for generating a PR description
|
||||
using an AI model.
|
||||
Args:
|
||||
pr_url (str): The URL of the pull request.
|
||||
args (list, optional): List of arguments passed to the PRDescription class. Defaults to None.
|
||||
"""
|
||||
update_settings_from_args(args)
|
||||
|
||||
# Initialize the git provider and main PR language
|
||||
self.git_provider = get_git_provider()(pr_url)
|
||||
self.main_pr_language = get_main_pr_language(
|
||||
@ -40,27 +38,27 @@ class PRDescription:
|
||||
"description": self.git_provider.get_pr_description(),
|
||||
"language": self.main_pr_language,
|
||||
"diff": "", # empty diff for initial calculation
|
||||
"extra_instructions": settings.pr_description.extra_instructions,
|
||||
"extra_instructions": get_settings().pr_description.extra_instructions,
|
||||
}
|
||||
|
||||
# Initialize the token handler
|
||||
self.token_handler = TokenHandler(
|
||||
self.git_provider.pr,
|
||||
self.vars,
|
||||
settings.pr_description_prompt.system,
|
||||
settings.pr_description_prompt.user,
|
||||
get_settings().pr_description_prompt.system,
|
||||
get_settings().pr_description_prompt.user,
|
||||
)
|
||||
|
||||
# Initialize patches_diff and prediction attributes
|
||||
self.patches_diff = None
|
||||
self.prediction = None
|
||||
|
||||
async def describe(self):
|
||||
async def run(self):
|
||||
"""
|
||||
Generates a PR description using an AI model and publishes it to the PR.
|
||||
"""
|
||||
logging.info('Generating a PR description...')
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
self.git_provider.publish_comment("Preparing pr description...", is_temporary=True)
|
||||
|
||||
await retry_with_fallback_models(self._prepare_prediction)
|
||||
@ -68,9 +66,9 @@ class PRDescription:
|
||||
logging.info('Preparing answer...')
|
||||
pr_title, pr_body, pr_types, markdown_text = self._prepare_pr_answer()
|
||||
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
logging.info('Pushing answer...')
|
||||
if settings.pr_description.publish_description_as_comment:
|
||||
if get_settings().pr_description.publish_description_as_comment:
|
||||
self.git_provider.publish_comment(markdown_text)
|
||||
else:
|
||||
self.git_provider.publish_description(pr_title, pr_body)
|
||||
@ -116,10 +114,10 @@ class PRDescription:
|
||||
variables["diff"] = self.patches_diff # update diff
|
||||
|
||||
environment = Environment(undefined=StrictUndefined)
|
||||
system_prompt = environment.from_string(settings.pr_description_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(settings.pr_description_prompt.user).render(variables)
|
||||
system_prompt = environment.from_string(get_settings().pr_description_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(get_settings().pr_description_prompt.user).render(variables)
|
||||
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"\nSystem prompt:\n{system_prompt}")
|
||||
logging.info(f"\nUser prompt:\n{user_prompt}")
|
||||
|
||||
@ -170,7 +168,7 @@ class PRDescription:
|
||||
else:
|
||||
pr_body += f"{value}\n\n___\n"
|
||||
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"title:\n{title}\n{pr_body}")
|
||||
|
||||
return title, pr_body, pr_types, markdown_text
|
@ -6,13 +6,11 @@ from jinja2 import Environment, StrictUndefined
|
||||
from pr_agent.algo.ai_handler import AiHandler
|
||||
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
||||
from pr_agent.algo.token_handler import TokenHandler
|
||||
from pr_agent.config_loader import settings
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
class PRInformationFromUser:
|
||||
def __init__(self, pr_url: str, args: list = None):
|
||||
self.git_provider = get_git_provider()(pr_url)
|
||||
@ -29,19 +27,19 @@ class PRInformationFromUser:
|
||||
}
|
||||
self.token_handler = TokenHandler(self.git_provider.pr,
|
||||
self.vars,
|
||||
settings.pr_information_from_user_prompt.system,
|
||||
settings.pr_information_from_user_prompt.user)
|
||||
get_settings().pr_information_from_user_prompt.system,
|
||||
get_settings().pr_information_from_user_prompt.user)
|
||||
self.patches_diff = None
|
||||
self.prediction = None
|
||||
|
||||
async def generate_questions(self):
|
||||
logging.info('Generating question to the user...')
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
self.git_provider.publish_comment("Preparing questions...", is_temporary=True)
|
||||
await retry_with_fallback_models(self._prepare_prediction)
|
||||
logging.info('Preparing questions...')
|
||||
pr_comment = self._prepare_pr_answer()
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
logging.info('Pushing questions...')
|
||||
self.git_provider.publish_comment(pr_comment)
|
||||
self.git_provider.remove_initial_comment()
|
||||
@ -57,9 +55,9 @@ class PRInformationFromUser:
|
||||
variables = copy.deepcopy(self.vars)
|
||||
variables["diff"] = self.patches_diff # update diff
|
||||
environment = Environment(undefined=StrictUndefined)
|
||||
system_prompt = environment.from_string(settings.pr_information_from_user_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(settings.pr_information_from_user_prompt.user).render(variables)
|
||||
if settings.config.verbosity_level >= 2:
|
||||
system_prompt = environment.from_string(get_settings().pr_information_from_user_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(get_settings().pr_information_from_user_prompt.user).render(variables)
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"\nSystem prompt:\n{system_prompt}")
|
||||
logging.info(f"\nUser prompt:\n{user_prompt}")
|
||||
response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2,
|
||||
@ -68,7 +66,7 @@ class PRInformationFromUser:
|
||||
|
||||
def _prepare_pr_answer(self) -> str:
|
||||
model_output = self.prediction.strip()
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"answer_str:\n{model_output}")
|
||||
answer_str = f"{model_output}\n\n Please respond to the questions above in the following format:\n\n" +\
|
||||
"\n>/answer\n>1) ...\n>2) ...\n>...\n"
|
||||
|
@ -6,7 +6,7 @@ from jinja2 import Environment, StrictUndefined
|
||||
from pr_agent.algo.ai_handler import AiHandler
|
||||
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
||||
from pr_agent.algo.token_handler import TokenHandler
|
||||
from pr_agent.config_loader import settings
|
||||
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
|
||||
|
||||
@ -30,8 +30,8 @@ class PRQuestions:
|
||||
}
|
||||
self.token_handler = TokenHandler(self.git_provider.pr,
|
||||
self.vars,
|
||||
settings.pr_questions_prompt.system,
|
||||
settings.pr_questions_prompt.user)
|
||||
get_settings().pr_questions_prompt.system,
|
||||
get_settings().pr_questions_prompt.user)
|
||||
self.patches_diff = None
|
||||
self.prediction = None
|
||||
|
||||
@ -42,14 +42,14 @@ class PRQuestions:
|
||||
question_str = ""
|
||||
return question_str
|
||||
|
||||
async def answer(self):
|
||||
async def run(self):
|
||||
logging.info('Answering a PR question...')
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
self.git_provider.publish_comment("Preparing answer...", is_temporary=True)
|
||||
await retry_with_fallback_models(self._prepare_prediction)
|
||||
logging.info('Preparing answer...')
|
||||
pr_comment = self._prepare_pr_answer()
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
logging.info('Pushing answer...')
|
||||
self.git_provider.publish_comment(pr_comment)
|
||||
self.git_provider.remove_initial_comment()
|
||||
@ -65,9 +65,9 @@ class PRQuestions:
|
||||
variables = copy.deepcopy(self.vars)
|
||||
variables["diff"] = self.patches_diff # update diff
|
||||
environment = Environment(undefined=StrictUndefined)
|
||||
system_prompt = environment.from_string(settings.pr_questions_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(settings.pr_questions_prompt.user).render(variables)
|
||||
if settings.config.verbosity_level >= 2:
|
||||
system_prompt = environment.from_string(get_settings().pr_questions_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(get_settings().pr_questions_prompt.user).render(variables)
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"\nSystem prompt:\n{system_prompt}")
|
||||
logging.info(f"\nUser prompt:\n{user_prompt}")
|
||||
response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2,
|
||||
@ -77,6 +77,6 @@ class PRQuestions:
|
||||
def _prepare_pr_answer(self) -> str:
|
||||
answer_str = f"Question: {self.question_str}\n\n"
|
||||
answer_str += f"Answer:\n{self.prediction.strip()}\n\n"
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"answer_str:\n{answer_str}")
|
||||
return answer_str
|
||||
|
@ -2,17 +2,17 @@ import copy
|
||||
import json
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
from typing import Tuple, List
|
||||
from typing import List, Tuple
|
||||
|
||||
from jinja2 import Environment, StrictUndefined
|
||||
|
||||
from pr_agent.algo.ai_handler import AiHandler
|
||||
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
||||
from pr_agent.algo.token_handler import TokenHandler
|
||||
from pr_agent.algo.utils import convert_to_markdown, try_fix_json, update_settings_from_args
|
||||
from pr_agent.config_loader import settings
|
||||
from pr_agent.algo.utils import convert_to_markdown, try_fix_json
|
||||
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, IncrementalPR
|
||||
from pr_agent.git_providers.git_provider import IncrementalPR, get_main_pr_language
|
||||
from pr_agent.servers.help import actions_help_text, bot_help_text
|
||||
|
||||
|
||||
@ -20,17 +20,15 @@ class PRReviewer:
|
||||
"""
|
||||
The PRReviewer class is responsible for reviewing a pull request and generating feedback using an AI model.
|
||||
"""
|
||||
def __init__(self, pr_url: str, cli_mode: bool = False, is_answer: bool = False, args: list = None):
|
||||
def __init__(self, pr_url: str, is_answer: bool = False, args: list = None):
|
||||
"""
|
||||
Initialize the PRReviewer object with the necessary attributes and objects to review a pull request.
|
||||
|
||||
Args:
|
||||
pr_url (str): The URL of the pull request to be reviewed.
|
||||
cli_mode (bool, optional): Indicates whether the review is being done in command-line interface mode. Defaults to False.
|
||||
is_answer (bool, optional): Indicates whether the review is being done in answer mode. Defaults to False.
|
||||
args (list, optional): List of arguments passed to the PRReviewer class. Defaults to None.
|
||||
"""
|
||||
update_settings_from_args(args)
|
||||
self.parse_args(args) # -i command
|
||||
|
||||
self.git_provider = get_git_provider()(pr_url, incremental=self.incremental)
|
||||
@ -41,11 +39,10 @@ class PRReviewer:
|
||||
self.is_answer = is_answer
|
||||
|
||||
if self.is_answer and not self.git_provider.is_supported("get_issue_comments"):
|
||||
raise Exception(f"Answer mode is not supported for {settings.config.git_provider} for now")
|
||||
raise Exception(f"Answer mode is not supported for {get_settings().config.git_provider} for now")
|
||||
self.ai_handler = AiHandler()
|
||||
self.patches_diff = None
|
||||
self.prediction = None
|
||||
self.cli_mode = cli_mode
|
||||
|
||||
answer_str, question_str = self._get_user_answers()
|
||||
self.vars = {
|
||||
@ -54,21 +51,21 @@ class PRReviewer:
|
||||
"description": self.git_provider.get_pr_description(),
|
||||
"language": self.main_language,
|
||||
"diff": "", # empty diff for initial calculation
|
||||
"require_score": settings.pr_reviewer.require_score_review,
|
||||
"require_tests": settings.pr_reviewer.require_tests_review,
|
||||
"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,
|
||||
"require_score": get_settings().pr_reviewer.require_score_review,
|
||||
"require_tests": get_settings().pr_reviewer.require_tests_review,
|
||||
"require_security": get_settings().pr_reviewer.require_security_review,
|
||||
"require_focused": get_settings().pr_reviewer.require_focused_review,
|
||||
'num_code_suggestions': get_settings().pr_reviewer.num_code_suggestions,
|
||||
'question_str': question_str,
|
||||
'answer_str': answer_str,
|
||||
"extra_instructions": settings.pr_reviewer.extra_instructions,
|
||||
"extra_instructions": get_settings().pr_reviewer.extra_instructions,
|
||||
}
|
||||
|
||||
self.token_handler = TokenHandler(
|
||||
self.git_provider.pr,
|
||||
self.vars,
|
||||
settings.pr_review_prompt.system,
|
||||
settings.pr_review_prompt.user
|
||||
get_settings().pr_review_prompt.system,
|
||||
get_settings().pr_review_prompt.user
|
||||
)
|
||||
|
||||
def parse_args(self, args: List[str]) -> None:
|
||||
@ -88,13 +85,13 @@ class PRReviewer:
|
||||
is_incremental = True
|
||||
self.incremental = IncrementalPR(is_incremental)
|
||||
|
||||
async def review(self) -> None:
|
||||
async def run(self) -> None:
|
||||
"""
|
||||
Review the pull request and generate feedback.
|
||||
"""
|
||||
logging.info('Reviewing PR...')
|
||||
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
self.git_provider.publish_comment("Preparing review...", is_temporary=True)
|
||||
|
||||
await retry_with_fallback_models(self._prepare_prediction)
|
||||
@ -102,12 +99,12 @@ class PRReviewer:
|
||||
logging.info('Preparing PR review...')
|
||||
pr_comment = self._prepare_pr_review()
|
||||
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
logging.info('Pushing PR review...')
|
||||
self.git_provider.publish_comment(pr_comment)
|
||||
self.git_provider.remove_initial_comment()
|
||||
|
||||
if settings.pr_reviewer.inline_code_comments:
|
||||
if get_settings().pr_reviewer.inline_code_comments:
|
||||
logging.info('Pushing inline code comments...')
|
||||
self._publish_inline_code_comments()
|
||||
|
||||
@ -140,10 +137,10 @@ class PRReviewer:
|
||||
variables["diff"] = self.patches_diff # update diff
|
||||
|
||||
environment = Environment(undefined=StrictUndefined)
|
||||
system_prompt = environment.from_string(settings.pr_review_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(settings.pr_review_prompt.user).render(variables)
|
||||
system_prompt = environment.from_string(get_settings().pr_review_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(get_settings().pr_review_prompt.user).render(variables)
|
||||
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"\nSystem prompt:\n{system_prompt}")
|
||||
logging.info(f"\nUser prompt:\n{user_prompt}")
|
||||
|
||||
@ -158,7 +155,8 @@ class PRReviewer:
|
||||
|
||||
def _prepare_pr_review(self) -> str:
|
||||
"""
|
||||
Prepare the PR review by processing the AI prediction and generating a markdown-formatted text that summarizes the feedback.
|
||||
Prepare the PR review by processing the AI prediction and generating a markdown-formatted text that summarizes
|
||||
the feedback.
|
||||
"""
|
||||
review = self.prediction.strip()
|
||||
|
||||
@ -174,7 +172,8 @@ class PRReviewer:
|
||||
data['PR Analysis']['Security concerns'] = val
|
||||
|
||||
# Filter out code suggestions that can be submitted as inline comments
|
||||
if settings.config.git_provider != 'bitbucket' and settings.pr_reviewer.inline_code_comments and 'Code suggestions' in data['PR Feedback']:
|
||||
if get_settings().config.git_provider != 'bitbucket' and get_settings().pr_reviewer.inline_code_comments \
|
||||
and 'Code suggestions' in data['PR Feedback']:
|
||||
data['PR Feedback']['Code suggestions'] = [
|
||||
d for d in data['PR Feedback']['Code suggestions']
|
||||
if any(key not in d for key in ('relevant file', 'relevant line in file', 'suggestion content'))
|
||||
@ -184,7 +183,8 @@ class PRReviewer:
|
||||
|
||||
# Add incremental review section
|
||||
if self.incremental.is_incremental:
|
||||
last_commit_url = f"{self.git_provider.get_pr_url()}/commits/{self.git_provider.incremental.first_new_commit_sha}"
|
||||
last_commit_url = f"{self.git_provider.get_pr_url()}/commits/" \
|
||||
f"{self.git_provider.incremental.first_new_commit_sha}"
|
||||
data = OrderedDict(data)
|
||||
data.update({'Incremental PR Review': {
|
||||
"⏮️ Review for commits since previous PR-Agent review": f"Starting from commit {last_commit_url}"}})
|
||||
@ -194,7 +194,7 @@ class PRReviewer:
|
||||
user = self.git_provider.get_user_id()
|
||||
|
||||
# Add help text if not in CLI mode
|
||||
if not self.cli_mode:
|
||||
if get_settings().get("CONFIG.CLI_MODE", False):
|
||||
markdown_text += "\n### How to use\n"
|
||||
if user and '[bot]' not in user:
|
||||
markdown_text += bot_help_text(user)
|
||||
@ -202,7 +202,7 @@ class PRReviewer:
|
||||
markdown_text += actions_help_text
|
||||
|
||||
# Log markdown response if verbosity level is high
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"Markdown response:\n{markdown_text}")
|
||||
|
||||
return markdown_text
|
||||
@ -211,7 +211,7 @@ class PRReviewer:
|
||||
"""
|
||||
Publishes inline comments on a pull request with code suggestions generated by the AI model.
|
||||
"""
|
||||
if settings.pr_reviewer.num_code_suggestions == 0:
|
||||
if get_settings().pr_reviewer.num_code_suggestions == 0:
|
||||
return
|
||||
|
||||
review = self.prediction.strip()
|
||||
|
@ -9,9 +9,8 @@ from jinja2 import Environment, StrictUndefined
|
||||
from pr_agent.algo.ai_handler import AiHandler
|
||||
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
||||
from pr_agent.algo.token_handler import TokenHandler
|
||||
from pr_agent.config_loader import settings
|
||||
from pr_agent.algo.utils import update_settings_from_args
|
||||
from pr_agent.git_providers import get_git_provider, GithubProvider
|
||||
from pr_agent.config_loader import get_settings
|
||||
from pr_agent.git_providers import GithubProvider, get_git_provider
|
||||
from pr_agent.git_providers.git_provider import get_main_pr_language
|
||||
|
||||
CHANGELOG_LINES = 50
|
||||
@ -24,8 +23,7 @@ class PRUpdateChangelog:
|
||||
self.main_language = get_main_pr_language(
|
||||
self.git_provider.get_languages(), self.git_provider.get_files()
|
||||
)
|
||||
update_settings_from_args(args)
|
||||
self.commit_changelog = settings.pr_update_changelog.push_changelog_changes
|
||||
self.commit_changelog = get_settings().pr_update_changelog.push_changelog_changes
|
||||
self._get_changlog_file() # self.changelog_file_str
|
||||
self.ai_handler = AiHandler()
|
||||
self.patches_diff = None
|
||||
@ -39,23 +37,23 @@ class PRUpdateChangelog:
|
||||
"diff": "", # empty diff for initial calculation
|
||||
"changelog_file_str": self.changelog_file_str,
|
||||
"today": date.today(),
|
||||
"extra_instructions": settings.pr_update_changelog.extra_instructions,
|
||||
"extra_instructions": get_settings().pr_update_changelog.extra_instructions,
|
||||
}
|
||||
self.token_handler = TokenHandler(self.git_provider.pr,
|
||||
self.vars,
|
||||
settings.pr_update_changelog_prompt.system,
|
||||
settings.pr_update_changelog_prompt.user)
|
||||
get_settings().pr_update_changelog_prompt.system,
|
||||
get_settings().pr_update_changelog_prompt.user)
|
||||
|
||||
async def update_changelog(self):
|
||||
async def run(self):
|
||||
assert type(self.git_provider) == GithubProvider, "Currently only Github is supported"
|
||||
|
||||
logging.info('Updating the changelog...')
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
self.git_provider.publish_comment("Preparing changelog updates...", is_temporary=True)
|
||||
await retry_with_fallback_models(self._prepare_prediction)
|
||||
logging.info('Preparing PR changelog updates...')
|
||||
new_file_content, answer = self._prepare_changelog_update()
|
||||
if settings.config.publish_output:
|
||||
if get_settings().config.publish_output:
|
||||
self.git_provider.remove_initial_comment()
|
||||
logging.info('Publishing changelog updates...')
|
||||
if self.commit_changelog:
|
||||
@ -75,9 +73,9 @@ class PRUpdateChangelog:
|
||||
variables = copy.deepcopy(self.vars)
|
||||
variables["diff"] = self.patches_diff # update diff
|
||||
environment = Environment(undefined=StrictUndefined)
|
||||
system_prompt = environment.from_string(settings.pr_update_changelog_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(settings.pr_update_changelog_prompt.user).render(variables)
|
||||
if settings.config.verbosity_level >= 2:
|
||||
system_prompt = environment.from_string(get_settings().pr_update_changelog_prompt.system).render(variables)
|
||||
user_prompt = environment.from_string(get_settings().pr_update_changelog_prompt.user).render(variables)
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"\nSystem prompt:\n{system_prompt}")
|
||||
logging.info(f"\nUser prompt:\n{user_prompt}")
|
||||
response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2,
|
||||
@ -86,7 +84,7 @@ class PRUpdateChangelog:
|
||||
return response
|
||||
|
||||
def _prepare_changelog_update(self) -> Tuple[str, str]:
|
||||
answer = self.prediction.strip().strip("```").strip()
|
||||
answer = self.prediction.strip().strip("```").strip() # noqa B005
|
||||
if hasattr(self, "changelog_file"):
|
||||
existing_content = self.changelog_file.decoded_content.decode()
|
||||
else:
|
||||
@ -100,7 +98,7 @@ class PRUpdateChangelog:
|
||||
answer += "\n\n\n>to commit the new content to the CHANGELOG.md file, please type:" \
|
||||
"\n>'/update_changelog --pr_update_changelog.push_changelog_changes=true'\n"
|
||||
|
||||
if settings.config.verbosity_level >= 2:
|
||||
if get_settings().config.verbosity_level >= 2:
|
||||
logging.info(f"answer:\n{answer}")
|
||||
|
||||
return new_file_content, answer
|
||||
@ -120,7 +118,7 @@ class PRUpdateChangelog:
|
||||
last_commit_id = list(self.git_provider.pr.get_commits())[-1]
|
||||
try:
|
||||
self.git_provider.pr.create_review(commit=last_commit_id, comments=[d])
|
||||
except:
|
||||
except Exception:
|
||||
# we can't create a review for some reason, let's just publish a comment
|
||||
self.git_provider.publish_comment(f"**Changelog updates:**\n\n{answer}")
|
||||
|
||||
@ -147,7 +145,7 @@ Example:
|
||||
changelog_file_lines = self.changelog_file.decoded_content.decode().splitlines()
|
||||
changelog_file_lines = changelog_file_lines[:CHANGELOG_LINES]
|
||||
self.changelog_file_str = "\n".join(changelog_file_lines)
|
||||
except:
|
||||
except Exception:
|
||||
self.changelog_file_str = ""
|
||||
if self.commit_changelog:
|
||||
logging.info("No CHANGELOG.md file found in the repository. Creating one...")
|
||||
|
Reference in New Issue
Block a user