import gradio as gr import openai import json import time from typing import Optional, Tuple, Dict, Any from gradio.themes.base import Base from gradio.themes.utils import colors, fonts, sizes # --- Enhanced Custom Theme --- class NordTheme(Base): def __init__(self): super().__init__( primary_hue=colors.blue, secondary_hue=colors.sky, neutral_hue=colors.slate, font=(fonts.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"), font_mono=(fonts.GoogleFont("Fira Code"), "ui-monospace", "monospace"), ) # only the supported tokens self.set( body_background_fill="#2E3440", body_text_color="#ECEFF4", block_background_fill="#3B4252", block_border_width="1px", block_border_color="#4C566A", block_label_background_fill="#434C5E", block_label_text_color="#ECEFF4", button_primary_background_fill="#5E81AC", button_primary_background_fill_hover="#81A1C1", button_primary_text_color="#ECEFF4", button_secondary_background_fill="#4C566A", button_secondary_background_fill_hover="#5A657A", button_secondary_text_color="#ECEFF4", border_color_accent="#5E81AC", block_radius="12px", ) # your CSS overrides, combining everything: css_overrides = """ /* Center the app and constrain its width */ .gradio-container { max-width: 1200px !important; margin: 0 auto !important; } /* Inputs */ .gradio-container textarea, .gradio-container input[type="text"], .gradio-container input[type="password"], .gradio-container .code-input { background: #434C5E !important; color: #ECEFF4 !important; border: none !important; border-radius: 6px !important; } /* Alerts */ .gradio-container .gr-alert-error { background-color: #BF616A !important; color: white !important; } .gradio-container .gr-alert-success { background-color: #A3BE8C !important; color: white !important; } .gradio-container .gr-alert-warning { background-color: #EBCB8B !important; color: black !important; } /* Orange “custom” alert */ .gradio-container .gr-alert-orange { background-color: #D08770 !important; color: white !important; } /* Code panels rounding */ .code-container { border-radius: 8px !important; } """ # --- Helper Functions --- # -*- coding: utf-8 -*- def sanitize_for_api(s: str) -> str: """ Turn any “smart quotes” into plain ASCII quotes (and similarly for the common apostrophes) so we never slip non-ASCII into our JSON encoder. """ return ( s .replace("\u201c", '"') .replace("\u201d", '"') .replace("\u2018", "'") .replace("\u2019", "'") ) # --- Enhanced Configuration --- PROGRAMMING_LANGUAGES = sorted([ 'Ada', 'Assembly', 'Bash', 'C', 'C#', 'C++', 'Clojure', 'COBOL', 'CSS', 'Crystal', 'Dart', 'Elixir', 'Erlang', 'F#', 'Fortran', 'Go', 'GraphQL', 'Groovy', 'Haskell', 'HTML', 'Java', 'JavaScript', 'Julia', 'Kotlin', 'Lisp', 'Lua', 'Markdown', 'MATLAB', 'Nim', 'Objective-C', 'OCaml', 'Pascal', 'Perl', 'PHP', 'PowerShell', 'Prolog', 'Python', 'R', 'Ruby', 'Rust', 'Scala', 'Scheme', 'Shell', 'SQL', 'Svelte', 'Swift', 'TOML', 'TypeScript', 'Visual Basic', 'Vue', 'XML', 'YAML', 'Zig' ]) LANGUAGES = ['Natural Language'] + PROGRAMMING_LANGUAGES # Enhanced model list with categorization MODELS = { "Code-Specialized": [ "deepseek/deepseek-coder-v2-instruct:free", "mistralai/codestral-latest:free", "codellama/codellama-70b-instruct:free", "qwen/qwen-2.5-coder-32b-instruct:free", "agentica-org/deepcoder-14b-preview:free", ], "General Purpose": [ "deepseek/deepseek-chat-v3:free", "deepseek/deepseek-r1-0528:free", "google/gemini-2.0-flash-exp:free", "meta-llama/llama-3.3-70b-instruct:free", "mistralai/mistral-small-3.2-24b-instruct-2506:free", "qwen/qwq-32b:free", ], "Experimental": [ "openrouter/cypher-alpha:free", "moonshotai/kimi-dev-72b:free", "qwen/qwen3-235b-a22b-04-28:free", ] } # Flatten models for dropdown ALL_MODELS = [] for category, models in MODELS.items(): ALL_MODELS.extend(models) DEFAULT_EXAMPLES = { "Python": """# Example: Binary search algorithm def binary_search(arr, target): left, right = 0, len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return -1 # Test the function numbers = [1, 3, 5, 7, 9, 11, 13, 15] result = binary_search(numbers, 7) print(f"Found at index: {result}")""", "JavaScript": """// Example: Async data fetching with error handling async function fetchUserData(userId) { try { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const userData = await response.json(); return userData; } catch (error) { console.error('Error fetching user data:', error); throw error; } } // Usage fetchUserData(123) .then(user => console.log('User:', user)) .catch(err => console.error('Failed to fetch user:', err));""", "Natural Language": """Create a function that implements a simple calculator with the following features: - Add, subtract, multiply, and divide two numbers - Handle division by zero errors - Return the result as a formatted string - Include input validation to ensure both inputs are numbers""" } # --- Enhanced Conversion Logic --- class ConversionHistory: """Simple in-memory history management""" def __init__(self, max_entries: int = 10): self.history = [] self.max_entries = max_entries def add_entry(self, source_lang: str, target_lang: str, source_code: str, result: str): entry = { "timestamp": time.time(), "source_lang": source_lang, "target_lang": target_lang, "source_code": source_code[:200] + "..." if len(source_code) > 200 else source_code, "result": result[:200] + "..." if len(result) > 200 else result, } self.history.insert(0, entry) if len(self.history) > self.max_entries: self.history.pop() def get_history(self) -> str: if not self.history: return "No conversion history yet." history_text = "## Recent Conversions\n\n" for i, entry in enumerate(self.history, 1): timestamp = time.strftime("%H:%M:%S", time.localtime(entry["timestamp"])) history_text += f"**{i}. {timestamp}** - {entry['source_lang']} → {entry['target_lang']}\n" history_text += f"```\n{entry['source_code']}\n```\n\n" return history_text # Global history instance conversion_history = ConversionHistory() def validate_inputs(source_code: str, source_lang: str, target_lang: str, model: str, api_key: str) -> Optional[str]: """Comprehensive input validation""" if not source_code.strip(): return "Please enter some code or a description to convert." if not api_key.strip(): return "OpenRouter API key is required." if not model or not model.strip(): return "Please select a model for the conversion." if source_lang == "Natural Language" and target_lang == "Natural Language": return "Please select a programming language for either the source or the target." if len(source_code) > 10000: return "Source code is too long. Please limit to 10,000 characters." return None def create_conversion_prompt(source_code: str, source_lang: str, target_lang: str) -> str: """Create optimized prompts for different conversion scenarios""" if source_lang == "Natural Language": return f"""You are an expert programmer. Based on the following description, write complete and functional code in {target_lang}. Requirements: - Write clean, well-structured, and documented code - Include proper error handling where appropriate - Follow {target_lang} best practices and conventions - Make the code production-ready User's request: {source_code} Respond with ONLY the raw {target_lang} code. Do not include explanations, markdown formatting, or code blocks.""" elif target_lang == "Natural Language": return f"""You are a programming expert. Explain the following {source_lang} code in clear, natural English. Please provide: 1. A brief overview of what the code does 2. Explanation of the main logic and algorithms used 3. Description of inputs and outputs 4. Any notable features or techniques used {source_lang} code to explain: ``` {source_code} ``` Provide a clear, educational explanation without including any code in your response.""" else: return f"""You are an expert programmer. Convert the following {source_lang} code to {target_lang}. Requirements: - Maintain the same functionality and logic - Follow {target_lang} best practices and conventions - Ensure the converted code is syntactically correct - Keep the same variable names where possible - Add brief comments for complex conversions {source_lang} code to convert: ``` {source_code} ``` Respond with ONLY the converted {target_lang} code. Do not include explanations, markdown formatting, or code blocks.""" def convert_code( source_code: str, source_lang: str, target_lang: str, model: str, api_key: str, temperature: float = 0.1, max_tokens: int = 4000 ) -> Tuple[str, str]: """ Enhanced conversion function with better error handling and progress tracking """ # Validate inputs validation_error = validate_inputs(source_code, source_lang, target_lang, model, api_key) if validation_error: return "", f"❌ {validation_error}" # Create client and prompt client = openai.OpenAI(base_url="https://openrouter.ai/api/v1", api_key=api_key) prompt = create_conversion_prompt(source_code, source_lang, target_lang) prompt = sanitize_for_api(prompt) try: # Make the API call completion = client.chat.completions.create( model=model, messages=[{"role": "user", "content": prompt}], temperature=temperature, max_tokens=max_tokens, stream=False ) result = completion.choices[0].message.content.strip() # Add to history conversion_history.add_entry(source_lang, target_lang, source_code, result) # Return result with success message success_msg = f"✅ Successfully converted from {source_lang} to {target_lang}" return result, success_msg except openai.AuthenticationError: return "", "❌ Authentication failed. Please check your OpenRouter API key." except openai.RateLimitError: return "", "❌ Rate limit exceeded. Please try again in a moment." except openai.APIError as e: return "", f"❌ API error: {str(e)}" except Exception as e: return "", f"❌ Unexpected error: {str(e)}" # --- Enhanced UI Helper Functions --- def update_code_language(lang: str) -> Dict[str, Any]: """Updates the Code component's language and placeholder text""" if lang == "Natural Language": return gr.update( language="text", placeholder="Describe the code you want here...", value=DEFAULT_EXAMPLES.get("Natural Language", "") ) example_code = DEFAULT_EXAMPLES.get(lang, f"# Enter your {lang} code here...") return gr.update( language=lang.lower(), placeholder=f"Enter your {lang} code here...", value=example_code ) def update_target_language(lang: str) -> Dict[str, Any]: """Updates the target code display language""" if lang == "Natural Language": return gr.update(language="text", placeholder="Explanation will appear here...") return gr.update(language=lang.lower(), placeholder="Converted code will appear here...") def swap_languages(source_lang: str, target_lang: str, source_code: str, target_code: str) -> Tuple[str, str, str, str]: """Swap source and target languages with their code""" return target_lang, source_lang, target_code, source_code def clear_all() -> Tuple[str, str, str]: """Clear all input and output fields""" return "", "", "Ready to convert!" def get_conversion_history() -> str: """Get formatted conversion history""" return conversion_history.get_history() # --- Enhanced Gradio Interface --- def create_header(): """Create an enhanced header with better styling""" return gr.HTML( """
Advanced Code & Natural Language Converter
🚀 Powered by OpenRouter • Built with Gradio • Get API Key
Always review generated code before use in production