acecalisto3 commited on
Commit
32945d9
·
verified ·
1 Parent(s): 6c96611

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +352 -75
app.py CHANGED
@@ -11,10 +11,7 @@ import atexit
11
  import subprocess
12
  from urllib.parse import urlparse, quote
13
  import webbrowser
14
- from dotenv import load_dotenv
15
-
16
- # Load environment variables from .env file
17
- load_dotenv()
18
 
19
  # Constants
20
  INPUT_DIRECTORY = 'input'
@@ -23,10 +20,8 @@ LOGS_DIRECTORY = 'logs'
23
  RESOLUTIONS_DIRECTORY = 'resolutions'
24
  REPOS_DIRECTORY = 'repos'
25
 
26
- # Logger setup
27
  def initialize_logger() -> logging.Logger:
28
- """Sets up and returns a logger instance."""
29
- os.makedirs(LOGS_DIRECTORY, exist_ok=True)
30
  log_file = f"{LOGS_DIRECTORY}/github_bot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
31
  logging.basicConfig(
32
  level=logging.INFO,
@@ -36,19 +31,15 @@ def initialize_logger() -> logging.Logger:
36
  logging.StreamHandler()
37
  ]
38
  )
39
- return logging.getLogger("GitHubBot")
40
-
41
- # Global logger instance
42
- logger = initialize_logger()
43
 
44
- # Ensure required directories exist
45
  def initialize_environment():
46
- """Creates necessary directories for the script."""
47
  directories = [LOGS_DIRECTORY, RESOLUTIONS_DIRECTORY, REPOS_DIRECTORY, INPUT_DIRECTORY, OUTPUT_DIRECTORY]
48
  for directory in directories:
49
  os.makedirs(directory, exist_ok=True)
50
 
51
- # GitHub API interaction
52
  class GitHubAPI:
53
  def __init__(self, token: str):
54
  self.token = token
@@ -59,7 +50,6 @@ class GitHubAPI:
59
  self.base_url = "https://api.github.com"
60
 
61
  def _check_rate_limit(self) -> bool:
62
- """Checks the GitHub API rate limit and waits if necessary."""
63
  try:
64
  response = requests.get(f"{self.base_url}/rate_limit", headers=self.headers)
65
  response.raise_for_status()
@@ -70,130 +60,417 @@ class GitHubAPI:
70
  if remaining < 10:
71
  wait_time = max(0, reset_time - int(time.time()))
72
  if wait_time > 0:
73
- logger.warning(f"Rate limit nearly exceeded. Waiting {wait_time} seconds...")
74
  time.sleep(wait_time)
75
  return False
76
  return True
77
- except requests.RequestException as e:
78
- logger.error(f"Error checking rate limit: {str(e)}")
79
  return True
80
 
81
  def get_repository(self, owner: str, repo: str) -> Dict:
82
- """Fetches repository details."""
83
  try:
84
  response = requests.get(f"{self.base_url}/repos/{owner}/{repo}", headers=self.headers)
85
  response.raise_for_status()
86
  return response.json()
87
  except requests.HTTPError as e:
88
- logger.error(f"HTTP error fetching repo {owner}/{repo}: {str(e)}")
89
  raise
90
  except Exception as e:
91
- logger.error(f"Error fetching repo: {str(e)}")
92
  raise
93
 
94
  def get_issues(self, owner: str, repo: str, state: str = 'open') -> List[Dict]:
95
- """Fetches issues for a repository."""
96
  if not self._check_rate_limit():
97
  return []
98
 
99
  try:
100
- response = requests.get(
101
- f"{self.base_url}/repos/{owner}/{repo}/issues",
102
- headers=self.headers,
103
- params={'state': state}
104
- )
105
  response.raise_for_status()
106
- return [issue for issue in response.json() if 'pull_request' not in issue]
107
- except requests.RequestException as e:
108
- logger.error(f"Error fetching issues for {owner}/{repo}: {str(e)}")
 
109
  return []
110
 
111
- # GitHub Bot main functionality
112
  class GitHubBot:
113
  def __init__(self):
114
  self.github_api = None
115
 
116
  def initialize_api(self, token: str):
117
- """Initializes the GitHub API client."""
118
  self.github_api = GitHubAPI(token)
119
 
120
  def fetch_issues(self, token: str, owner: str, repo: str) -> List[Dict]:
121
- """Fetches issues from a repository."""
122
- self.initialize_api(token)
123
- return self.github_api.get_issues(owner, repo)
 
 
 
