File size: 8,078 Bytes
f22daae
 
 
 
 
 
 
 
 
 
 
51d8a3f
f22daae
51d8a3f
 
f22daae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1561904
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
import os
from typing import Dict, List, Optional, Tuple

import gradio as gr

from config import (
    AVAILABLE_MODELS, DEMO_LIST, HTML_SYSTEM_PROMPT
)
from api_clients import generation_code, tavily_client
from chat_processing import (
    clear_history, history_to_chatbot_messages, update_image_input_visibility,
    get_gradio_language, send_to_sandbox,
)
from file_processing import create_multimodal_message
from web_extraction import enhance_query_with_search


def demo_card_click(e: gr.EventData):
    try:
        # Get the index from the event data
        if hasattr(e, '_data') and e._data:
            # Try different ways to get the index
            if 'index' in e._data:
                index = e._data['index']
            elif 'component' in e._data and 'index' in e._data['component']:
                index = e._data['component']['index']
            elif 'target' in e._data and 'index' in e._data['target']:
                index = e._data['target']['index']
            else:
                # If we can't get the index, try to extract it from the card data
                index = 0
        else:
            index = 0
        
        # Ensure index is within bounds
        if index >= len(DEMO_LIST):
            index = 0
            
        return DEMO_LIST[index]['description']
    except (KeyError, IndexError, AttributeError) as e:
        # Return the first demo description as fallback
        return DEMO_LIST[0]['description']

# Main application
with gr.Blocks(
    theme=gr.themes.Base(
        primary_hue="blue",
        secondary_hue="gray",
        neutral_hue="gray",
        font=gr.themes.GoogleFont("Inter"),
        font_mono=gr.themes.GoogleFont("JetBrains Mono"),
        text_size=gr.themes.sizes.text_md,
        spacing_size=gr.themes.sizes.spacing_md,
        radius_size=gr.themes.sizes.radius_md
    ),
    title="AnyCoder - AI Code Generator"
) as demo:
    history = gr.State([])
    setting = gr.State({
        "system": HTML_SYSTEM_PROMPT,
    })
    current_model = gr.State(AVAILABLE_MODELS[0])  # Moonshot Kimi-K2
    open_panel = gr.State(None)
    last_login_state = gr.State(None)
    with gr.Sidebar():
        input = gr.Textbox(
            label="What would you like to build?",
            placeholder="Describe your application...",
            lines=3,
            visible=True  # Always visible
        )
        # Language dropdown for code generation
        language_choices = [
            "python", "c", "cpp", "markdown", "latex", "json", "html", "css", "javascript", "jinja2", "typescript", "yaml", "dockerfile", "shell", "r", "sql", "sql-msSQL", "sql-mySQL", "sql-mariaDB", "sql-sqlite", "sql-cassandra", "sql-plSQL", "sql-hive", "sql-pgSQL", "sql-gql", "sql-gpSQL", "sql-sparkSQL", "sql-esper"
        ]
        language_dropdown = gr.Dropdown(
            choices=language_choices,
            value="html",
            label="Code Language",
            visible=True  # Always visible
        )
        website_url_input = gr.Textbox(
            label="Website URL for redesign",
            placeholder="https://example.com",
            lines=1,
            visible=True  # Always visible
        )
        file_input = gr.File(
            label="Reference file",
            file_types=[".pdf", ".txt", ".md", ".csv", ".docx", ".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".tif", ".gif", ".webp"],
            visible=True  # Always visible
        )
        image_input = gr.Image(
            label="UI design image",
            visible=False  # Hidden by default; shown only for ERNIE-VL or GLM-VL
        )
        with gr.Row():
            btn = gr.Button("Generate", variant="primary", size="lg", scale=2, visible=True)  # Always visible
            clear_btn = gr.Button("Clear", variant="secondary", size="sm", scale=1, visible=True)  # Always visible
        search_toggle = gr.Checkbox(
            label="πŸ” Web search",
            value=False,
            visible=True  # Always visible
        )
        model_dropdown = gr.Dropdown(
            choices=[model['name'] for model in AVAILABLE_MODELS],
            value=AVAILABLE_MODELS[0]['name'],  # Moonshot Kimi-K2
            label="Model",
            visible=True  # Always visible
        )
        gr.Markdown("**Quick start**", visible=True)
        with gr.Column(visible=True) as quick_examples_col:
            for i, demo_item in enumerate(DEMO_LIST[:3]):
                demo_card = gr.Button(
                    value=demo_item['title'], 
                    variant="secondary",
                    size="sm"
                )
                demo_card.click(
                    fn=lambda idx=i: gr.update(value=DEMO_LIST[idx]['description']),
                    outputs=input
                )
        if not tavily_client:
            gr.Markdown("⚠️ Web search unavailable", visible=True)
        else:
            gr.Markdown("βœ… Web search available", visible=True)
        model_display = gr.Markdown(f"**Model:** {AVAILABLE_MODELS[0]['name']}", visible=True)  # Moonshot Kimi-K2
        def on_model_change(model_name):
            for m in AVAILABLE_MODELS:
                if m['name'] == model_name:
                    return m, f"**Model:** {m['name']}", update_image_input_visibility(m)
            return AVAILABLE_MODELS[0], f"**Model:** {AVAILABLE_MODELS[0]['name']}", update_image_input_visibility(AVAILABLE_MODELS[0])  # Moonshot Kimi-K2 fallback
        def save_prompt(input):
            return {setting: {"system": input}}
        model_dropdown.change(
            on_model_change,
            inputs=model_dropdown,
            outputs=[current_model, model_display, image_input]
        )
        with gr.Accordion("Advanced", open=False, visible=True) as advanced_accordion:
            systemPromptInput = gr.Textbox(
                value=HTML_SYSTEM_PROMPT,
                label="System prompt",
                lines=5
            )
            save_prompt_btn = gr.Button("Save", variant="primary", size="sm")
            save_prompt_btn.click(save_prompt, inputs=systemPromptInput, outputs=setting)

    with gr.Column():
        with gr.Tabs():
            with gr.Tab("Code"):
                code_output = gr.Code(
                    language="html", 
                    lines=25, 
                    interactive=False,
                    label="Generated code"
                )
            with gr.Tab("Preview"):
                sandbox = gr.HTML(label="Live preview")
            with gr.Tab("History"):
                history_output = gr.Chatbot(show_label=False, height=400, type="messages")

    # Event handlers
    def update_code_language(language):
        return gr.update(language=get_gradio_language(language))

    language_dropdown.change(update_code_language, inputs=language_dropdown, outputs=code_output)

    def preview_logic(code, language):
        if language == "html":
            return send_to_sandbox(code)
        else:
            return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"

    btn.click(
        generation_code,
        inputs=[input, image_input, file_input, website_url_input, setting, history, current_model, search_toggle, language_dropdown],
        outputs=[code_output, history, sandbox, history_output]
    )
    # Update preview when code or language changes
    code_output.change(preview_logic, inputs=[code_output, language_dropdown], outputs=sandbox)
    language_dropdown.change(preview_logic, inputs=[code_output, language_dropdown], outputs=sandbox)
    clear_btn.click(clear_history, outputs=[history, history_output, file_input, website_url_input])

if __name__ == "__main__":
    demo.queue(api_open=False, default_concurrency_limit=20).launch(ssr_mode=True, mcp_server=False, show_api=False)