mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
update etc/tool/copilot.py
This commit is contained in:
parent
84bbedf31b
commit
f1ad883f94
1 changed files with 66 additions and 160 deletions
|
|
@ -18,17 +18,7 @@ g4f.debug.version_check = False
|
||||||
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
|
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
|
||||||
GITHUB_REPOSITORY = os.getenv('GITHUB_REPOSITORY')
|
GITHUB_REPOSITORY = os.getenv('GITHUB_REPOSITORY')
|
||||||
G4F_PROVIDER = os.getenv('G4F_PROVIDER')
|
G4F_PROVIDER = os.getenv('G4F_PROVIDER')
|
||||||
G4F_MODEL = os.getenv('G4F_MODEL') or g4f.models.gpt_4o or g4f.models.gpt_4o
|
G4F_MODEL = os.getenv('G4F_MODEL') or g4f.models.gpt_4
|
||||||
|
|
||||||
def get_github_token():
|
|
||||||
token = os.getenv('GITHUB_TOKEN')
|
|
||||||
if not token:
|
|
||||||
raise ValueError("GITHUB_TOKEN environment variable is not set")
|
|
||||||
print(f"Token length: {len(token)}")
|
|
||||||
print(f"Token (masked): {'*' * (len(token) - 4) + token[-4:]}")
|
|
||||||
if len(token) != 40 or not token.isalnum():
|
|
||||||
raise ValueError("GITHUB_TOKEN appears to be invalid (should be 40 alphanumeric characters)")
|
|
||||||
return token
|
|
||||||
|
|
||||||
def get_pr_details(github: Github) -> PullRequest:
|
def get_pr_details(github: Github) -> PullRequest:
|
||||||
"""
|
"""
|
||||||
|
|
@ -40,24 +30,15 @@ def get_pr_details(github: Github) -> PullRequest:
|
||||||
Returns:
|
Returns:
|
||||||
PullRequest: An object representing the pull request.
|
PullRequest: An object representing the pull request.
|
||||||
"""
|
"""
|
||||||
pr_number = os.getenv('PR_NUMBER')
|
with open('./pr_number', 'r') as file:
|
||||||
|
pr_number = file.read().strip()
|
||||||
if not pr_number:
|
if not pr_number:
|
||||||
print("PR_NUMBER environment variable is not set.")
|
return
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
repo = github.get_repo(GITHUB_REPOSITORY)
|
||||||
print(f"Attempting to get repo: {GITHUB_REPOSITORY}")
|
pull = repo.get_pull(int(pr_number))
|
||||||
repo = github.get_repo(GITHUB_REPOSITORY)
|
|
||||||
print(f"Successfully got repo: {repo.full_name}")
|
|
||||||
|
|
||||||
print(f"Attempting to get pull request: {pr_number}")
|
return pull
|
||||||
pull = repo.get_pull(int(pr_number))
|
|
||||||
print(f"Successfully got pull request: #{pull.number}")
|
|
||||||
|
|
||||||
return pull
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error in get_pr_details: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_diff(diff_url: str) -> str:
|
def get_diff(diff_url: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
|
@ -118,36 +99,15 @@ def get_ai_response(prompt: str, as_json: bool = True) -> Union[dict, str]:
|
||||||
Returns:
|
Returns:
|
||||||
Union[dict, str]: The parsed response from g4f, either as a dictionary or a string.
|
Union[dict, str]: The parsed response from g4f, either as a dictionary or a string.
|
||||||
"""
|
"""
|
||||||
max_retries = 5
|
response = g4f.ChatCompletion.create(
|
||||||
providers = [None, 'Chatgpt4Online', 'OpenaiChat', 'Bing', 'Ai4Chat', 'NexraChatGPT']
|
G4F_MODEL,
|
||||||
|
[{'role': 'user', 'content': prompt}],
|
||||||
|
G4F_PROVIDER,
|
||||||
|
ignore_stream_and_auth=True
|
||||||
|
)
|
||||||
|
return read_json(response) if as_json else read_text(response)
|
||||||
|
|
||||||
for provider in providers:
|
def analyze_code(pull: PullRequest, diff: str)-> list[dict]:
|
||||||
for _ in range(max_retries):
|
|
||||||
try:
|
|
||||||
response = g4f.chat.completions.create(
|
|
||||||
G4F_MODEL,
|
|
||||||
[{'role': 'user', 'content': prompt}],
|
|
||||||
provider,
|
|
||||||
ignore_stream_and_auth=True
|
|
||||||
)
|
|
||||||
if as_json:
|
|
||||||
parsed_response = read_json(response)
|
|
||||||
if parsed_response and 'reviews' in parsed_response:
|
|
||||||
return parsed_response
|
|
||||||
else:
|
|
||||||
parsed_response = read_text(response)
|
|
||||||
if parsed_response.strip():
|
|
||||||
return parsed_response
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error with provider {provider}: {e}")
|
|
||||||
|
|
||||||
# If all retries and providers fail, return a default response
|
|
||||||
if as_json:
|
|
||||||
return {"reviews": []}
|
|
||||||
else:
|
|
||||||
return "AI Code Review: Unable to generate a detailed response. Please review the changes manually."
|
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
@ -163,33 +123,27 @@ def analyze_code(pull: PullRequest, diff: str) -> list[dict]:
|
||||||
current_file_path = None
|
current_file_path = None
|
||||||
offset_line = 0
|
offset_line = 0
|
||||||
|
|
||||||
try:
|
for line in diff.split('\n'):
|
||||||
for line in diff.split('\n'):
|
if line.startswith('+++ b/'):
|
||||||
if line.startswith('+++ b/'):
|
current_file_path = line[6:]
|
||||||
current_file_path = line[6:]
|
changed_lines = []
|
||||||
changed_lines = []
|
elif line.startswith('@@'):
|
||||||
elif line.startswith('@@'):
|
match = re.search(r'\+([0-9]+?),', line)
|
||||||
match = re.search(r'\+([0-9]+?),', line)
|
if match:
|
||||||
if match:
|
offset_line = int(match.group(1))
|
||||||
offset_line = int(match.group(1))
|
elif current_file_path:
|
||||||
elif current_file_path:
|
if (line.startswith('\\') or line.startswith('diff')) and changed_lines:
|
||||||
if (line.startswith('\\') or line.startswith('diff')) and changed_lines:
|
prompt = create_analyze_prompt(changed_lines, pull, current_file_path)
|
||||||
prompt = create_analyze_prompt(changed_lines, pull, current_file_path)
|
response = get_ai_response(prompt)
|
||||||
response = get_ai_response(prompt)
|
for review in response.get('reviews', []):
|
||||||
for review in response.get('reviews', []):
|
review['path'] = current_file_path
|
||||||
review['path'] = current_file_path
|
comments.append(review)
|
||||||
comments.append(review)
|
current_file_path = None
|
||||||
current_file_path = None
|
elif line.startswith('-'):
|
||||||
elif line.startswith('-'):
|
changed_lines.append(line)
|
||||||
changed_lines.append(line)
|
else:
|
||||||
else:
|
changed_lines.append(f"{offset_line}:{line}")
|
||||||
changed_lines.append(f"{offset_line}:{line}")
|
offset_line += 1
|
||||||
offset_line += 1
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error in analyze_code: {e}")
|
|
||||||
|
|
||||||
if not comments:
|
|
||||||
print("No comments generated by analyze_code")
|
|
||||||
|
|
||||||
return comments
|
return comments
|
||||||
|
|
||||||
|
|
@ -240,105 +194,57 @@ def create_review_prompt(pull: PullRequest, diff: str):
|
||||||
Returns:
|
Returns:
|
||||||
str: The generated prompt for review.
|
str: The generated prompt for review.
|
||||||
"""
|
"""
|
||||||
description = pull.body if pull.body else "No description provided."
|
|
||||||
return f"""Your task is to review a pull request. Instructions:
|
return f"""Your task is to review a pull request. Instructions:
|
||||||
- Write in name of g4f copilot. Don't use placeholder.
|
- Write in name of g4f copilot. Don't use placeholder.
|
||||||
- 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.
|
||||||
- If no issues are found, still provide a brief summary of the changes.
|
|
||||||
|
|
||||||
Pull request author: {pull.user.name or "Unknown"}
|
Pull request author: {pull.user.name}
|
||||||
Pull request title: {pull.title or "Untitled Pull Request"}
|
Pull request title: {pull.title}
|
||||||
Pull request description:
|
Pull request description:
|
||||||
---
|
---
|
||||||
{description}
|
{pull.body}
|
||||||
---
|
---
|
||||||
|
|
||||||
Diff:
|
Diff:
|
||||||
```diff
|
```diff
|
||||||
{diff}
|
{diff}
|
||||||
```
|
```
|
||||||
|
|
||||||
Please provide a comprehensive review of the changes, highlighting any potential issues or improvements, or summarizing the changes if no issues are found.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
github_token = get_github_token()
|
github = Github(GITHUB_TOKEN)
|
||||||
except ValueError as e:
|
|
||||||
print(f"Error: {str(e)}")
|
|
||||||
return
|
|
||||||
|
|
||||||
if not GITHUB_REPOSITORY or not os.getenv('PR_NUMBER'):
|
|
||||||
print("Error: GITHUB_REPOSITORY or PR_NUMBER environment variables are not set.")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"GITHUB_REPOSITORY: {GITHUB_REPOSITORY}")
|
|
||||||
print(f"PR_NUMBER: {os.getenv('PR_NUMBER')}")
|
|
||||||
print("GITHUB_TOKEN is set")
|
|
||||||
|
|
||||||
try:
|
|
||||||
github = Github(github_token)
|
|
||||||
|
|
||||||
# Test GitHub connection
|
|
||||||
print("Testing GitHub connection...")
|
|
||||||
try:
|
|
||||||
user = github.get_user()
|
|
||||||
print(f"Successfully authenticated as: {user.login}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error authenticating: {str(e)}")
|
|
||||||
print(f"Error type: {type(e).__name__}")
|
|
||||||
print(f"Error args: {e.args}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# If connection is successful, proceed with PR details
|
|
||||||
pull = get_pr_details(github)
|
pull = get_pr_details(github)
|
||||||
if not pull:
|
if not pull:
|
||||||
print(f"No PR number found or invalid PR number")
|
print(f"No PR number found")
|
||||||
return
|
exit()
|
||||||
print(f"Successfully fetched PR #{pull.number}")
|
|
||||||
if pull.get_reviews().totalCount > 0 or pull.get_issue_comments().totalCount > 0:
|
if pull.get_reviews().totalCount > 0 or pull.get_issue_comments().totalCount > 0:
|
||||||
print(f"Has already a review")
|
print(f"Has already a review")
|
||||||
return
|
exit()
|
||||||
|
|
||||||
diff = get_diff(pull.diff_url)
|
diff = get_diff(pull.diff_url)
|
||||||
review = "AI Code Review: Unable to generate a detailed response."
|
|
||||||
comments = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
review = get_ai_response(create_review_prompt(pull, diff), False)
|
|
||||||
comments = analyze_code(pull, diff)
|
|
||||||
except Exception as analysis_error:
|
|
||||||
print(f"Error during analysis: {analysis_error}")
|
|
||||||
review += f" Error during analysis: {str(analysis_error)[:200]}"
|
|
||||||
|
|
||||||
print("Comments:", comments)
|
|
||||||
|
|
||||||
review_body = review if review and review.strip() else "AI Code Review"
|
|
||||||
if not review_body.strip():
|
|
||||||
review_body = "AI Code Review: No specific issues found."
|
|
||||||
|
|
||||||
try:
|
|
||||||
if comments:
|
|
||||||
pull.create_review(body=review_body, comments=comments, event='COMMENT')
|
|
||||||
else:
|
|
||||||
pull.create_review(body=review_body, event='COMMENT')
|
|
||||||
print("Review posted successfully")
|
|
||||||
except Exception as post_error:
|
|
||||||
print(f"Error posting review: {post_error}")
|
|
||||||
error_message = f"AI Code Review: An error occurred while posting the review. Error: {str(post_error)[:200]}. Please review the changes manually."
|
|
||||||
pull.create_issue_comment(body=error_message)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Unexpected error in main: {e.__class__.__name__}: {e}")
|
print(f"Error get details: {e.__class__.__name__}: {e}")
|
||||||
try:
|
exit(1)
|
||||||
if 'pull' in locals():
|
try:
|
||||||
error_message = f"AI Code Review: An error occurred while processing this pull request. Error: {str(e)[:200]}. Please review the changes manually."
|
review = get_ai_response(create_review_prompt(pull, diff), False)
|
||||||
pull.create_issue_comment(body=error_message)
|
except Exception as e:
|
||||||
else:
|
print(f"Error create review: {e}")
|
||||||
print("Unable to post error message: Pull request object not available")
|
exit(1)
|
||||||
except Exception as post_error:
|
try:
|
||||||
print(f"Failed to post error message to pull request: {post_error}")
|
comments = analyze_code(pull, diff)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error analyze: {e}")
|
||||||
|
exit(1)
|
||||||
|
print("Comments:", comments)
|
||||||
|
try:
|
||||||
|
if comments:
|
||||||
|
pull.create_review(body=review, comments=comments)
|
||||||
|
else:
|
||||||
|
pull.create_issue_comment(body=review)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error posting review: {e}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue