acecalisto3 commited on
Commit
cbb25bf
Β·
verified Β·
1 Parent(s): 0cdb48b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -131
app.py CHANGED
@@ -6,6 +6,10 @@ from pathlib import Path
6
  from datetime import datetime
7
  import shutil
8
  import time
 
 
 
 
9
 
10
  # ========== Configuration ==========
11
  REPO_OWNER = "enricoros"
@@ -13,211 +17,238 @@ REPO_NAME = "big-agi"
13
  MIAGI_FORK = "https://github.com/Ig0tU/miagi.git"
14
  WORKSPACE = Path("/tmp/issue_workspace")
15
  WORKSPACE.mkdir(exist_ok=True)
 
16
 
17
- # ========== Theme & Styling ==========
 
 
 
 
18
  theme = gr.themes.Default(
19
  primary_hue="emerald",
20
  secondary_hue="zinc",
 
21
  ).set(
22
  button_primary_background_fill="*primary_500",
23
  button_primary_background_fill_hover="*primary_400",
24
  button_primary_text_color="white",
25
  block_label_background_fill="*primary_500",
26
  block_label_text_color="white",
 
27
  )
28
 
29
- # ========== State Management ==========
30
- class IssueManager:
31
  def __init__(self):
32
- self.issues = {}
33
- self.last_fetched = None
34
- self.current_issue = None
35
- self.repo = None
36
-
37
- def fetch_issues(self):
 
 
38
  if self.last_fetched and (datetime.now() - self.last_fetched).seconds < 300:
39
- return True
40
-
41
  try:
42
- response = requests.get(
43
- f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/issues",
44
- headers={"Authorization": f"Bearer {os.environ.get('GITHUB_TOKEN', '')}"}
45
- )
46
- response.raise_for_status()
47
- self.issues = {issue['number']: issue for issue in response.json()}
48
- self.last_fetched = datetime.now()
49
- return True
50
  except Exception as e:
51
- print(f"Error fetching issues: {e}")
52
- return False
53
 
54
- issue_manager = IssueManager()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- # ========== Core Functions ==========
57
- def replicate_issue(issue_number):
 
 
58
  try:
59
  issue_number = int(issue_number)
60
- if not issue_manager.fetch_issues():
61
- return {"error": "⚠️ Failed to fetch issues from GitHub"}, None, None
62
-
 
63
  if issue_number not in issue_manager.issues:
64
  return {"error": f"❌ Issue #{issue_number} not found"}, None, None
65
-
66
  issue = issue_manager.issues[issue_number]
67
  repo_path = WORKSPACE / f"miagi-{issue_number}"
 
68
 
69
- # Clone repository
 
 
 
70
  try:
71
- repo = Repo.clone_from(MIAGI_FORK, repo_path, branch="main")
 
 
72
  except GitCommandError:
73
  repo = Repo(repo_path)
74
-
75
- # Create working branch
76
  branch_name = f"issue-{issue_number}"
77
  repo.git.checkout('-b', branch_name)
78
 
79
- # Simulate issue replication
80
  issues_dir = repo_path / "issues" / str(issue_number)
81
  issues_dir.mkdir(parents=True, exist_ok=True)
82
- (issues_dir / "replication.log").write_text(f"Replicated at {datetime.utcnow()} UTC")
 
 
 
 
 
83
 
84
  issue_manager.repo = repo
85
  issue_manager.current_issue = issue_number
86
 
87
  return {
88
- "success": f"πŸš€ Replicated issue #{issue_number} in branch '{branch_name}'"
89
- }, issue["body"], gr.update(visible=True)
90
-
 
 
91
  except Exception as e:
 
92
  return {"error": f"β›” Critical error: {str(e)}"}, None, None
93
 
94
- def resolve_issue(resolution_notes):
95
  if not issue_manager.current_issue:
96
  return {"error": "⚠️ No active issue selected"}, None
97
-
98
  try:
99
  repo = issue_manager.repo
100
  issue_number = issue_manager.current_issue
101
  resolution_dir = repo.working_dir / "issues" / str(issue_number)
102
 
