XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

update etc/tool/copilot.py

f1ad883f
kqlio67 <kqlio67@users.noreply.github.com>
提交于

代码差异

1 个文件 +67 -161
Modified etc/tool/copilot.py +67 -161
@@ -18,17 +18,7 @@ g4f.debug.version_check = False
18 18 GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
19 19 GITHUB_REPOSITORY = os.getenv('GITHUB_REPOSITORY')
20 20 G4F_PROVIDER = os.getenv('G4F_PROVIDER')
21 G4F_MODEL = os.getenv('G4F_MODEL') or g4f.models.gpt_4o or g4f.models.gpt_4o
22
23 def get_github_token():
24 token = os.getenv('GITHUB_TOKEN')
25 if not token:
26 raise ValueError("GITHUB_TOKEN environment variable is not set")
27 print(f"Token length: {len(token)}")
28 print(f"Token (masked): {'*' * (len(token) - 4) + token[-4:]}")
29 if len(token) != 40 or not token.isalnum():
30 raise ValueError("GITHUB_TOKEN appears to be invalid (should be 40 alphanumeric characters)")
31 return token
21 G4F_MODEL = os.getenv('G4F_MODEL') or g4f.models.gpt_4
32 22
33 23 def get_pr_details(github: Github) -> PullRequest:
34 24 """
@@ -40,24 +30,15 @@ def get_pr_details(github: Github) -> PullRequest:
40 30 Returns:
41 31 PullRequest: An object representing the pull request.
42 32 """
43 pr_number = os.getenv('PR_NUMBER')
33 with open('./pr_number', 'r') as file:
34 pr_number = file.read().strip()
44 35 if not pr_number:
45 print("PR_NUMBER environment variable is not set.")
46 return None
36 return
47 37
48 try:
49 print(f"Attempting to get repo: {GITHUB_REPOSITORY}")
50 repo = github.get_repo(GITHUB_REPOSITORY)
51 print(f"Successfully got repo: {repo.full_name}")
52
53 print(f"Attempting to get pull request: {pr_number}")
54 pull = repo.get_pull(int(pr_number))
55 print(f"Successfully got pull request: #{pull.number}")
56
57 return pull
58 except Exception as e:
59 print(f"Error in get_pr_details: {e}")
60 return None
38 repo = github.get_repo(GITHUB_REPOSITORY)
39 pull = repo.get_pull(int(pr_number))
40
41 return pull
61 42
62 43 def get_diff(diff_url: str) -> str:
63 44 """
@@ -118,36 +99,15 @@ def get_ai_response(prompt: str, as_json: bool = True) -> Union[dict, str]:
118 99 Returns:
119 100 Union[dict, str]: The parsed response from g4f, either as a dictionary or a string.
120 101 """
121 max_retries = 5
122 providers = [None, 'Chatgpt4Online', 'OpenaiChat', 'Bing', 'Ai4Chat', 'NexraChatGPT']
123
124 for provider in providers:
125 for _ in range(max_retries):
126 try:
127 response = g4f.chat.completions.create(
128 G4F_MODEL,
129 [{'role': 'user', 'content': prompt}],
130 provider,
131 ignore_stream_and_auth=True
132 )
133 if as_json:
134 parsed_response = read_json(response)
135 if parsed_response and 'reviews' in parsed_response:
136 return parsed_response
137 else:
138 parsed_response = read_text(response)
139 if parsed_response.strip():
140 return parsed_response
141 except Exception as e:
142 print(f"Error with provider {provider}: {e}")
143
144 # If all retries and providers fail, return a default response
145 if as_json:
146 return {"reviews": []}
147 else:
148 return "AI Code Review: Unable to generate a detailed response. Please review the changes manually."
149
150 def analyze_code(pull: PullRequest, diff: str) -> list[dict]:
102 response = g4f.ChatCompletion.create(
103 G4F_MODEL,
104 [{'role': 'user', 'content': prompt}],
105 G4F_PROVIDER,
106 ignore_stream_and_auth=True
107 )
108 return read_json(response) if as_json else read_text(response)
109
110 def analyze_code(pull: PullRequest, diff: str)-> list[dict]:
151 111 """
152 112 Analyzes the code changes in the pull request.
153 113
@@ -163,34 +123,28 @@ def analyze_code(pull: PullRequest, diff: str) -> list[dict]:
163 123 current_file_path = None
164 124 offset_line = 0
165 125
166 try:
167 for line in diff.split('\n'):
168 if line.startswith('+++ b/'):
169 current_file_path = line[6:]
170 changed_lines = []
171 elif line.startswith('@@'):
172 match = re.search(r'\+([0-9]+?),', line)
173 if match:
174 offset_line = int(match.group(1))
175 elif current_file_path:
176 if (line.startswith('\\') or line.startswith('diff')) and changed_lines:
177 prompt = create_analyze_prompt(changed_lines, pull, current_file_path)
178 response = get_ai_response(prompt)
179 for review in response.get('reviews', []):
180 review['path'] = current_file_path
181 comments.append(review)
182 current_file_path = None
183 elif line.startswith('-'):
184 changed_lines.append(line)
185 else:
186 changed_lines.append(f"{offset_line}:{line}")
187 offset_line += 1
188 except Exception as e:
189 print(f"Error in analyze_code: {e}")
190
191 if not comments:
192 print("No comments generated by analyze_code")
193
126 for line in diff.split('\n'):
127 if line.startswith('+++ b/'):
128 current_file_path = line[6:]
129 changed_lines = []
130 elif line.startswith('@@'):
131 match = re.search(r'\+([0-9]+?),', line)
132 if match:
133 offset_line = int(match.group(1))
134 elif current_file_path:
135 if (line.startswith('\\') or line.startswith('diff')) and changed_lines:
136 prompt = create_analyze_prompt(changed_lines, pull, current_file_path)
137 response = get_ai_response(prompt)
138 for review in response.get('reviews', []):
139 review['path'] = current_file_path
140 comments.append(review)
141 current_file_path = None
142 elif line.startswith('-'):
143 changed_lines.append(line)
144 else:
145 changed_lines.append(f"{offset_line}:{line}")
146 offset_line += 1
147
194 148 return comments
195 149
196 150 def create_analyze_prompt(changed_lines: list[str], pull: PullRequest, file_path: str):
@@ -240,105 +194,57 @@ def create_review_prompt(pull: PullRequest, diff: str):
240 194 Returns:
241 195 str: The generated prompt for review.
242 196 """
243 description = pull.body if pull.body else "No description provided."
244 197 return f"""Your task is to review a pull request. Instructions:
245 198 - Write in name of g4f copilot. Don't use placeholder.
246 199 - Write the review in GitHub Markdown format.
247 200 - Thank the author for contributing to the project.
248 - If no issues are found, still provide a brief summary of the changes.
249 201
250 Pull request author: {pull.user.name or "Unknown"}
251 Pull request title: {pull.title or "Untitled Pull Request"}
202 Pull request author: {pull.user.name}
203 Pull request title: {pull.title}
252 204 Pull request description:
253 205 ---
254 {description}
206 {pull.body}
255 207 ---
256 208
257 209 Diff:
258 210 ```diff
259 211 {diff}
260 212 ```
261
262 Please provide a comprehensive review of the changes, highlighting any potential issues or improvements, or summarizing the changes if no issues are found.
263 213 """
264 214
265 215 def main():
266 216 try:
267 github_token = get_github_token()
268 except ValueError as e:
269 print(f"Error: {str(e)}")
270 return
271
272 if not GITHUB_REPOSITORY or not os.getenv('PR_NUMBER'):
273 print("Error: GITHUB_REPOSITORY or PR_NUMBER environment variables are not set.")
274 return
275
276 print(f"GITHUB_REPOSITORY: {GITHUB_REPOSITORY}")
277 print(f"PR_NUMBER: {os.getenv('PR_NUMBER')}")
278 print("GITHUB_TOKEN is set")
279
280 try:
281 github = Github(github_token)
282
283 # Test GitHub connection
284 print("Testing GitHub connection...")
285 try:
286 user = github.get_user()
287 print(f"Successfully authenticated as: {user.login}")
288 except Exception as e:
289 print(f"Error authenticating: {str(e)}")
290 print(f"Error type: {type(e).__name__}")
291 print(f"Error args: {e.args}")
292 return
293
294 # If connection is successful, proceed with PR details
217 github = Github(GITHUB_TOKEN)
295 218 pull = get_pr_details(github)
296 219 if not pull:
297 print(f"No PR number found or invalid PR number")
298 return
299 print(f"Successfully fetched PR #{pull.number}")
220 print(f"No PR number found")
221 exit()
300 222 if pull.get_reviews().totalCount > 0 or pull.get_issue_comments().totalCount > 0:
301 223 print(f"Has already a review")
302 return
303
224 exit()
304 225 diff = get_diff(pull.diff_url)
305 review = "AI Code Review: Unable to generate a detailed response."
306 comments = []
307
308 try:
309 review = get_ai_response(create_review_prompt(pull, diff), False)
310 comments = analyze_code(pull, diff)
311 except Exception as analysis_error:
312 print(f"Error during analysis: {analysis_error}")
313 review += f" Error during analysis: {str(analysis_error)[:200]}"
314
315 print("Comments:", comments)
316
317 review_body = review if review and review.strip() else "AI Code Review"
318 if not review_body.strip():
319 review_body = "AI Code Review: No specific issues found."
320
321 try:
322 if comments:
323 pull.create_review(body=review_body, comments=comments, event='COMMENT')
324 else:
325 pull.create_review(body=review_body, event='COMMENT')
326 print("Review posted successfully")
327 except Exception as post_error:
328 print(f"Error posting review: {post_error}")
329 error_message = f"AI Code Review: An error occurred while posting the review. Error: {str(post_error)[:200]}. Please review the changes manually."
330 pull.create_issue_comment(body=error_message)
331
332 226 except Exception as e:
333 print(f"Unexpected error in main: {e.__class__.__name__}: {e}")
334 try:
335 if 'pull' in locals():
336 error_message = f"AI Code Review: An error occurred while processing this pull request. Error: {str(e)[:200]}. Please review the changes manually."
337 pull.create_issue_comment(body=error_message)
338 else:
339 print("Unable to post error message: Pull request object not available")
340 except Exception as post_error:
341 print(f"Failed to post error message to pull request: {post_error}")
227 print(f"Error get details: {e.__class__.__name__}: {e}")
228 exit(1)
229 try:
230 review = get_ai_response(create_review_prompt(pull, diff), False)
231 except Exception as e:
232 print(f"Error create review: {e}")
233 exit(1)
234 try:
235 comments = analyze_code(pull, diff)
236 except Exception as e:
237 print(f"Error analyze: {e}")
238 exit(1)
239 print("Comments:", comments)
240 try:
241 if comments:
242 pull.create_review(body=review, comments=comments)
243 else:
244 pull.create_issue_comment(body=review)
245 except Exception as e:
246 print(f"Error posting review: {e}")
247 exit(1)
342 248
343 249 if __name__ == "__main__":
344 250 main()