124
 
125
- def resolve_issue(self, token: str, owner: str, repo: str, issue_number: int, resolution: str, forked_repo: str) -> str:
126
- """Resolves a GitHub issue and pushes changes to a forked repository."""
127
  try:
128
  self.initialize_api(token)
129
  self.github_api.get_repository(owner, repo)
130
 
 
131
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
132
  resolution_file = f"{RESOLUTIONS_DIRECTORY}/resolution_{issue_number}_{timestamp}.md"
133
 
134
  with open(resolution_file, "w") as f:
135
  f.write(f"# Resolution for Issue #{issue_number}\n\n{resolution}")
136
 
137
- temp_repo_dir = f"/tmp/{forked_repo.split('/')[-1]}"
138
- subprocess.run(['git', 'clone', forked_repo, temp_repo_dir], check=True)
139
- os.chdir(temp_repo_dir)
 
 
140
 
141
- input("Apply the fix manually, then press ENTER to continue...")
 
142
 
 
143
  subprocess.run(['git', 'add', '.'], check=True)
144
- subprocess.run(['git', 'commit', '-m', f"Resolved issue #{issue_number}: {resolution}"], check=True)
145
  subprocess.run(['git', 'push', 'origin', 'HEAD'], check=True)
146
 
147
- pull_request_url = f"https://github.com/{forked_repo.split('/')[-1]}/compare/master...{owner}:{repo}_resolved_issue_{issue_number}"
148
- webbrowser.open(pull_request_url)
149
 
150
- return f"Resolution completed and saved: {resolution_file}"
151
 
152
  except Exception as e:
153
- logger.error(f"Error resolving issue #{issue_number} for {owner}/{repo}: {str(e)}")
154
- return f"Error resolving issue: {str(e)}"
 
 
 
 
 
 
155
 
156
- # Utility Functions
157
  def extract_info_from_url(url: str) -> Dict[str, Any]:
158
- """Extracts information from a URL."""
159
  info = {}
160
  try:
161
  response = requests.get(url)
162
  response.raise_for_status()
163
  info['status_code'] = response.status_code
164
  info['headers'] = dict(response.headers)
165
- info['content'] = response.text[:500]
166
- parsed_url = urlparse(url)
167
 
 
168
  if 'github.com' in parsed_url.netloc:
169
- parts = parsed_url.path.strip('/').split('/')
170
- if len(parts) >= 2:
171
- owner, repo = parts[:2]
172
- bot = GitHubBot()
173
  issues = bot.fetch_issues(github_token, owner, repo)
174
  info['issues'] = issues
175
- except requests.RequestException as e:
176
- info['error'] = f"Error extracting info: {str(e)}"
 
 
 
 
 
 
177
  return info
178
 
179
- # Initialize environment
180
- initialize_environment()
181
 
182
- # Example usage (placeholder for main logic)
183
- if __name__ == "__main__":
184
- print("GitHub Bot initialized. Add main logic as needed.")
 
 
 
185
 
186
- # Sample interaction for testing purposes
187
- token = input("Enter your GitHub Personal Access Token: ").strip()
188
- owner = input("Enter the repository owner: ").strip()
189
- repo = input("Enter the repository name: ").strip()
 
190
 
191
- bot = GitHubBot()
192
- issues = bot.fetch_issues(token, owner, repo)
193
-
194
- if issues:
195
- print(f"Found {len(issues)} issue(s):")
196
- for issue in issues:
197
- print(f"- #{issue['number']}: {issue['title']}")
198
- else:
199
- print("No issues found or unable to fetch issues.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  import subprocess
12
  from urllib.parse import urlparse, quote
13
  import webbrowser
14
+ import spaces
 
 
 
15
 
16
  # Constants
17
  INPUT_DIRECTORY = 'input'
 
20
  RESOLUTIONS_DIRECTORY = 'resolutions'
21
  REPOS_DIRECTORY = 'repos'
22
 
23
+ # Set up logging
24
  def initialize_logger() -> logging.Logger:
 
 
25
  log_file = f"{LOGS_DIRECTORY}/github_bot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
26
  logging.basicConfig(
27
  level=logging.INFO,
 
31
  logging.StreamHandler()
32
  ]
33
  )
34
+ return logging.getLogger(__name__)
 
 
 
35
 
36
+ # Initialize environment and logger
37
  def initialize_environment():
 
38
  directories = [LOGS_DIRECTORY, RESOLUTIONS_DIRECTORY, REPOS_DIRECTORY, INPUT_DIRECTORY, OUTPUT_DIRECTORY]
