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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +207 -121
app.py CHANGED
@@ -1,137 +1,223 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
  import os
4
- import asyncio
5
- import aiohttp
6
- import json
7
- import logging
8
- import hashlib
9
- from typing import List, Dict, Tuple
10
- from transformers import pipeline
11
- from sentence_transformers import SentenceTransformer, util
12
- from pydantic import BaseModel, SecretStr
13
 
14
- # Enable detailed logging
15
- logging.basicConfig(level=logging.INFO)
 
 
 
 
16
 
17
- # Hugging Face Inference Client
18
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
19
-
20
- # Load a pre-trained model for sentence similarity
21
- similarity_model = SentenceTransformer('all-mpnet-base-v2')
22
-
23
- class GitHubConfig(BaseModel):
24
- username: str
25
- repository: str
26
- api_token: SecretStr
27
-
28
- class GitHubIntegration:
29
- def __init__(self, config: GitHubConfig):
30
- self.config = config
31
- self.headers = {
32
- "Authorization": f"Bearer {self.config.api_token.get_secret_value()}",
33
- "Accept": "application/vnd.github.v3+json"
34
- }
35
- self.url = "https://api.github.com"
36
-
37
- async def fetch_issues(self) -> List[Dict]:
38
- cache_key = hashlib.md5(f"{self.config.username}/{self.config.repository}".encode()).hexdigest()
39
- cached_data = await self._load_cache(cache_key)
40
- if cached_data:
41
- return cached_data
42
 
43
- url = f"{self.url}/repos/{self.config.username}/{self.config.repository}/issues"
 
 
 
 
 
 
 
 
 
 
 
44
  try:
45
- async with aiohttp.ClientSession() as session:
46
- async with session.get(url, headers=self.headers) as response:
47
- response.raise_for_status()
48
- issues = await response.json()
49
- await self._save_cache(cache_key, issues)
50
- return issues
 
 
51
  except Exception as e:
52
- logging.error(f"GitHub API error: {str(e)}")
53
- return []
 
 
54
 
55
- async def _load_cache(self, key: str) -> List[Dict] | None:
56
- cache_file = f"cache_{key}.json"
57
- if os.path.exists(cache_file):
58
- async with aiohttp.ClientSession() as session:
59
- async with session.get(f"file://{cache_file}") as f:
60
- return json.loads(await f.text())
61
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
- async def _save_cache(self, key: str, data: List[Dict]):
64
- cache_file = f"cache_{key}.json"
65
- with open(cache_file, "w") as f:
66
- json.dump(data, f)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
- async def analyze_issues(issue_text: str, model_name: str) -> str:
69
- """
70
- Analyze issues and provide solutions.
71
- """
72
- logging.info(f"Analyzing issue with model: {model_name}")
73
- prompt = f"""
74
- Issue: {issue_text}
75
- Please provide a comprehensive resolution in the following format:
76
- ## Problem Summary:
77
- ## Root Cause Analysis:
78
- ## Solution Options:
79
- ## Recommended Solution:
80
- ## Implementation Steps:
81
- ## Verification Steps:
82
- """
83
  try:
84
- nlp = pipeline("text-generation", model=model_name, max_length=1000)
85
- result = nlp(prompt)
86
- return result[0]['generated_text']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  except Exception as e:
88
- logging.error(f"Error analyzing issue: {e}")
89
- return "Error analyzing issue."
90
 
91
- async def find_related_issues(issue_text: str, issues: list) -> list:
92
- """
93
- Find related issues using similarity model.
94
- """
95
- issue_embedding = similarity_model.encode(issue_text)
96
- related_issues = [
97
- (issue, util.cos_sim(issue_embedding, similarity_model.encode(issue['title']))[0][0])
98
- for issue in issues
99
- ]
100
- return sorted(related_issues, key=lambda x: x[1], reverse=True)[:3]
101
 
102
- def respond(command: str, github_api_token: str, github_username: str, github_repository: str, selected_model: str) -> str:
103
- """
104
- Handle chat responses.
105
- """
106
- if command.startswith("/github"):
107
- parts = command.split(maxsplit=2)
108
- if len(parts) < 3:
109
- return "❌ Format: /github <username> <repo> <token>"
110
- github_client = GitHubIntegration(GitHubConfig(username=parts[0], repository=parts[1], api_token=SecretStr(parts[2])))
111
- issues = asyncio.run(github_client.fetch_issues())
112
- return "βœ… GitHub configured successfully."
113
- elif command.startswith("/analyze"):
114
- issue_text = command.replace("/analyze", "").strip()
115
- return asyncio.run(analyze_issues(issue_text, selected_model))
116
- elif command.startswith("/list_issues"):
117
- github_client = GitHubIntegration(GitHubConfig(username=github_username, repository=github_repository, api_token=SecretStr(github_api_token)))
118
- issues = asyncio.run(github_client.fetch_issues())
119
- return "\n".join([f"- {issue['title']} (Issue #{issue['number']})" for issue in issues])
120
- else:
121
- return "Unknown command. Use /help for instructions."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
- iface = gr.Interface(
124
- fn=respond,
125
- inputs=[
126
- gr.Textbox(label="Command"),
127
- gr.Textbox(label="GitHub API Token", placeholder="Enter your GitHub API token"),
128
- gr.Textbox(label="GitHub Username", placeholder="Enter your GitHub username"),
129
- gr.Textbox(label="GitHub Repository", placeholder="Enter your GitHub repository"),
130
- gr.Dropdown(label="Model", choices=["text-davinci-003", "text-curie-001"], value="text-davinci-003"),
131
- ],
132
- outputs=gr.Textbox(label="Response"),
133
- title="AI GitHub Assistant",
134
- description="Interact with GitHub and analyze issues with AI.",
135
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
 
137
- iface.launch(share=True)
 
 
 
1
  import gradio as gr
 
2
  import os
3
+ import requests
4
+ from git import Repo, GitCommandError
5
+ from pathlib import Path
6
+ from datetime import datetime
7
+ import shutil
8
+ import time
 
 
 
9
 
10
+ # ========== Configuration ==========
11
+ REPO_OWNER = "enricoros"
12
+ 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)