Padmanav commited on
Commit
bb08a92
Β·
1 Parent(s): cf84c8b

feat: add Gradio UI with tabs for all agent outputs

Browse files
Files changed (1) hide show
  1. gradio_app/app.py +212 -0
gradio_app/app.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import json
4
+
5
+ BACKEND_URL = "http://localhost:8000/api/v1"
6
+
7
+
8
+ def analyze_repository(github_url: str, quick_mode: bool):
9
+ """
10
+ Send repository URL to FastAPI backend and display results.
11
+ """
12
+
13
+ if not github_url.strip():
14
+ return "Please enter a GitHub URL", "", "", "", ""
15
+
16
+ if not github_url.startswith("https://github.com/"):
17
+ return "Please enter a valid GitHub URL (https://github.com/...)", "", "", "", ""
18
+
19
+ try:
20
+ endpoint = "/quick-analyze" if quick_mode else "/analyze"
21
+
22
+ response = requests.post(
23
+ f"{BACKEND_URL}{endpoint}",
24
+ json={"github_url": github_url},
25
+ timeout=300
26
+ )
27
+
28
+ if response.status_code != 200:
29
+ return f"Error: {response.status_code} - {response.text}", "", "", "", ""
30
+
31
+ data = response.json()
32
+
33
+ if quick_mode:
34
+ # Quick analyze returns RepositoryResponse
35
+ repo = data.get("data", {})
36
+ summary = f"""
37
+ ## Repository Summary
38
+
39
+ - **Name:** {repo.get('name', 'N/A')}
40
+ - **Language:** {repo.get('language', 'N/A')}
41
+ - **Frameworks:** {', '.join(repo.get('frameworks', []))}
42
+ - **Total Files:** {repo.get('total_files', 0)}
43
+ - **Total Lines:** {repo.get('total_lines', 0)}
44
+ - **Summary:** {repo.get('summary', 'N/A')}
45
+
46
+ ### Architecture
47
+ {repo.get('architecture', 'N/A')}
48
+
49
+ ### Entry Points
50
+ {chr(10).join(repo.get('entry_points', [])) or 'None detected'}
51
+ """
52
+ return summary, "", "", "", ""
53
+
54
+ else:
55
+ # Full analyze returns EngineeringReport
56
+ repo = data.get("repository", {})
57
+ issues = data.get("issues", {})
58
+ tests = data.get("tests", {})
59
+ review = data.get("review", {})
60
+ full_report = data.get("full_report", "")
61
+
62
+ # Repository tab
63
+ repo_summary = f"""
64
+ ## Repository Summary
65
+
66
+ - **Name:** {repo.get('name', 'N/A')}
67
+ - **Language:** {repo.get('language', 'N/A')}
68
+ - **Frameworks:** {', '.join(repo.get('frameworks', []))}
69
+ - **Total Files:** {repo.get('total_files', 0)}
70
+ - **Total Lines:** {repo.get('total_lines', 0)}
71
+
72
+ ### Summary
73
+ {repo.get('summary', 'N/A')}
74
+
75
+ ### Architecture
76
+ {repo.get('architecture', 'N/A')}
77
+ """
78
+
79
+ # Issues tab
80
+ issues_summary = f"""
81
+ ## Bug Detection Results
82
+
83
+ - **Critical Bugs:** {issues.get('total_critical', 0)}
84
+ - **Warnings:** {issues.get('total_warnings', 0)}
85
+ - **Suggestions:** {issues.get('total_suggestions', 0)}
86
+
87
+ ### Critical Bugs
88
+ {chr(10).join([f"- {b.get('description', '')} ({b.get('file', '')})" for b in issues.get('critical', [])]) or 'None found'}
89
+
90
+ ### Warnings
91
+ {chr(10).join([f"- {w.get('description', '')} ({w.get('file', '')})" for w in issues.get('warnings', [])]) or 'None found'}
92
+
93
+ ### Suggestions
94
+ {chr(10).join([f"- {s.get('description', '')}" for s in issues.get('suggestions', [])]) or 'None found'}
95
+ """
96
+
97
+ # Tests tab
98
+ tests_summary = f"""
99
+ ## Test Generation Results
100
+
101
+ - **Tests Generated:** {tests.get('total_tests_generated', 0)}
102
+ - **Coverage Before:** {tests.get('estimated_coverage_before', 0)}%
103
+ - **Coverage After:** {tests.get('estimated_coverage_after', 0)}%
104
+
105
+ ### Generated Test Code
106
+ ```python
107
+ {tests.get('test_code', 'No tests generated')}
108
+ ```
109
+ """
110
+
111
+ # Review tab
112
+ review_summary = f"""
113
+ ## Code Review Results
114
+
115
+ - **Overall Score:** {review.get('overall_score', 0)}/10
116
+
117
+ ### SOLID Violations
118
+ {chr(10).join([f"- {v}" for v in review.get('solid_violations', [])]) or 'None found'}
119
+
120
+ ### Duplicate Code
121
+ {chr(10).join([f"- {d}" for d in review.get('duplicate_code', [])]) or 'None found'}
122
+
123
+ ### Refactor Suggestions
124
+ {chr(10).join([f"- {r}" for r in review.get('refactor_suggestions', [])]) or 'None found'}
125
+
126
+ ### Summary
127
+ {review.get('summary', 'N/A')}
128
+ """
129
+
130
+ return repo_summary, issues_summary, tests_summary, review_summary, full_report
131
+
132
+ except requests.exceptions.ConnectionError:
133
+ return "Cannot connect to backend. Make sure FastAPI is running on port 8000.", "", "", "", ""
134
+ except requests.exceptions.Timeout:
135
+ return "Request timed out. Large repositories may take longer.", "", "", "", ""
136
+ except Exception as e:
137
+ return f"Unexpected error: {str(e)}", "", "", "", ""
138
+
139
+
140
+ # Build Gradio UI
141
+ with gr.Blocks(
142
+ title="AI Code Review Agent",
143
+ theme=gr.themes.Soft()
144
+ ) as demo:
145
+
146
+ gr.Markdown("""
147
+ # πŸ€– AI Code Review Agent
148
+ ### Multi-agent AI platform that simulates a software engineering team
149
+ Enter a public GitHub repository URL to analyze it automatically.
150
+ """)
151
+
152
+ with gr.Row():
153
+ with gr.Column(scale=4):
154
+ github_url = gr.Textbox(
155
+ label="GitHub Repository URL",
156
+ placeholder="https://github.com/username/repository",
157
+ lines=1
158
+ )
159
+ with gr.Column(scale=1):
160
+ quick_mode = gr.Checkbox(
161
+ label="Quick Mode",
162
+ value=False,
163
+ info="Only run repo analysis (faster)"
164
+ )
165
+
166
+ analyze_btn = gr.Button(
167
+ "πŸš€ Analyze Repository",
168
+ variant="primary",
169
+ size="lg"
170
+ )
171
+
172
+ gr.Markdown("---")
173
+
174
+ with gr.Tabs():
175
+ with gr.Tab("πŸ“ Repository"):
176
+ repo_output = gr.Markdown()
177
+
178
+ with gr.Tab("πŸ› Bugs & Issues"):
179
+ issues_output = gr.Markdown()
180
+
181
+ with gr.Tab("πŸ§ͺ Generated Tests"):
182
+ tests_output = gr.Markdown()
183
+
184
+ with gr.Tab("πŸ” Code Review"):
185
+ review_output = gr.Markdown()
186
+
187
+ with gr.Tab("πŸ“Š Full Report"):
188
+ report_output = gr.Markdown()
189
+
190
+ analyze_btn.click(
191
+ fn=analyze_repository,
192
+ inputs=[github_url, quick_mode],
193
+ outputs=[repo_output, issues_output, tests_output, review_output, report_output]
194
+ )
195
+
196
+ gr.Markdown("""
197
+ ---
198
+ ### How it works
199
+ 1. **Repository Analysis** β€” Detects language, frameworks, architecture
200
+ 2. **Bug Detection** β€” Runs static analysis and identifies issues
201
+ 3. **Test Generation** β€” Creates pytest test cases automatically
202
+ 4. **Code Review** β€” Reviews SOLID principles and suggests refactors
203
+ 5. **Report** β€” Combines everything into an engineering report
204
+ """)
205
+
206
+
207
+ if __name__ == "__main__":
208
+ demo.launch(
209
+ server_name="0.0.0.0",
210
+ server_port=7860,
211
+ share=False
212
+ )