|
|
@ -21,10 +21,13 @@ G4F_MODEL = os.getenv('G4F_MODEL') or g4f.models.gpt_4
|
|
|
|
|
|
|
|
|
|
|
|
def get_pr_details(github: Github) -> PullRequest:
|
|
|
|
def get_pr_details(github: Github) -> PullRequest:
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Rteurns the details of the pull request from GitHub.
|
|
|
|
Retrieves the details of the pull request from GitHub.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
github (Github): The Github object to interact with the GitHub API.
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
PullRequest: A PullRequest instance.
|
|
|
|
PullRequest: An object representing the pull request.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
with open(os.getenv('GITHUB_EVENT_PATH', ''), 'r') as file:
|
|
|
|
with open(os.getenv('GITHUB_EVENT_PATH', ''), 'r') as file:
|
|
|
|
data = json.load(file)
|
|
|
|
data = json.load(file)
|
|
|
@ -36,19 +39,28 @@ def get_pr_details(github: Github) -> PullRequest:
|
|
|
|
|
|
|
|
|
|
|
|
def get_diff(diff_url: str) -> str:
|
|
|
|
def get_diff(diff_url: str) -> str:
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Fetches the diff of the pull request.
|
|
|
|
Fetches the diff of the pull request from a given URL.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
Args:
|
|
|
|
pull (PullRequest): Pull request.
|
|
|
|
diff_url (str): URL to the pull request diff.
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
str or None: The diff of the pull request or None if not available.
|
|
|
|
str: The diff of the pull request.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
response = requests.get(diff_url)
|
|
|
|
response = requests.get(diff_url)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
return response.text
|
|
|
|
return response.text
|
|
|
|
|
|
|
|
|
|
|
|
def read_json(text: str) -> dict:
|
|
|
|
def read_json(text: str) -> dict:
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
Parses JSON code block from a string.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
text (str): A string containing a JSON code block.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
dict: A dictionary parsed from the JSON code block.
|
|
|
|
|
|
|
|
"""
|
|
|
|
match = re.search(r"```(json|)\n(?P<code>[\S\s]+?)\n```", text)
|
|
|
|
match = re.search(r"```(json|)\n(?P<code>[\S\s]+?)\n```", text)
|
|
|
|
if match:
|
|
|
|
if match:
|
|
|
|
text = match.group("code")
|
|
|
|
text = match.group("code")
|
|
|
@ -58,21 +70,31 @@ def read_json(text: str) -> dict:
|
|
|
|
print("No valid json:", text)
|
|
|
|
print("No valid json:", text)
|
|
|
|
return {}
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
def read_text(text: str) -> dict:
|
|
|
|
def read_text(text: str) -> str:
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
Extracts text from a markdown code block.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
text (str): A string containing a markdown code block.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
str: The extracted text.
|
|
|
|
|
|
|
|
"""
|
|
|
|
match = re.search(r"```(markdown|)\n(?P<text>[\S\s]+?)\n```", text)
|
|
|
|
match = re.search(r"```(markdown|)\n(?P<text>[\S\s]+?)\n```", text)
|
|
|
|
if match:
|
|
|
|
if match:
|
|
|
|
return match.group("text")
|
|
|
|
return match.group("text")
|
|
|
|
return text
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
|
|
|
def get_ai_response(prompt, as_json: bool = True) -> Union[dict, str]:
|
|
|
|
def get_ai_response(prompt: str, as_json: bool = True) -> Union[dict, str]:
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Gets a response from g4f API based on the prompt.
|
|
|
|
Gets a response from g4f API based on the prompt.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
Args:
|
|
|
|
prompt (str): The prompt to send to g4f.
|
|
|
|
prompt (str): The prompt to send to g4f.
|
|
|
|
|
|
|
|
as_json (bool): Whether to parse the response as JSON.
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
dict: The parsed response from g4f.
|
|
|
|
Union[dict, str]: The parsed response from g4f, either as a dictionary or a string.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
response = g4f.ChatCompletion.create(
|
|
|
|
response = g4f.ChatCompletion.create(
|
|
|
|
G4F_MODEL,
|
|
|
|
G4F_MODEL,
|
|
|
@ -80,20 +102,18 @@ def get_ai_response(prompt, as_json: bool = True) -> Union[dict, str]:
|
|
|
|
G4F_PROVIDER,
|
|
|
|
G4F_PROVIDER,
|
|
|
|
ignore_stream_and_auth=True
|
|
|
|
ignore_stream_and_auth=True
|
|
|
|
)
|
|
|
|
)
|
|
|
|
if as_json:
|
|
|
|
return read_json(response) if as_json else read_text(response)
|
|
|
|
return read_json(response)
|
|
|
|
|
|
|
|
return read_text(response)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def analyze_code(pull: PullRequest, diff: str)-> list:
|
|
|
|
def analyze_code(pull: PullRequest, diff: str)-> list[dict]:
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Analyzes the code changes in the pull request.
|
|
|
|
Analyzes the code changes in the pull request.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
Args:
|
|
|
|
|
|
|
|
pull (PullRequest): The pull request object.
|
|
|
|
diff (str): The diff of the pull request.
|
|
|
|
diff (str): The diff of the pull request.
|
|
|
|
pr_details (dict): Details of the pull request.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
list: List of comments generated by the analysis.
|
|
|
|
list[dict]: A list of comments generated by the analysis.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
comments = []
|
|
|
|
comments = []
|
|
|
|
changed_lines = []
|
|
|
|
changed_lines = []
|
|
|
@ -122,13 +142,14 @@ def analyze_code(pull: PullRequest, diff: str)-> list:
|
|
|
|
|
|
|
|
|
|
|
|
return comments
|
|
|
|
return comments
|
|
|
|
|
|
|
|
|
|
|
|
def create_prompt(changed_lines: list, pull: PullRequest, file_path: str):
|
|
|
|
def create_prompt(changed_lines: list[str], pull: PullRequest, file_path: str):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Creates a prompt for the g4f model.
|
|
|
|
Creates a prompt for the g4f model.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
Args:
|
|
|
|
diff (str): The line of code to analyze.
|
|
|
|
changed_lines (list[str]): The lines of code that have changed.
|
|
|
|
pr_details (dict): Details of the pull request.
|
|
|
|
pull (PullRequest): The pull request object.
|
|
|
|
|
|
|
|
file_path (str): The path to the file being reviewed.
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
str: The generated prompt.
|
|
|
|
str: The generated prompt.
|
|
|
@ -159,16 +180,17 @@ Each line is prefixed by its number. Code to review:
|
|
|
|
|
|
|
|
|
|
|
|
def create_review_prompt(pull: PullRequest, diff: str):
|
|
|
|
def create_review_prompt(pull: PullRequest, diff: str):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Creates a prompt to create a review.
|
|
|
|
Creates a prompt to create a review comment.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
Args:
|
|
|
|
diff (str): The line of code to analyze.
|
|
|
|
pull (PullRequest): The pull request object.
|
|
|
|
|
|
|
|
diff (str): The diff of the pull request.
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Returns:
|
|
|
|
str: The generated prompt.
|
|
|
|
str: The generated prompt for review.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
return f"""Your task is to review a pull request. Instructions:
|
|
|
|
return f"""Your task is to review a pull request. Instructions:
|
|
|
|
- Your name / you are copilot.
|
|
|
|
- Write in name of you "g4f-copilot".
|
|
|
|
- Write the review in GitHub Markdown format.
|
|
|
|
- Write the review in GitHub Markdown format.
|
|
|
|
- Thank the author for contributing to the project.
|
|
|
|
- Thank the author for contributing to the project.
|
|
|
|
- Point out that you might leave a few comments on the files.
|
|
|
|
- Point out that you might leave a few comments on the files.
|
|
|
@ -192,7 +214,7 @@ def main():
|
|
|
|
pull = get_pr_details(github)
|
|
|
|
pull = get_pr_details(github)
|
|
|
|
diff = get_diff(pull.diff_url)
|
|
|
|
diff = get_diff(pull.diff_url)
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
print(f"Error get details: {e}")
|
|
|
|
print(f"Error get details: {e.__class__.__name__}: {e}")
|
|
|
|
exit(1)
|
|
|
|
exit(1)
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
review = get_ai_response(create_review_prompt(pull, diff), False)
|
|
|
|
review = get_ai_response(create_review_prompt(pull, diff), False)
|
|
|
@ -206,7 +228,10 @@ def main():
|
|
|
|
exit(1)
|
|
|
|
exit(1)
|
|
|
|
print("Comments:", comments)
|
|
|
|
print("Comments:", comments)
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
|
|
|
|
if not comments:
|
|
|
|
pull.create_review(body=review, comments=comments)
|
|
|
|
pull.create_review(body=review, comments=comments)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
pull.create_comment(body=review)
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
print(f"Error posting review: {e}")
|
|
|
|
print(f"Error posting review: {e}")
|
|
|
|
exit(1)
|
|
|
|
exit(1)
|
|
|
|