103
- # Create resolution files
104
  timestamp = datetime.utcnow().strftime("%Y%m%d-%H%M%S")
105
- (resolution_dir / f"resolution_{timestamp}.md").write_text(resolution_notes)
 
 
 
 
 
 
106
  (resolution_dir / "RESOLVED").touch()
107
 
108
- return {"success": "πŸ”§ Resolution draft saved locally"}, gr.update(visible=True)
109
-
110
  except Exception as e:
111
  return {"error": f"β›” Resolution failed: {str(e)}"}, None
112
 
113
- def submit_resolution():
114
  if not issue_manager.current_issue:
115
  return {"error": "⚠️ No active issue selected"}
116
-
117
  try:
118
  repo = issue_manager.repo
119
  issue_number = issue_manager.current_issue
120
 
121
- # Stage changes
122
  repo.git.add(all=True)
123
-
124
- # Commit
125
  commit_message = f"Resolve #{issue_number}: {issue_manager.issues[issue_number]['title']}"
126
  repo.index.commit(commit_message)
127
 
128
- # Push
129
  origin = repo.remote(name='origin')
130
- origin.push(refspec=f"issue-{issue_number}:issue-{issue_number}")
131
-
132
- # Create PR
133
- pr_url = f"https://github.com/Ig0tU/miagi/compare/issue-{issue_number}?expand=1"
134
 
 
 
 
 
 
135
  return {
136
  "success": f"πŸš€ Resolution submitted!\n\n[Review PR]({pr_url})",
137
  "pr_url": pr_url
138
  }
139
-
140
- except GitCommandError as e:
141
- return {"error": f"β›” Git operation failed: {str(e)}"}
142
  except Exception as e:
143
  return {"error": f"β›” Submission failed: {str(e)}"}
144
 
145
- # ========== UI Components ==========
146
- def create_header():
147
- with gr.Row():
148
- gr.Markdown("""
149
- # πŸš€ Issue Resolution Workshop
150
- ### ⚑ Power Tools for GitHub Issue Management
151
- """)
152
- gr.Image(value="https://img.icons8.com/3d-fluency/94/github.png", width=94, height=94)
153
-
154
- def create_workflow_tabs():
155
- with gr.Tabs() as tabs:
156
- with gr.TabItem("πŸ” Investigate", id=1):
157
- with gr.Row():
158
- with gr.Column(scale=1):
159
- issue_input = gr.Number(label="ISSUE NUMBER", precision=0)
160
- gr.Button("πŸ“‘ Sync GitHub Issues", variant="secondary").click(
161
- fn=lambda: issue_manager.fetch_issues(),
162
- outputs=None
163
- )
164
- with gr.Column(scale=2):
165
- status_output = gr.JSON(label="STATUS")
166
- replicate_btn = gr.Button("⚑ Replicate Issue", variant="primary")
167
-
168
- with gr.TabItem("πŸ”§ Resolve", id=2):
169
- with gr.Row():
170
- with gr.Column():
171
- issue_desc = gr.Markdown("### Issue details will appear here")
172
- resolution_input = gr.Textbox(label="Resolution Notes", lines=8,
173
- placeholder="Describe your solution...")
174
- resolve_btn = gr.Button("πŸ’Ύ Save Resolution", variant="primary")
175
- with gr.Column():
176
- resolution_proof = gr.FileExplorer(label="Resolution Artifacts")
177
-
178
- with gr.TabItem("πŸš€ Deploy", id=3):
179
- with gr.Row():
180
- with gr.Column():
181
- gr.Markdown("### Deployment Checklist")
182
- gr.CheckboxGroup(["βœ… Tests passing", "βœ… Code reviewed", "βœ… Documentation updated"])
183
- deploy_btn = gr.Button("πŸ”₯ Submit Resolution", variant="primary")
184
- with gr.Column():
185
- pr_output = gr.Markdown()
186
-
187
- return (issue_input, replicate_btn, status_output, issue_desc,
188
- resolution_input, resolve_btn, deploy_btn, pr_output)
189
-
190
- # ========== App Assembly ==========
191
- with gr.Blocks(theme=theme, css="footer {visibility: hidden}") as app:
192
- create_header()
193
- components = create_workflow_tabs()
194
- (issue_input, replicate_btn, status_output, issue_desc,
195
- resolution_input, resolve_btn, deploy_btn, pr_output) = components
196
-
197
- # Event handlers
198
- replicate_event = replicate_btn.click(
199
- fn=replicate_issue,
200
- inputs=issue_input,
201
- outputs=[status_output, issue_desc, gr.Tabs(selected=1)]
202
- )
203
-
204
- resolve_event = resolve_btn.click(
205
- fn=resolve_issue,
206
- inputs=resolution_input,
207
- outputs=[status_output, deploy_btn]
208
- )
209
-
210
- deploy_event = deploy_btn.click(
211
- fn=submit_resolution,
212
- outputs=[status_output, pr_output]
213
- )
214
-
215
- # Progress animations
216
- replicate_event.then(
217
- fn=lambda: gr.update(visible=True),
218
- outputs=resolve_btn
219
- )
220
 
