""" 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"""
{icon}
{agent_name}
{message}
""" 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("""

DebugGenie 🧞

Multi-Agent AI Debugging Assistant

🤖 Powered by Claude • Gemini • GPT-4 🎨 3D Visualization 🔊 Voice Explanations
""") # 2. STATS BAR gr.HTML("""
🤖 3 AI Agents Active
🔧 5 MCP Tools Connected
⚡ Real-time Analysis Ready
""") # 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 = """
🥇 Top Recommendation

Install Missing Dependency

The error ModuleNotFoundError indicates that gradio is not installed.

pip install gradio
🥈 Alternative

Check Virtual Environment

Ensure you are running in the correct venv.

""" 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 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 )