debuggenie / app.py
Nihal2000's picture
Update app.py
42fc0c4 verified
"""
DebugGenie - Hackathon Edition πŸ†
Modern, Multi-Agent AI Debugging Assistant
"""
import os
import time
import gradio as gr
import plotly.graph_objects as go
import networkx as nx
# --- CONFIGURATION ---
MODAL_API_URL = os.environ.get("MODAL_API_URL")
# --- CUSTOM CSS (Moved to launch() in Gradio 6) ---
HACKATHON_CSS = """
/* 🎨 Global Styles */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&family=JetBrains+Mono:wght@400;700&display=swap');
.gradio-container {
max-width: 1400px !important;
}
/* 🦸 Hero Section */
.hero-section {
background: linear-gradient(135deg, #1e40af 0%, #7c3aed 100%);
padding: 3rem 2rem;
border-radius: 1rem;
color: white;
text-align: center;
margin-bottom: 2rem;
box-shadow: 0 10px 25px rgba(30, 64, 175, 0.2);
}
.hero-title {
font-size: 3.5rem;
font-weight: 800;
margin-bottom: 0.5rem;
background: linear-gradient(to right, #ffffff, #e0e7ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero-subtitle {
font-size: 1.25rem;
color: #e0e7ff;
margin-bottom: 2rem;
font-weight: 500;
}
.feature-badges {
display: flex;
justify-content: center;
gap: 1rem;
flex-wrap: wrap;
}
.badge {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
padding: 0.5rem 1rem;
border-radius: 2rem;
font-size: 0.9rem;
font-weight: 600;
border: 1px solid rgba(255, 255, 255, 0.2);
transition: transform 0.2s;
}
.badge:hover {
transform: translateY(-2px);
background: rgba(255, 255, 255, 0.25);
}
/* πŸ“Š Stats Bar */
.stats-container {
display: flex;
justify-content: center;
gap: 3rem;
margin: 2rem 0;
padding: 1.5rem;
background: white;
border-radius: 0.75rem;
border: 1px solid #e5e7eb;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
}
.stat-item {
font-weight: 600;
color: #4b5563;
}
/* πŸ€– Agent Activity Monitor */
.agent-card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.75rem;
padding: 1rem;
margin-bottom: 0.75rem;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 1rem;
}
.agent-card:hover {
transform: translateX(4px);
border-color: #6366f1;
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.1);
}
.agent-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
background: #f3f4f6;
}
.agent-info {
flex: 1;
}
.agent-name {
font-weight: 700;
font-size: 0.9rem;
color: #1f2937;
margin-bottom: 0.25rem;
}
.agent-status {
font-size: 0.8rem;
color: #6b7280;
}
/* 🟒 Status Indicators */
.status-dot {
width: 10px;
height: 10px;
border-radius: 50%;
display: inline-block;
}
.status-dot.waiting {
background-color: #ef4444;
box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.2);
}
.status-dot.processing {
background-color: #f59e0b;
animation: pulse 1.5s infinite;
}
.status-dot.complete {
background-color: #10b981;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.4); }
70% { box-shadow: 0 0 0 6px rgba(245, 158, 11, 0); }
100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0); }
}
/* πŸ’‘ Solution Cards */
.solution-card {
background: white;
border: 1px solid #e5e7eb;
border-left: 4px solid #10b981;
border-radius: 0.75rem;
padding: 1.5rem;
margin-bottom: 1.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
}
.rank-badge {
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 1rem;
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
display: inline-block;
margin-bottom: 0.75rem;
}
.confidence-bar-bg {
height: 6px;
background: #e5e7eb;
border-radius: 3px;
margin-top: 0.5rem;
overflow: hidden;
}
.confidence-bar-fill {
height: 100%;
background: linear-gradient(90deg, #10b981 0%, #3b82f6 100%);
border-radius: 3px;
transition: width 1s ease-out;
}
/* πŸ“± Mobile Tweaks */
@media (max-width: 768px) {
.hero-title { font-size: 2rem; }
.stats-container { flex-direction: column; gap: 1rem; }
}
"""
# --- HELPER FUNCTIONS ---
def generate_agent_html(agent_name, status, message, progress):
"""Generates HTML for a single agent card."""
status_class = "waiting"
if status == "processing":
status_class = "processing"
elif status == "complete":
status_class = "complete"
icon = "πŸ€–"
if "Claude" in agent_name:
icon = "🧠"
elif "Gemini" in agent_name:
icon = "✨"
elif "GPT-4" in agent_name:
icon = "⚑"
return f"""
<div class="agent-card">
<div class="agent-avatar">{icon}</div>
<div class="agent-info">
<div class="agent-name">
{agent_name}
<span class="status-dot {status_class}" style="float: right;"></span>
</div>
<div class="agent-status">{message}</div>
<div class="confidence-bar-bg">
<div class="confidence-bar-fill" style="width: {progress}%;"></div>
</div>
</div>
</div>
"""
def create_3d_viz():
"""Creates a 3D network graph using Plotly."""
G = nx.random_geometric_graph(20, 0.125)
edge_x = []
edge_y = []
edge_z = []
for edge in G.edges():
x0, y0 = G.nodes[edge[0]]['pos']
x1, y1 = G.nodes[edge[1]]['pos']
edge_x.extend([x0, x1, None])
edge_y.extend([y0, y1, None])
edge_z.extend([0, 0, None])
edge_trace = go.Scatter3d(
x=edge_x, y=edge_y, z=edge_z,
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines'
)
node_x = []
node_y = []
node_z = []
for node in G.nodes():
x, y = G.nodes[node]['pos']
node_x.append(x)
node_y.append(y)
node_z.append(0)
node_trace = go.Scatter3d(
x=node_x, y=node_y, z=node_z,
mode='markers',
hoverinfo='text',
marker=dict(
showscale=True,
colorscale='YlGnBu',
reversescale=True,
color=[],
size=10,
colorbar=dict(
thickness=15,
title='Node Connections',
xanchor='left',
titleside='right'
),
line_width=2
)
)
fig = go.Figure(
data=[edge_trace, node_trace],
layout=go.Layout(
title='Error Dependency Graph',
titlefont_size=16,
showlegend=False,
hovermode='closest',
margin=dict(b=20, l=5, r=5, t=40),
scene=dict(
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
zaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
)
)
)
return fig
# --- MAIN APP ---
def create_app():
# Create Blocks with theme and css (they should be here in Gradio 6)
with gr.Blocks(
title="DebugGenie 🧞",
theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate"),
css=HACKATHON_CSS
) as demo:
# 1. HERO SECTION
with gr.Row():
gr.HTML("""
<div class="hero-section">
<h1 class="hero-title">DebugGenie 🧞</h1>
<p class="hero-subtitle">Multi-Agent AI Debugging Assistant</p>
<div class="feature-badges">
<span class="badge">πŸ€– Powered by Claude β€’ Gemini β€’ GPT-4</span>
<span class="badge">🎨 3D Visualization</span>
<span class="badge">πŸ”Š Voice Explanations</span>
</div>
</div>
""")
# 2. STATS BAR
gr.HTML("""
<div class="stats-container">
<div class="stat-item">πŸ€– 3 AI Agents Active</div>
<div class="stat-item">πŸ”§ 5 MCP Tools Connected</div>
<div class="stat-item">⚑ Real-time Analysis Ready</div>
</div>
""")
# 3. MAIN LAYOUT (Two Columns)
with gr.Row():
# LEFT COLUMN: INPUT (40%)
with gr.Column(scale=2):
with gr.Group():
gr.Markdown("### πŸ“ Describe the Issue")
error_input = gr.Code(
label="Error Trace / Code Snippet",
language="python",
lines=10
)
with gr.Accordion("πŸ“Έ Add Context (Optional)", open=False):
screenshot_input = gr.Image(
label="Upload Screenshot",
type="pil",
height=200
)
analyze_btn = gr.Button(
"πŸ” Analyze Error",
variant="primary",
size="lg"
)
with gr.Row():
example_btn = gr.Button("🎲 Try Example", size="sm", variant="secondary")
clear_btn = gr.Button("πŸ—‘οΈ Clear", size="sm", variant="secondary")
# RIGHT COLUMN: RESULTS (60%)
with gr.Column(scale=3):
# Agent Activity Monitor
gr.Markdown("### πŸ“‘ Agent Activity Monitor")
agent_monitor = gr.HTML(
value=generate_agent_html("System", "waiting", "Ready to analyze...", 0) +
generate_agent_html("Claude", "waiting", "Standby", 0) +
generate_agent_html("Gemini", "waiting", "Standby", 0)
)
# Results Tabs
results_tabs = gr.Tabs(visible=False)
with results_tabs:
# Tab 1: Solutions
with gr.Tab("🎯 Solutions"):
solutions_display = gr.HTML()
# Tab 2: 3D Viz
with gr.Tab("🎨 3D Visualization"):
viz_plot = gr.Plot(label="Error Graph")
# Tab 3: Raw Logs
with gr.Tab("πŸ“œ Agent Logs"):
chatbot = gr.Chatbot(
label="Conversation",
height=400,
type="messages"
)
# Voice Player (Bottom)
voice_player = gr.Group(visible=False)
with voice_player:
gr.Markdown("### πŸ”Š Audio Briefing")
audio_out = gr.Audio(interactive=False)
# --- LOGIC ---
def analyze_error(error_code, img):
# 1. Initial State
yield {
agent_monitor: generate_agent_html("System", "processing", "Initializing swarm...", 10) +
generate_agent_html("Claude", "waiting", "Queued", 0) +
generate_agent_html("Gemini", "waiting", "Queued", 0),
results_tabs: gr.update(visible=True),
voice_player: gr.update(visible=False)
}
time.sleep(1)
# 2. Claude Analysis
yield {
agent_monitor: generate_agent_html("System", "complete", "Swarm Active", 100) +
generate_agent_html("Claude", "processing", "Analyzing syntax tree...", 45) +
generate_agent_html("Gemini", "waiting", "Queued", 0)
}
time.sleep(1.5)
# 3. Gemini Analysis
yield {
agent_monitor: generate_agent_html("System", "complete", "Swarm Active", 100) +
generate_agent_html("Claude", "complete", "Analysis complete", 100) +
generate_agent_html("Gemini", "processing", "Checking documentation...", 60)
}
time.sleep(1.5)
# 4. Finalizing
yield {
agent_monitor: generate_agent_html("System", "complete", "Swarm Active", 100) +
generate_agent_html("Claude", "complete", "Analysis complete", 100) +
generate_agent_html("Gemini", "complete", "Solutions found", 100)
}
# 5. Show Results
solution_html = """
<div class="solution-card">
<div class="rank-badge">πŸ₯‡ Top Recommendation</div>
<h3>Install Missing Dependency</h3>
<p>The error <code>ModuleNotFoundError</code> indicates that <code>gradio</code> is not installed.</p>
<div class="confidence-bar-bg"><div class="confidence-bar-fill" style="width: 98%;"></div></div>
<pre style="background: #f3f4f6; padding: 10px; border-radius: 5px; margin-top: 10px;">pip install gradio</pre>
</div>
<div class="solution-card" style="border-left-color: #f59e0b;">
<div class="rank-badge" style="background: #f59e0b;">πŸ₯ˆ Alternative</div>
<h3>Check Virtual Environment</h3>
<p>Ensure you are running in the correct venv.</p>
<div class="confidence-bar-bg"><div class="confidence-bar-fill" style="width: 75%; background: #f59e0b;"></div></div>
</div>
"""
fig = create_3d_viz()
yield {
solutions_display: solution_html,
viz_plot: fig,
voice_player: gr.update(visible=True),
chatbot: [
{"role": "user", "content": "Analyze this error."},
{"role": "assistant", "content": "I've analyzed the stack trace. The root cause is a missing library."}
]
}
def clear_inputs():
return "", None
def load_example():
return """Traceback (most recent call last):
File "app.py", line 10, in <module>
import gradio as gr
ModuleNotFoundError: No module named 'gradio'""", None
# Event handlers
analyze_btn.click(
analyze_error,
inputs=[error_input, screenshot_input],
outputs=[agent_monitor, results_tabs, voice_player, solutions_display, viz_plot, chatbot]
)
clear_btn.click(
clear_inputs,
outputs=[error_input, screenshot_input]
)
example_btn.click(
load_example,
outputs=[error_input, screenshot_input]
)
return demo
if __name__ == "__main__":
demo = create_app()
# Simple launch without theme/css (already in Blocks constructor)
demo.launch(
server_name="0.0.0.0",
server_port=7860
)