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

CodeVerter Pro

Advanced Code & Natural Language Converter

""" ) def create_footer(): """Create an enhanced footer""" return gr.HTML( """

🚀 Powered by OpenRouter • Built with Gradio • Get API Key

Always review generated code before use in production

""" ) # --- Main Application --- with gr.Blocks( theme=NordTheme(), css=css_overrides, title="CodeVerter Pro" ) as app: # Header create_header() # Configuration Section with gr.Accordion("⚙️ Configuration", open=True): with gr.Row(): with gr.Column(scale=2): openrouter_key = gr.Textbox( label="🔑 OpenRouter API Key", placeholder="Enter your OpenRouter API key...", type="password", info="Get your free API key from openrouter.ai" ) with gr.Column(scale=2): model_selection = gr.Dropdown( label="🤖 Model Selection", choices=ALL_MODELS, value=ALL_MODELS[0] if ALL_MODELS else None, allow_custom_value=True, info="Choose a model optimized for your task" ) with gr.Column(scale=1): temperature = gr.Slider( minimum=0.0, maximum=1.0, step=0.1, value=0.1, label="🌡️ Temperature", info="Controls randomness" ) # Main Conversion Interface with gr.Row(equal_height=True): with gr.Column(scale=1): gr.Markdown("### 📝 Source") source_lang_selection = gr.Dropdown( label="Source Language", choices=LANGUAGES, value="Python", info="Select the language of your input" ) source_code_input = gr.Code( label="Source Code/Description", language="python", value=DEFAULT_EXAMPLES["Python"], lines=20, show_label=False ) with gr.Column(scale=1): gr.Markdown("### 🎯 Target") target_lang_selection = gr.Dropdown( label="Target Language", choices=LANGUAGES, value="JavaScript", info="Select the desired output language" ) target_code_output = gr.Code( label="Converted Code/Explanation", language="javascript", lines=20, interactive=False, show_label=False ) # Action Buttons with gr.Row(): convert_button = gr.Button("🔄 Convert", variant="primary", scale=2) swap_button = gr.Button("🔀 Swap Languages", variant="secondary", scale=1) clear_button = gr.Button("🗑️ Clear All", variant="secondary", scale=1) # Status and History with gr.Row(): with gr.Column(scale=2): status_display = gr.Textbox( label="Status", value="Ready to convert!", interactive=False, show_label=False ) with gr.Column(scale=1): history_button = gr.Button("📋 View History", variant="secondary") # History Modal with gr.Accordion("📋 Conversion History", open=False) as history_accordion: history_display = gr.Markdown("No conversions yet.") # Event Handlers source_lang_selection.change( fn=update_code_language, inputs=source_lang_selection, outputs=source_code_input ) target_lang_selection.change( fn=update_target_language, inputs=target_lang_selection, outputs=target_code_output ) convert_button.click( fn=convert_code, inputs=[ source_code_input, source_lang_selection, target_lang_selection, model_selection, openrouter_key, temperature ], outputs=[target_code_output, status_display], api_name="convert" ) swap_button.click( fn=swap_languages, inputs=[source_lang_selection, target_lang_selection, source_code_input, target_code_output], outputs=[source_lang_selection, target_lang_selection, source_code_input, target_code_output] ) clear_button.click( fn=clear_all, outputs=[source_code_input, target_code_output, status_display] ) history_button.click( fn=get_conversion_history, outputs=history_display ) # Footer create_footer() # --- Launch Configuration --- if __name__ == "__main__": app.launch( server_name="0.0.0.0", server_port=7860, share=False, debug=False, show_error=True, quiet=False )