39
  for directory in directories:
40
  os.makedirs(directory, exist_ok=True)
41
 
42
+ # GitHub API handler
43
  class GitHubAPI:
44
  def __init__(self, token: str):
45
  self.token = token
 
50
  self.base_url = "https://api.github.com"
51
 
52
  def _check_rate_limit(self) -> bool:
 
53
  try:
54
  response = requests.get(f"{self.base_url}/rate_limit", headers=self.headers)
55
  response.raise_for_status()
 
60
  if remaining < 10:
61
  wait_time = max(0, reset_time - int(time.time()))
62
  if wait_time > 0:
63
+ logger.warning(f"Rate limit nearly exceeded. Waiting {wait_time} seconds before retrying...")
64
  time.sleep(wait_time)
65
  return False
66
  return True
67
+ except requests.exceptions.RequestException as e:
68
+ logger.error(f"Error checking rate limit: {str(e)}. Retrying...")
69
  return True
70
 
71
  def get_repository(self, owner: str, repo: str) -> Dict:
 
72
  try:
73
  response = requests.get(f"{self.base_url}/repos/{owner}/{repo}", headers=self.headers)
74
  response.raise_for_status()
75
  return response.json()
76
  except requests.HTTPError as e:
77
+ logger.error(f"HTTP error getting repository info for {owner}/{repo}: {str(e)}. Please check the repository details.")
78
  raise
79
  except Exception as e:
80
+ logger.error(f"Error getting repository info: {str(e)}")
81
  raise
82
 
83
  def get_issues(self, owner: str, repo: str, state: str = 'open') -> List[Dict]:
 
84
  if not self._check_rate_limit():
85
  return []
86
 
87
  try:
88
+ response = requests.get(f"{self.base_url}/repos/{owner}/{repo}/issues", headers=self.headers, params={'state': state})
 
 
 
 
89
  response.raise_for_status()
90
+ issues = response.json()
91
+ return [issue for issue in issues if 'pull_request' not in issue]
92
+ except Exception as e:
93
+ logger.error(f"Error fetching issues for repository {owner}/{repo}: {str(e)}. Please verify the repository and token.")
94
  return []
95
 
96
+ # GitHub Bot
97
  class GitHubBot:
98
  def __init__(self):
99
  self.github_api = None
100
 
101
  def initialize_api(self, token: str):
 
102
  self.github_api = GitHubAPI(token)
103
 
104
  def fetch_issues(self, token: str, owner: str, repo: str) -> List[Dict]:
105
+ try:
106
+ self.initialize_api(token)
107
+ return self.github_api.get_issues(owner, repo)
108
+ except Exception as e:
109
+ logger.error(f"Error fetching issues for repository {owner}/{repo}: {str(e)}")
110
+ return []
111
 
112
+ def resolve_issue (self, token: str, owner: str, repo: str, issue_number: int, resolution: str, forked_repo: str) -> str:
 
113
  try:
114
  self.initialize_api(token)
115
  self.github_api.get_repository(owner, repo)
116
 
117
+ # Create resolution file
118
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
119
  resolution_file = f"{RESOLUTIONS_DIRECTORY}/resolution_{issue_number}_{timestamp}.md"
120
 
121
  with open(resolution_file, "w") as f:
122
  f.write(f"# Resolution for Issue #{issue_number}\n\n{resolution}")
123
 
124
+ # Clone the forked repo
125
+ subprocess.run(['git', 'clone', forked_repo, '/tmp/' + forked_repo.split('/')[-1]], check=True)
126
+
127
+ # Change to the cloned directory
128
+ os.chdir('/tmp/' + forked_repo.split('/')[-1])
129
 
130
+ # Assuming manual intervention now
131
+ input("Apply the fix manually and stage the changes (press ENTER)? ")
132
 
133
+ # Commit and push the modifications
134
  subprocess.run(['git', 'add', '.'], check=True)
135
+ subprocess.run(['git', 'commit', '-m', f"Resolved issue #{issue_number} ({quote(resolution)})"], check=True)
136
  subprocess.run(['git', 'push', 'origin', 'HEAD'], check=True)
137
 
138
+ # Open Pull Request page
139
+ webbrowser.open(f'https://github.com/{forked_repo.split("/")[-1]}/compare/master...{owner}:{forked_repo.split("/")[-1]}_resolved_issue_{issue_number}')
140
 