221
  # ========== Execution ==========
222
  if __name__ == "__main__":
 
223
  app.launch(server_port=7860, share=True)
 
6
  from datetime import datetime
7
  import shutil
8
  import time
9
+ import json
10
+ import asyncio
11
+ from typing import Dict, Optional, Tuple
12
+ import logging
13
 
14
  # ========== Configuration ==========
15
  REPO_OWNER = "enricoros"
 
17
  MIAGI_FORK = "https://github.com/Ig0tU/miagi.git"
18
  WORKSPACE = Path("/tmp/issue_workspace")
19
  WORKSPACE.mkdir(exist_ok=True)
20
+ HF_SPACE_API = "https://huggingface.co/api/spaces" # Hypothetical HF Space API
21
 
22
+ # Setup logging
23
+ logging.basicConfig(level=logging.INFO)
24
+ logger = logging.getLogger(__name__)
25
+
26
+ # ========== Enhanced Theme ==========
27
  theme = gr.themes.Default(
28
  primary_hue="emerald",
29
  secondary_hue="zinc",
30
+ radius_size="lg",
31
  ).set(
32
  button_primary_background_fill="*primary_500",
33
  button_primary_background_fill_hover="*primary_400",
34
  button_primary_text_color="white",
35
  block_label_background_fill="*primary_500",
36
  block_label_text_color="white",
37
+ body_background_fill="gray_100",
38
  )
39
 
40
+ # ========== State Management with Spaces Integration ==========
41
+ class EnhancedIssueManager:
42
  def __init__(self):
43
+ self.issues: Dict[int, dict] = {}
44
+ self.last_fetched: Optional[datetime] = None
45
+ self.current_issue: Optional[int] = None
46
+ self.repo: Optional[Repo] = None
47
+ self.space_status: Dict = {}
48
+ self.progress_tracker = {}
49
+
50
+ async def fetch_issues(self) -> Tuple[bool, str]:
51
  if self.last_fetched and (datetime.now() - self.last_fetched).seconds < 300:
52
+ return True, "Using cached issues"
53
+
54
  try:
55
+ headers = {"Authorization": f"Bearer {os.environ.get('GITHUB_TOKEN', '')}"}
56
+ async with aiohttp.ClientSession() as session:
57
+ async with session.get(f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/issues",
58
+ headers=headers) as response:
59
+ response.raise_for_status()
60
+ self.issues = {issue['number']: issue for issue in await response.json()}
61
+ self.last_fetched = datetime.now()
62
+ return True, "Successfully fetched issues"
63
  except Exception as e:
64
+ logger.error(f"Error fetching issues: {e}")
65
+ return False, f"Failed to fetch issues: {str(e)}"
66
 
