""" SuperCoder - Hugging Face Spaces Frontend (FIXED) Connects to your local API server via tunnel """ import gradio as gr import requests from typing import List, Tuple import os # ============================================================================ # Configuration - YOUR TUNNEL URL # ============================================================================ # The API_URL is pulled from a Space Secret for better security API_URL = os.getenv("API_URL", "https://your-tunnel-url.ngrok-free.dev") API_URL = API_URL.rstrip('/') # ============================================================================ # API Client Functions # ============================================================================ def call_api(message: str, temperature: float = 0.1, max_tokens: int = 512) -> str: """Call the remote API with error handling""" if not message or not message.strip(): return "⚠️ Please enter a message" try: response = requests.post( f"{API_URL}/api/chat", json={ "messages": [{"role": "user", "content": message}], "temperature": temperature, "max_tokens": max_tokens }, timeout=90, headers={ "Content-Type": "application/json", "ngrok-skip-browser-warning": "true" } ) if response.status_code == 200: result = response.json() return result.get("response", "No response from API") elif response.status_code == 503: return "🔧 Backend service unavailable. Please ensure your local server is running." else: return f"❌ API Error ({response.status_code}): {response.text[:200]}" except requests.exceptions.Timeout: return "⏱️ Request timed out. The model might be processing a complex request or the server is down." except requests.exceptions.ConnectionError: return f"🔌 Cannot connect to API at {API_URL}. Please verify:\n1. Local server is running\n2. Tunnel (ngrok/cloudflare) is active\n3. API_URL is correct" except Exception as e: return f"⚠️ Unexpected error: {str(e)}" def check_api_status() -> str: """Check if the API is reachable and healthy""" try: response = requests.get( f"{API_URL}/health", timeout=10, # Increased timeout slightly for cold starts headers={"ngrok-skip-browser-warning": "true"} ) if response.status_code == 200: data = response.json() status = data.get("status", "unknown") if status == "ok": return "✅ Connected - Backend Ready" else: return f"⚠️ Connected but status: {status}" else: return f"❌ API returned status {response.status_code}" except requests.exceptions.ConnectionError: return f"🔴 Cannot reach {API_URL} - Check tunnel status" except requests.exceptions.Timeout: return "⏱️ Health check timed out" except Exception as e: return f"❌ Error: {str(e)}" # ============================================================================ # Gradio Interface # ============================================================================ def respond(message: str, history: List[Tuple[str, str]], temperature: float, max_tokens: int): """Handle chat responses""" history.append((message, None)) yield history # Show user message immediately bot_response = call_api(message, temperature, max_tokens) history[-1] = (message, bot_response) yield history def apply_template(template: str, history: List[Tuple[str, str]]) -> tuple: """Apply a code template""" templates = { "Explain Code": "Please explain the following code in detail:\n```python\n# Paste your code here\n```", "Debug Code": "I have a bug in my code. Can you help me debug it?\n```python\n# Paste your buggy code here\n```", "Write Function": "Please write a Python function that: [describe what you need]", "Optimize Code": "Can you optimize this code for better performance?\n```python\n# Paste your code here\n```", "Add Comments": "Please add clear comments to this code:\n```python\n# Paste your code here\n```" } return templates.get(template, ""), history # Create the Gradio interface with gr.Blocks( title="SuperCoder Pro", theme=gr.themes.Soft(primary_hue="indigo"), css=".gradio-container {max-width: 1200px !important}" ) as demo: gr.Markdown( """ # 🤖 SuperCoder Pro ### AI-Powered Coding Assistant > **Note:** This interface connects to a local backend via a secure tunnel. > Ensure your local server and tunnel are running. """ ) # Status bar with gr.Row(): with gr.Column(scale=4): # --- FIX ---: Set a static default value here status_display = gr.Textbox( value="⏳ Initializing...", label="🔌 Backend Status", interactive=False, show_copy_button=True ) with gr.Column(scale=1): refresh_btn = gr.Button("🔄 Refresh Status", size="sm") # Main chat interface with gr.Row(): with gr.Column(scale=3): chatbot = gr.Chatbot( label="💬 Conversation", height=500, show_copy_button=True, avatar_images=(None, "🤖"), bubble_full_width=False ) with gr.Row(): msg_input = gr.Textbox( placeholder="Ask me to write, explain, debug, or review code...", scale=5, lines=2, show_label=False, autofocus=True, container=False ) send_btn = gr.Button("Send 🚀", scale=1, variant="primary") # Settings sidebar with gr.Column(scale=1): gr.Markdown("### ⚙️ Model Settings") temperature = gr.Slider(0.0, 1.0, value=0.1, step=0.05, label="🌡️ Temperature") max_tokens = gr.Slider(128, 4096, value=1024, step=128, label="📏 Max Tokens") gr.Markdown("---") gr.Markdown("### 🎯 Quick Templates") template_dropdown = gr.Dropdown( choices=["Explain Code", "Debug Code", "Write Function", "Optimize Code", "Add Comments"], label="Select Template", value="Explain Code" ) use_template_btn = gr.Button("📝 Use Template", size="sm") clear_btn = gr.Button("🗑️ Clear Chat", variant="stop", size="sm") gr.Markdown("---") gr.Markdown(f"""### 📡 Connection Info\n**API Endpoint:**\n`{API_URL}`""") # Event handlers # --- FIX ---: Use the demo.load() event to check status after UI is ready demo.load(check_api_status, outputs=[status_display]) refresh_btn.click(check_api_status, outputs=[status_display]) msg_submit_event = msg_input.submit( respond, inputs=[msg_input, chatbot, temperature, max_tokens], outputs=[chatbot] ) msg_submit_event.then(lambda: gr.update(value=""), outputs=[msg_input]) send_btn.click( respond, inputs=[msg_input, chatbot, temperature, max_tokens], outputs=[chatbot] ).then(lambda: gr.update(value=""), outputs=[msg_input]) use_template_btn.click(apply_template, inputs=[template_dropdown, chatbot], outputs=[msg_input, chatbot]) clear_btn.click(lambda: [], outputs=[chatbot]) # ============================================================================ # Launch Configuration for HF Spaces # ============================================================================ if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860, show_error=True )