141
+ return f"Resolution saved: {resolution_file}"
142
 
143
  except Exception as e:
144
+ error_msg = f"Error resolving issue #{issue_number} in repository {owner}/{repo}: {str(e)}"
145
+ logger.error(error_msg)
146
+ return error_msg
147
+
148
+ def handle_issue_selection(token, owner, repo, issue_number, resolution, forked_repo):
149
+ bot = GitHubBot()
150
+ result = bot.resolve_issue(token, owner, repo, issue_number, resolution, forked_repo)
151
+ return result
152
 
 
153
  def extract_info_from_url(url: str) -> Dict[str, Any]:
 
154
  info = {}
155
  try:
156
  response = requests.get(url)
157
  response.raise_for_status()
158
  info['status_code'] = response.status_code
159
  info['headers'] = dict(response.headers)
160
+ info['content'] = response.text[:500] # Limit content to first 500 characters for brevity
 
161
 
162
+ parsed_url = urlparse(url)
163
  if 'github.com' in parsed_url.netloc:
164
+ parts = parsed_url.path.split('/')
165
+ if len(parts) > 2:
166
+ owner = parts[1]
167
+ repo = parts[2]
168
  issues = bot.fetch_issues(github_token, owner, repo)
169
  info['issues'] = issues
170
+ elif 'huggingface.co' in parsed_url.netloc:
171
+ # Add Hugging Face specific handling if needed
172
+ pass
173
+
174
+ except requests.HTTPError as e:
175
+ info['error'] = f"HTTP error: {str(e)}"
176
+ except Exception as e:
177
+ info['error'] = f"Error: {str(e)}"
178
  return info
179
 
180
+ # Initialize GitHubBot globally
181
+ bot = GitHubBot()
182
 
183
+ # Define missing functions with validation
184
+ def fetch_issues(token, repo_url):
185
+ try:
186
+ parts = repo_url.split('/')
187
+ if len(parts) < 2:
188
+ raise ValueError("Repository URL is not in the correct format. Expected format: 'owner/repo'.")
189
 
190
+ owner, repo = parts[-2], parts[-1]
191
+ issues = bot.fetch_issues(token, owner, repo)
192
+ return issues
193
+ except Exception as e:
194
+ return str(e)
195
 