67
+ async def check_space_status(self, issue_number: int) -> Dict:
68
+ """Check if issue relates to a Hugging Face Space"""
69
+ try:
70
+ headers = {"Authorization": f"Bearer {os.environ.get('HF_TOKEN', '')}"}
71
+ async with aiohttp.ClientSession() as session:
72
+ async with session.get(f"{HF_SPACE_API}/{REPO_OWNER}/{REPO_NAME}",
73
+ headers=headers) as response:
74
+ if response.status == 200:
75
+ space_data = await response.json()
76
+ self.space_status[issue_number] = space_data
77
+ return {"space_found": True, "data": space_data}
78
+ return {"space_found": False}
79
+ except Exception as e:
80
+ logger.error(f"Space check failed: {e}")
81
+ return {"space_found": False, "error": str(e)}
82
 
83
+ issue_manager = EnhancedIssueManager()
84
+
85
+ # ========== Core Functions with Space Handling ==========
86
+ async def replicate_issue(issue_number: str) -> Tuple[Dict, str, gr.update]:
87
  try:
88
  issue_number = int(issue_number)
89
+ success, fetch_message = await issue_manager.fetch_issues()
90
+ if not success:
91
+ return {"error": f"⚠️ {fetch_message}"}, None, None
92
+
93
  if issue_number not in issue_manager.issues:
94
  return {"error": f"❌ Issue #{issue_number} not found"}, None, None
95
+
96
  issue = issue_manager.issues[issue_number]
97
  repo_path = WORKSPACE / f"miagi-{issue_number}"
98
+ issue_manager.progress_tracker[issue_number] = {"status": "initializing"}
99
 
100
+ # Check Space status
101
+ space_status = await issue_manager.check_space_status(issue_number)
102
+
103
+ # Clone with progress
104
  try:
105
+ issue_manager.progress_tracker[issue_number] = {"status": "cloning"}
106
+ repo = Repo.clone_from(MIAGI_FORK, repo_path, branch="main",
107
+ progress=lambda x: issue_manager.progress_tracker[issue_number].update({"progress": x}))
108
  except GitCommandError:
109
  repo = Repo(repo_path)
110
+
 
111
  branch_name = f"issue-{issue_number}"
112
  repo.git.checkout('-b', branch_name)
113
 
114
+ # Handle Space replication if applicable
115
  issues_dir = repo_path / "issues" / str(issue_number)
116
  issues_dir.mkdir(parents=True, exist_ok=True)
117
+
118
+ replication_details = {
119
+ "timestamp": datetime.utcnow().isoformat(),
120
+ "space_status": space_status
121
+ }
122
+ (issues_dir / "replication.json").write_text(json.dumps(replication_details))
123
 
124
  issue_manager.repo = repo
125
  issue_manager.current_issue = issue_number
126
 
127
  return {
128
+ "success": f"πŸš€ Replicated issue #{issue_number}",
129
+ "space": space_status,
130
+ "progress": issue_manager.progress_tracker[issue_number]
131
+ }, issue["body"], gr.update(selected=1)
132
+
133
  except Exception as e:
134
+ logger.error(f"Replication error: {e}")
135
  return {"error": f"β›” Critical error: {str(e)}"}, None, None
136
 
137
+ async def resolve_issue(resolution_notes: str, space_config: Optional[str] = None) -> Tuple[Dict, gr.update]:
138
  if not issue_manager.current_issue:
139
  return {"error": "⚠️ No active issue selected"}, None
140
+
141
  try:
142
  repo = issue_manager.repo
143
  issue_number = issue_manager.current_issue
144
  resolution_dir = repo.working_dir / "issues" / str(issue_number)
145
 
 
146
  timestamp = datetime.utcnow().strftime("%Y%m%d-%H%M%S")
147
+ resolution_data = {
148
+ "notes": resolution_notes,
149
+ "space_config": space_config,
150
+ "resolved_at": timestamp
151
+ }
152
+
153
+ (resolution_dir / f"resolution_{timestamp}.json").write_text(json.dumps(resolution_data))
154
  (resolution_dir / "RESOLVED").touch()
155
 
156
+ return {"success": "πŸ”§ Resolution saved"}, gr.update(visible=True)
 
157
  except Exception as e:
158
  return {"error": f"β›” Resolution failed: {str(e)}"}, None
159
 
160
+ async def submit_resolution() -> Dict:
161
  if not issue_manager.current_issue:
162
  return {"error": "⚠️ No active issue selected"}
163
+
164
  try:
