File size: 8,538 Bytes
20718fa
 
0db2f97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d3141a7
 
 
 
 
0db2f97
20718fa
 
 
d3141a7
 
 
 
 
 
 
 
 
 
 
20718fa
0db2f97
 
 
 
 
 
 
 
 
20718fa
 
 
 
 
 
 
 
 
 
 
 
0db2f97
20718fa
cd4b4ee
 
 
 
 
 
20718fa
cd4b4ee
20718fa
 
0db2f97
 
d3141a7
cd4b4ee
 
20718fa
0db2f97
cd4b4ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d3141a7
20718fa
 
 
0db2f97
 
20718fa
0db2f97
20718fa
0db2f97
20718fa
0db2f97
20718fa
 
 
cd4b4ee
d3141a7
cd4b4ee
 
 
 
0db2f97
 
 
 
cd4b4ee
0db2f97
 
cd4b4ee
20718fa
0db2f97
 
 
20718fa
 
cd4b4ee
 
20718fa
 
 
0db2f97
cd4b4ee
20718fa
0db2f97
cd4b4ee
d3141a7
cd4b4ee
 
20718fa
cd4b4ee
20718fa
 
0db2f97
20718fa
 
 
 
 
0db2f97
cd4b4ee
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
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(
            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",
            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",
            background_fill_primary_dark="#2E3440",
            color_accent_soft="#4c566a",
            block_radius="12px",
            # The invalid 'button_radius' argument has been removed.
            # Button radius is now controlled by the properties below.
            radius_sm=sizes.radius_sm,
            radius_md=sizes.radius_md,
            radius_lg=sizes.radius_lg,
        )

# --- UI Configuration ---

PROGRAMMING_LANGUAGES = sorted([
    'Ada', 'Assembly', 'Bash', 'C', 'C#', 'C++', 'Clojure', 'COBOL', 'CSS',
    'Crystal', 'Dart', 'Elixir', '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',
    'SQL', 'Svelte', 'Swift', 'TOML', 'TypeScript', 'Visual Basic', 'Vue',
    'XML', 'YAML', 'Zig'
])
LANGUAGES = ['Natural Language'] + PROGRAMMING_LANGUAGES


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
):
    """
    Handles three conversion scenarios:
    1. Natural Language -> Code
    2. Code -> Natural Language
    3. Code -> Code
    """
    if not source_code.strip():
        raise gr.Error("Please enter some code or a description 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.")

    if source_lang == "Natural Language" and target_lang == "Natural Language":
        raise gr.Error("Please select a programming language for either the source or the target.")

    client = openai.OpenAI(base_url="https://openrouter.ai/api/v1", api_key=api_key)

    if source_lang == "Natural Language":
        prompt = (
            f"You are a programming expert. Based on the following description, write a complete and functional code snippet in {target_lang}. "
            f"The user's request is: '{source_code}'.\n\n"
            f"Your response must only contain the raw {target_lang} code without any explanations, comments, or markdown formatting (like ```)."
        )
    elif target_lang == "Natural Language":
        prompt = (
            f"You are a programming expert. Explain the following {source_lang} code in simple, natural English. "
            f"Describe what the code does, its main logic, its inputs, and what it outputs. Do not include any code in your explanation.\n\n"
            f"--- Start of {source_lang} Code ---\n"
            f"{source_code}\n"
            f"--- End of {source_lang} Code ---"
        )
    else:
        prompt = (
            f"You are an expert programmer. Convert the following {source_lang} code to {target_lang}. "
            "Your response must only contain the raw, converted code. Do not include any explanations, comments, or markdown formatting (like ```)."
            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 ---

def update_code_language(lang: str):
    """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...")
    return gr.update(language=lang.lower(), placeholder=f"Enter your {lang} code here...")

with gr.Blocks(theme=NordTheme()) as app:
    gr.HTML(
        """
        <div style="display: flex; align-items: center; gap: 12px; padding: 10px;">
            <svg xmlns="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;">Code & Natural Language Converter</p>
            </div>
        </div>
        """
    )

    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)

    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", 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="Result", language="javascript", lines=15, interactive=False)

    source_lang_selection.change(fn=update_code_language, inputs=source_lang_selection, outputs=source_code_input)
    target_lang_selection.change(lambda lang: gr.update(language=lang.lower() if lang != "Natural Language" else "text"), inputs=target_lang_selection, outputs=target_code_output)

    convert_button = gr.Button("Convert", 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"
    )

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

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