File size: 7,025 Bytes
20718fa
 
0db2f97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20718fa
 
 
 
 
 
0db2f97
20718fa
 
0db2f97
 
 
 
 
 
 
 
 
20718fa
 
 
 
 
 
 
 
 
 
 
 
0db2f97
20718fa
 
 
 
 
0db2f97
 
20718fa
0db2f97
20718fa
 
 
 
 
 
 
 
 
 
 
0db2f97
 
20718fa
0db2f97
20718fa
0db2f97
20718fa
0db2f97
20718fa
 
 
0db2f97
20718fa
0db2f97
 
 
 
 
 
 
20718fa
0db2f97
 
 
20718fa
0db2f97
20718fa
 
 
0db2f97
20718fa
 
 
0db2f97
20718fa
0db2f97
 
20718fa
 
 
 
 
0db2f97
 
20718fa
0db2f97
 
20718fa
0db2f97
 
 
20718fa
 
0db2f97
20718fa
 
0db2f97
20718fa
 
 
 
 
 
0db2f97
 
 
20718fa
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import gradio as gr
import openai
from gradio.themes.base import Base
from gradio.themes.utils import colors, fonts, sizes

# --- Custom Theme Definition ---

class NordTheme(Base):
    """
    A custom Gradio theme inspired by the Nord color palette.
    """
    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"),
        )
        self.set(
            # Color Palette
            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",
            
            input_background_fill="#434C5E",
            input_border_color="transparent",
            input_text_color="#ECEFF4",
            
            # Button Styles
            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",
            
            # Other Elements
            border_color_accent="#5E81AC",
            background_fill_primary_dark="#2E3440",
            color_accent_soft="#4c566a",
            
            # Sizing
            radius_sm=sizes.radius_sm,
            radius_md=sizes.radius_md,
            radius_lg=sizes.radius_lg,
            block_radius="12px",
            button_radius="8px",
        )

# --- UI Configuration ---

LANGUAGES = [
    'Python', 'JavaScript', 'TypeScript', 'Java', 'C++', 'C#', 'C', 'Go', 
    'Rust', 'Swift', 'Kotlin', 'PHP', 'Ruby', 'Scala', 'R', 'MATLAB', 
    'Perl', 'Haskell', 'Lua', 'Dart', 'Elixir', 'F#', 'Clojure', 'SQL'
]

MODELS = sorted([
    "agentica-org/deepcoder-14b-preview:free", "deepseek/deepseek-chat-v3:free",
    "deepseek/deepseek-r1-0528:free", "google/gemma-3-27b-it:free",
    "google/gemini-2.0-flash-exp:free", "meta-llama/llama-3.3-70b-instruct:free",
    "mistralai/devstral-small-2505:free", "mistralai/mistral-small-3.2-24b-instruct-2506:free",
    "moonshotai/kimi-dev-72b:free", "openrouter/cypher-alpha:free",
    "qwen/qwen-2.5-coder-32b-instruct:free", "qwen/qwen3-235b-a22b-04-28:free",
    "qwen/qwq-32b:free",
])

DEFAULT_SOURCE_CODE = """# Example Python code
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))"""

# --- Core Conversion Logic ---

def convert_code(
    source_code: str, source_lang: str, target_lang: str, model: str, api_key: str
):
    if not source_code.strip():
        raise gr.Error("Please enter some code to convert.")
    if not api_key.strip():
        raise gr.Error("OpenRouter API key is required.")
    if not model or not model.strip():
        raise gr.Error("Please select or enter a model for the conversion.")

    client = openai.OpenAI(base_url="https://openrouter.ai/api/v1", api_key=api_key)
    prompt = (
        f"You are an expert programmer. Convert the following {source_lang} code "
        f"to {target_lang}. Your response should only contain the raw, converted code. "
        "Do not include any explanations, markdown formatting (like ```), or extra text."
        f"\n\n--- Start of {source_lang} Code ---\n"
        f"{source_code}\n"
        f"--- End of {source_lang} Code ---"
    )
    try:
        completion = client.chat.completions.create(
            model=model,
            messages=[{"role": "user", "content": prompt}],
            temperature=0.1, max_tokens=2048
        )
        return completion.choices[0].message.content.strip()
    except openai.AuthenticationError:
        raise gr.Error("Authentication failed. Check your OpenRouter API key.")
    except Exception as e:
        raise gr.Error(f"An error occurred: {e}")

# --- Gradio User Interface ---

with gr.Blocks(theme=NordTheme()) as app:
    # Header
    gr.HTML(
        """
        <div style="display: flex; align-items: center; gap: 12px; padding: 10px;">
            <svg xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#81A1C1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 16 4-4-4-4"/><path d="m6 8-4 4 4 4"/><path d="m14.5 4-5 16"/></svg>
            <div>
                <h1 style="font-size: 1.5rem; font-weight: 700; color: #ECEFF4; margin: 0;">CodeVerter</h1>
                <p style="font-size: 0.875rem; color: #D8DEE9; margin: 0;">Programming Language Converter via OpenRouter</p>
            </div>
        </div>
        """
    )

    # Configuration Accordion
    with gr.Accordion("⚙️ Configuration", open=True):
        openrouter_key = gr.Textbox(
            label="OpenRouter API Key",
            placeholder="Enter your OpenRouter API key...",
            type="password",
        )
        model_selection = gr.Dropdown(
            label="Select or Enter a Model Name",
            choices=MODELS,
            value=MODELS[0] if MODELS else None,
            allow_custom_value=True,
        )

    # Main conversion interface
    with gr.Row(equal_height=False):
        with gr.Column(scale=1):
            source_lang_selection = gr.Dropdown(label="Source Language", choices=LANGUAGES, value="Python")
            source_code_input = gr.Code(label="Source Code", language="python", value=DEFAULT_SOURCE_CODE, lines=15)
        with gr.Column(scale=1):
            target_lang_selection = gr.Dropdown(label="Target Language", choices=LANGUAGES, value="JavaScript")
            target_code_output = gr.Code(label="Converted Code", language="javascript", lines=15, interactive=False)
    
    # Sync language highlighting with dropdowns
    source_lang_selection.change(lambda x: gr.update(language=x.lower()), inputs=source_lang_selection, outputs=source_code_input)
    target_lang_selection.change(lambda x: gr.update(language=x.lower()), inputs=target_lang_selection, outputs=target_code_output)

    # Convert button and action
    convert_button = gr.Button("Convert Code", variant="primary", scale=1)
    convert_button.click(
        fn=convert_code,
        inputs=[source_code_input, source_lang_selection, target_lang_selection, model_selection, openrouter_key],
        outputs=target_code_output,
        api_name="convert"
    )

    # Footer
    gr.HTML(
        """<div style="text-align: center; margin-top: 24px; color: #a0aec0; font-size: 0.875rem;">
        <p>CodeVerter uses LLMs via OpenRouter. Results may require manual review.</p>
        </div>"""
    )

if __name__ == "__main__":
    app.launch()