165
  repo = issue_manager.repo
166
  issue_number = issue_manager.current_issue
167
 
 
168
  repo.git.add(all=True)
 
 
169
  commit_message = f"Resolve #{issue_number}: {issue_manager.issues[issue_number]['title']}"
170
  repo.index.commit(commit_message)
171
 
 
172
  origin = repo.remote(name='origin')
173
+ branch_name = f"issue-{issue_number}"
174
+ origin.push(refspec=f"{branch_name}:{branch_name}")
 
 
175
 
176
+ # Space-specific submission if applicable
177
+ if issue_manager.space_status.get(issue_number, {}).get("space_found"):
178
+ await self._update_space_config(issue_number)
179
+
180
+ pr_url = f"https://github.com/Ig0tU/miagi/compare/{branch_name}?expand=1"
181
  return {
182
  "success": f"πŸš€ Resolution submitted!\n\n[Review PR]({pr_url})",
183
  "pr_url": pr_url
184
  }
 
 
 
185
  except Exception as e:
186
  return {"error": f"β›” Submission failed: {str(e)}"}
187
 
188
+ async def _update_space_config(self, issue_number: int):
189
+ """Update Hugging Face Space configuration"""
190
+ try:
191
+ headers = {"Authorization": f"Bearer {os.environ.get('HF_TOKEN', '')}"}
192
+ config = {"issue_number": issue_number, "status": "resolved"}
193
+ async with aiohttp.ClientSession() as session:
194
+ await session.post(
195
+ f"{HF_SPACE_API}/{REPO_OWNER}/{REPO_NAME}/config",
196
+ json=config,
197
+ headers=headers
198
+ )
199
+ except Exception as e:
200
+ logger.error(f"Space config update failed: {e}")
201
+
202
+ # ========== Enhanced UI ==========
203
+ def create_enhanced_ui():
204
+ with gr.Blocks(theme=theme, css="footer {visibility: hidden}") as app:
205
+ gr.Markdown("# πŸš€ Enhanced Repository Manager\n### With Hugging Face Spaces Integration")
206
+
207
+ with gr.Tabs() as tabs:
208
+ with gr.Tab("πŸ” Investigate"):
209
+ with gr.Row():
210
+ issue_input = gr.Number(label="Issue Number")
211
+ replicate_btn = gr.Button("⚑ Replicate", variant="primary")
212
+ status_output = gr.JSON(label="Replication Status")
213
+ progress_bar = gr.Progress()
214
+
215
+ with gr.Tab("πŸ”§ Resolve"):
216
+ with gr.Row():
217
+ with gr.Column():
218
+ issue_desc = gr.Markdown()
219
+ resolution_input = gr.Textbox(lines=8, label="Resolution Notes")
220
+ space_config = gr.Textbox(lines=2, label="Space Config (if applicable)")
221
+ resolve_btn = gr.Button("πŸ’Ύ Save", variant="primary")
222
+ with gr.Column():
223
+ file_explorer = gr.FileExplorer()
224
+
225
+ with gr.Tab("πŸš€ Deploy"):
226
+ deploy_btn = gr.Button("πŸ”₯ Submit", variant="primary")
227
+ pr_output = gr.Markdown()
228
+ space_status = gr.JSON(label="Space Status")
229
+
230
+ # Event handlers with async support
231
+ replicate_btn.click(
232
+ fn=replicate_issue,
233
+ inputs=issue_input,
234
+ outputs=[status_output, issue_desc, tabs],
235
+ _js="async (...args) => await gradioClient.run(args)"
236
+ )
237
+
238
+ resolve_btn.click(
239
+ fn=resolve_issue,
240
+ inputs=[resolution_input, space_config],
241
+ outputs=[status_output, deploy_btn]
242
+ )
243
+
244
+ deploy_btn.click(
245
+ fn=submit_resolution,
246
+ outputs=[status_output, pr_output, space_status]
247
+ )
248
+
249
+ return app
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
  # ========== Execution ==========
252
  if __name__ == "__main__":
253
+ app = create_enhanced_ui()
254
  app.launch(server_port=7860, share=True)