196
+ def resolve_issue(token, repo_url, issue_number, resolution, forked_repo_url):
197
+ try:
198
+ parts = repo_url.split('/')
199
+ if len(parts) < 2:
200
+ raise ValueError("Repository URL is not in the correct format. Expected format: 'owner/repo'.")
201
+
202
+ owner, repo = parts[-2], parts[-1]
203
+ result = bot.resolve_issue(token, owner, repo, issue_number, resolution, forked_repo_url)
204
+ return result
205
+ except Exception as e:
206
+ return str(e)
207
+
208
+ def extract_info(url):
209
+ try:
210
+ info = extract_info_from_url(url)
211
+ return info
212
+ except Exception as e:
213
+ return str(e)
214
+
215
+ # HTML and CSS integration
216
+ custom_html = """
217
+ <!DOCTYPE html>
218
+ <html>
219
+ <head>
220
+ <title>GitHub Issue Manager</title>
221
+ <meta charset="UTF-8">
222
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
223
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css " rel="stylesheet">
224
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.css" rel="stylesheet" type="text/css" />
225
+ <style>
226
+ body {
227
+ background: linear-gradient(to bottom right, #121212, #303030) !important;
228
+ color: #e0e0e0;
229
+ font-family: 'Roboto', sans-serif;
230
+ overflow-x: hidden; /* Prevent horizontal scrollbar */
231
+ }
232
+ .card {
233
+ border-radius: 1.5rem;
234
+ box-shadow: 0 15px 25px rgba(0, 0, 0, 0.2);
235
+ margin-bottom: 20px;
236
+ }
237
+ .input, .select, .textarea {
238
+ border: 2px solid #4a4a4a;
239
+ border-radius: 0.75rem;
240
+ padding-inline: 1.5rem;
241
+ padding-block: 0.75rem;
242
+ }
243
+ h1, h2, h3 {
244
+ color: #e0e0e0;
245
+ }
246
+ .output-area {
247
+ padding: 1.5rem;
248
+ border-radius: 0.75rem;
249
+ }
250
+ .btn {
251
+ border-radius: 0.75rem;
252
+ padding-block: 0.75rem;
253
+ padding-inline: 1.5rem;
254
+ }
255
+ .btn-primary {
256
+ background-color: #7928CA;
257
+ color: white;
258
+ border: 2px solid #7928CA;
259
+ }
260
+ .btn-primary:hover {
261
+ background-color: #5e22a1;
262
+ }
263
+ .btn-success {
264
+ background-color: #22c55e;
265
+ color: white;
266
+ border: 2px solid #22c55e;
267
+ }
268
+ .btn-success:hover {
269
+ background-color: #1a9a46;
270
+ }
271
+ </style>
272
+ </head>
273
+ <body class="bg-gray-900">
274
+ <div class="container mx-auto p-4">
275
+ <h1 class="text-4xl md:text-5xl font-extrabold text-center mb-8">GitHub Issue Manager</h1>
276
+ <!-- GitHub Token & Repo URL -->
277
+ <div class="card bg-gray-800 p-8">
278
+ <div class="form-control">
279
+ <label class="label">
280
+ <span class="label-text">GitHub Token</span>
281
+ </label>
282
+ <input type="password" placeholder="Enter your GitHub Personal Access Token" class="input input-bordered input-primary" id="github-token">
283
+ </div>
284
+ <div class="form-control">
285
+ <label class="label">
286
+ <span class="label-text">Repository URL</span>
287
+ </label>
288
+ <input type="text" placeholder="Enter the full GitHub repository URL" class="input input-bordered input-primary" id="repo-url">
289
+ </div>
290
+ </div>
291
+ <!-- Fetch & Resolve Section -->
292
+ <div class="card bg-gray-800 p-8">
293
+ <div class="flex justify-between gap-4">
294
+ <button class="btn btn-primary" id="fetch-issues">Fetch Issues</button>
295
+ <select class="select select-primary w-full max-w-xs" id="issue-dropdown">
296
+ <option disabled selected>Select Issue</option>
297
+ </select>
298
+ </div>
299
+ <div class="form-control mt-4">
300
+ <label class="label">
301
+ <span class="label-text">Resolution</span>
302
+ </label>
303
+ <textarea class="textarea textarea-primary" placeholder="Enter the resolution details" id="resolution-textarea"></textarea>
304
+ </div>
305
+ <div class="form-control mt-4">
306
+ <label class="label">
307
+ <span class="label-text">Forked Repository URL</span>
308
+ </label>
309
+ <input type="text" placeholder="URL to your forked repository (Optional)" class="input input-bordered input-primary" id="forked-repo-url">
310
+ </div>
311
+ <div class="form-control mt-4">
312
+ <button class="btn btn-success" id="resolve-issue">Resolve Issue</button>
313
+ </div>
314
+ </div>
315
+ <!-- Output Area -->
316
+ <div class="card bg-gray-800 p-8 mt-4">
317
+ <label class="label">
318
+ <span class="label-text">Output</span>
319
+ </label>
320
+ <textarea class="textarea textarea-primary h-48" id="output-textarea" readonly></textarea>
321
+ </div>
322
+ <!-- URL to Extract -->
323
+ <div class="card bg-gray-800 p-8 mt-4">
324
+ <div class="form-control">
325
+ <label class="label">
326
+ <span class="label-text"> URL</span>
327
+ </label>
328
+ <input type="text" placeholder="Enter a URL to extract information" class="input input-bordered input-primary" id="url-textbox">
329
+ </div>
330
+ <div class="form-control">
331
+ <button class="btn btn-primary" id="extract-info">Extract Info</button>
332
+ </div>
333
+ </div>
334
+ </div>
335
+ <script>
336
+ const githubTokenInput = document.getElementById('github-token');
337
+ const repoUrlInput = document.getElementById('repo-url');
338
+ const fetchIssuesButton = document.getElementById('fetch-issues');
339
+ const issueDropdown = document.getElementById('issue-dropdown');
340
+ const resolutionTextarea = document.getElementById('resolution-textarea');
341
+ const forkedRepoUrlInput = document.getElementById('forked-repo-url');
342
+ const resolveIssueButton = document.getElementById('resolve-issue');
343
+ const outputTextarea = document.getElementById('output-textarea');
344
+ const urlTextbox = document.getElementById('url-textbox');
345
+ const extractInfoButton = document.getElementById('extract-info');
346
+
347
+ fetchIssuesButton.addEventListener('click', async () => {
348
+ const token = githubTokenInput.value;
349
+ const repoUrl = repoUrlInput.value;
350
+ if (!token || !repoUrl) {
351
+ outputTextarea.value = "Please provide both GitHub Token and Repository URL.";
352
+ return;
353
+ }
354
+ try {
355
+ const response = await fetch('/fetch-issues', {
356
+ method: 'POST',
357
+ headers: {
358
+ 'Content-Type': 'application/json',
359
+ },
360
+ body: JSON.stringify({ githubToken: token, repoUrl: repoUrl }),
361
+ });
362
+ if (!response.ok) {
363
+ throw new Error(`HTTP error! status: ${response.status}`);
364
+ }
365
+ const data = await response.json();
366
+ if (data.error) {
367
+ outputTextarea.value = data.error;
368
+ } else {
369
+ issueDropdown.innerHTML = '';
370
+ data.issues.forEach(issue => {
371
+ const option = document.createElement('option');
372
+ option.value = issue.number;
373
+ option.text = `${issue.number}: ${issue.title}`;
374
+ issueDropdown.add(option);
375
+ });
376
+ }
377
+ } catch (error) {
378
+ outputTextarea.value = `Error fetching issues: ${error.message}`;
379
+ }
380
+ });
381
+
382
+ resolveIssueButton.addEventListener('click', async () => {
383
+ const token = githubTokenInput.value;
384
+ const repoUrl = repoUrlInput.value;
385
+ const issueNumber = issueDropdown.value;
386
+ const resolution = resolutionTextarea.value;
387
+ const forkedRepoUrl = forkedRepoUrlInput.value;
388
+ if (!token || !repoUrl || !issueNumber || !resolution) {
389
+ outputTextarea.value = "Please provide all required fields.";
390
+ return;
391
+ }
392
+ try {
393
+ const response = await fetch('/resolve-issue', {
394
+ method: 'POST',
395
+ headers: {
396
+ 'Content-Type': 'application/json',
397
+ },
398
+ body: JSON.stringify({ githubToken: token, repoUrl: repoUrl, issueNumber: issueNumber, resolution: resolution, forkedRepoUrl: forkedRepoUrl }),
399
+ });
400
+ if (!response.ok) {
401
+ throw new Error(`HTTP error! status: ${response.status}`);
402
+ }
403
+ const data = await response.json();
404
+ if (data.error) {
405
+ outputTextarea.value = data.error;
406
+ } else {
407
+ outputTextarea.value = data.output;
408
+ }
409
+ } catch (error) {
410
+ outputTextarea.value = `Error resolving issue: ${error.message}`;
411
+ }
412
+ });
413
+
414
+ extractInfoButton.addEventListener('click', async () => {
415
+ const url = urlTextbox.value;
416
+ if (!url) {
417
+ outputTextarea.value = "Please provide a URL.";
418
+ return;
419
+ }
420
+ try {
421
+ const response = await fetch('/extract-info', {
422
+ method: 'POST',
423
+ headers: {
424
+ 'Content-Type': 'application/json',
425
+ },
426
+ body: JSON.stringify({ url: url }),
427
+ });
428
+ if (!response.ok) {
429
+ throw new Error(`HTTP error! status: ${response.status}`);
430
+ }
431
+ const data = await response.json();
432
+ if (data.error) {
433
+ outputTextarea.value = data.error;
434
+ } else {
435
+ outputTextarea.value = JSON.stringify(data, null, 2);
436
+ }
437
+ } catch (error) {
438
+ outputTextarea.value = `Error extracting info: ${error.message}`;
439
+ }
440
+ });
441
+ </script>
442
+ </body>
443
+ </html>
444
+ """
445
+
446
+ def create_gradio_interface():
447
+ with gr.Blocks(css=None, theme=None) as demo:
448
+ gr.HTML(custom_html)
449
+ return demo
450
+
451
+ # Cleanup function
452
+ def cleanup():
453
+ try:
454
+ temp_dirs = [REPOS_DIRECTORY]
455
+ for dir_name in temp_dirs:
456
+ if os.path.exists(dir _name):
457
+ shutil.rmtree(dir_name)
458
+ logging.shutdown()
459
+ except Exception as e:
460
+ print(f"Error during cleanup: {str(e)}")
461
+
462
+ @spaces.GPU()
463
+ def main():
464
+ # Initialize environment and logger
465
+ initialize_environment()
466
+ logger = initialize_logger()
467
+
468
+ # Register cleanup handlers
469
+ atexit.register(cleanup)
470
+
471
+ # Create Gradio interface
472
+ demo = create_gradio_interface()
473
+ demo.launch()
474
+
475
+ if __name__ == "__main__":
476
+ main()