|
import os |
|
import uuid |
|
import base64 |
|
import tempfile |
|
from typing import Dict, List, Optional, Tuple, Union |
|
|
|
import gradio as gr |
|
|
|
|
|
from config import ( |
|
AVAILABLE_MODELS, DEFAULT_MODEL, THEME_CONFIGS, DEMO_LIST, |
|
HTML_SYSTEM_PROMPT, get_saved_theme, save_theme_preference, get_gradio_language |
|
) |
|
from utils import ( |
|
get_inference_client, remove_code_block, extract_text_from_file, |
|
create_multimodal_message, apply_search_replace_changes, |
|
cleanup_all_temp_media, reap_old_media, process_image_for_model |
|
) |
|
from web_utils import extract_website_content, enhance_query_with_search |
|
from media_generation import ( |
|
generate_image_with_qwen, generate_image_to_image, generate_video_from_image, |
|
generate_video_from_text, generate_music_from_text |
|
) |
|
from code_processing import ( |
|
is_streamlit_code, is_gradio_code, extract_html_document, |
|
parse_transformers_js_output, format_transformers_js_output, build_transformers_inline_html, |
|
parse_svelte_output, format_svelte_output, |
|
parse_multipage_html_output, format_multipage_output, |
|
validate_and_autofix_files, inline_multipage_into_single_preview, |
|
apply_generated_media_to_html |
|
) |
|
|
|
|
|
current_theme_name = get_saved_theme() |
|
current_theme = THEME_CONFIGS[current_theme_name]["theme"] |
|
|
|
class AnyCoder: |
|
"""Main AnyCoder application class""" |
|
|
|
def __init__(self): |
|
self.setup_cleanup() |
|
|
|
def setup_cleanup(self): |
|
"""Setup cleanup handlers""" |
|
cleanup_all_temp_media() |
|
reap_old_media() |
|
|
|
def create_advanced_ui(self): |
|
"""Create the advanced professional UI""" |
|
|
|
with gr.Blocks( |
|
title="AnyCoder - Professional AI Development Suite", |
|
theme=current_theme, |
|
css=self.get_custom_css(), |
|
head=self.get_head_html() |
|
) as app: |
|
|
|
history = gr.State([]) |
|
setting = gr.State({"system": HTML_SYSTEM_PROMPT}) |
|
current_model = gr.State(DEFAULT_MODEL) |
|
session_state = gr.State({}) |
|
|
|
|
|
with gr.Row(elem_classes=["header-row"]): |
|
with gr.Column(scale=3): |
|
gr.HTML(""" |
|
<div class="app-header"> |
|
<div class="header-content"> |
|
<div class="logo-section"> |
|
<div class="logo">β‘</div> |
|
<div class="app-title"> |
|
<h1>AnyCoder</h1> |
|
<p>Professional AI Development Suite</p> |
|
</div> |
|
</div> |
|
<div class="status-indicators"> |
|
<div class="status-item"> |
|
<span class="status-dot active"></span> |
|
<span>AI Models Ready</span> |
|
</div> |
|
<div class="status-item"> |
|
<span class="status-dot active"></span> |
|
<span>Web Search Available</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
""") |
|
|
|
with gr.Column(scale=1, min_width=200): |
|
with gr.Row(): |
|
login_button = gr.LoginButton(scale=1, size="sm") |
|
theme_selector = gr.Dropdown( |
|
choices=list(THEME_CONFIGS.keys()), |
|
value=current_theme_name, |
|
label="Theme", |
|
scale=1, |
|
container=False |
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
|
with gr.Column(scale=1, elem_classes=["sidebar"]): |
|
self.create_sidebar(current_model, session_state) |
|
|
|
|
|
with gr.Column(scale=3, elem_classes=["main-content"]): |
|
self.create_main_content(history, current_model) |
|
|
|
|
|
self.setup_event_handlers(app, history, setting, current_model, session_state) |
|
|
|
return app |
|
|
|
def create_sidebar(self, current_model, session_state): |
|
"""Create the professional sidebar""" |
|
|
|
|
|
with gr.Group(elem_classes=["control-group"]): |
|
gr.HTML('<div class="group-title">π€ AI Model</div>') |
|
|
|
model_dropdown = gr.Dropdown( |
|
choices=[f"{model['name']} ({model['category']})" for model in AVAILABLE_MODELS], |
|
value=f"{DEFAULT_MODEL['name']} ({DEFAULT_MODEL['category']})", |
|
label="Select Model", |
|
info="Choose your AI model based on task requirements", |
|
container=False |
|
) |
|
|
|
|
|
model_info = gr.HTML(self.get_model_info_html(DEFAULT_MODEL)) |
|
|
|
|
|
with gr.Group(elem_classes=["control-group"]): |
|
gr.HTML('<div class="group-title">βοΈ Project Settings</div>') |
|
|
|
language_dropdown = gr.Dropdown( |
|
choices=[ |
|
("Static HTML", "html"), |
|
("Streamlit App", "streamlit"), |
|
("Gradio App", "gradio"), |
|
("Transformers.js", "transformers.js"), |
|
("Svelte App", "svelte"), |
|
("Python Script", "python"), |
|
("JavaScript", "javascript"), |
|
("CSS Styles", "css"), |
|
("Other", "other") |
|
], |
|
value="html", |
|
label="Project Type", |
|
container=False |
|
) |
|
|
|
with gr.Row(): |
|
search_toggle = gr.Checkbox( |
|
label="Web Search", |
|
value=False, |
|
info="Enable real-time web search" |
|
) |
|
advanced_mode = gr.Checkbox( |
|
label="Advanced Mode", |
|
value=False, |
|
info="Show advanced options" |
|
) |
|
|
|
|
|
with gr.Group(elem_classes=["control-group"]): |
|
gr.HTML('<div class="group-title">π Input Sources</div>') |
|
|
|
file_input = gr.File( |
|
label="Upload Reference File", |
|
file_types=[".pdf", ".txt", ".md", ".csv", ".docx", ".jpg", ".jpeg", ".png"], |
|
container=False |
|
) |
|
|
|
website_url_input = gr.Textbox( |
|
label="Website URL (for redesign)", |
|
placeholder="https://example.com", |
|
container=False |
|
) |
|
|
|
image_input = gr.Image( |
|
label="Design Reference Image", |
|
visible=False, |
|
container=False |
|
) |
|
|
|
|
|
with gr.Group(elem_classes=["control-group"], visible=False) as advanced_controls: |
|
gr.HTML('<div class="group-title">π¨ Media Generation</div>') |
|
|
|
with gr.Row(): |
|
enable_images = gr.Checkbox(label="Images", value=False, scale=1) |
|
enable_videos = gr.Checkbox(label="Videos", value=False, scale=1) |
|
enable_music = gr.Checkbox(label="Music", value=False, scale=1) |
|
|
|
media_prompts = gr.Textbox( |
|
label="Media Generation Prompts", |
|
placeholder="Describe media to generate...", |
|
lines=2, |
|
visible=False, |
|
container=False |
|
) |
|
|
|
|
|
with gr.Group(elem_classes=["control-group"]): |
|
gr.HTML('<div class="group-title">π Quick Start</div>') |
|
|
|
example_gallery = gr.Gallery( |
|
value=[(None, demo["title"]) for demo in DEMO_LIST[:6]], |
|
label="Example Projects", |
|
show_label=False, |
|
elem_classes=["example-gallery"], |
|
columns=2, |
|
rows=3, |
|
height="auto", |
|
container=False |
|
) |
|
|
|
|
|
with gr.Group(elem_classes=["control-group"]): |
|
gr.HTML('<div class="group-title">π₯ Import Project</div>') |
|
|
|
import_url = gr.Textbox( |
|
label="GitHub/HuggingFace URL", |
|
placeholder="https://github.com/user/repo or https://huggingface.co/spaces/user/space", |
|
container=False |
|
) |
|
|
|
with gr.Row(): |
|
import_btn = gr.Button("Import", variant="secondary", scale=1) |
|
import_status = gr.HTML("", visible=False, scale=2) |
|
|
|
|
|
self.sidebar_components = { |
|
'model_dropdown': model_dropdown, |
|
'model_info': model_info, |
|
'language_dropdown': language_dropdown, |
|
'search_toggle': search_toggle, |
|
'advanced_mode': advanced_mode, |
|
'file_input': file_input, |
|
'website_url_input': website_url_input, |
|
'image_input': image_input, |
|
'advanced_controls': advanced_controls, |
|
'enable_images': enable_images, |
|
'enable_videos': enable_videos, |
|
'enable_music': enable_music, |
|
'media_prompts': media_prompts, |
|
'example_gallery': example_gallery, |
|
'import_url': import_url, |
|
'import_btn': import_btn, |
|
'import_status': import_status |
|
} |
|
|
|
|
|
advanced_mode.change( |
|
lambda checked: gr.update(visible=checked), |
|
inputs=[advanced_mode], |
|
outputs=[advanced_controls] |
|
) |
|
|
|
|
|
for checkbox in [enable_images, enable_videos, enable_music]: |
|
checkbox.change( |
|
lambda *args: gr.update(visible=any(args)), |
|
inputs=[enable_images, enable_videos, enable_music], |
|
outputs=[media_prompts] |
|
) |
|
|
|
def create_main_content(self, history, current_model): |
|
"""Create the main content area""" |
|
|
|
|
|
with gr.Group(elem_classes=["input-group"]): |
|
input_textbox = gr.Textbox( |
|
label="What would you like to build?", |
|
placeholder="Describe your application in detail... (e.g., 'Create a modern dashboard with charts and user management')", |
|
lines=4, |
|
container=False, |
|
elem_classes=["main-input"] |
|
) |
|
|
|
with gr.Row(): |
|
generate_btn = gr.Button( |
|
"π Generate Application", |
|
variant="primary", |
|
scale=3, |
|
size="lg", |
|
elem_classes=["generate-btn"] |
|
) |
|
clear_btn = gr.Button( |
|
"ποΈ Clear", |
|
variant="secondary", |
|
scale=1, |
|
size="lg" |
|
) |
|
|
|
|
|
with gr.Tabs(elem_classes=["output-tabs"]): |
|
|
|
|
|
with gr.Tab("π₯οΈ Live Preview", elem_classes=["preview-tab"]): |
|
with gr.Group(): |
|
preview_controls = gr.HTML(""" |
|
<div class="preview-controls"> |
|
<div class="preview-info"> |
|
<span class="info-item">π± Responsive Design</span> |
|
<span class="info-item">β‘ Real-time Updates</span> |
|
<span class="info-item">π Sandboxed Environment</span> |
|
</div> |
|
</div> |
|
""") |
|
|
|
sandbox = gr.HTML( |
|
label="Application Preview", |
|
elem_classes=["preview-container"] |
|
) |
|
|
|
|
|
with gr.Tab("π» Source Code", elem_classes=["code-tab"]): |
|
with gr.Row(): |
|
with gr.Column(scale=4): |
|
code_output = gr.Code( |
|
language="html", |
|
lines=30, |
|
interactive=True, |
|
label="Generated Code", |
|
elem_classes=["code-editor"] |
|
) |
|
|
|
with gr.Column(scale=1, elem_classes=["code-sidebar"]): |
|
|
|
with gr.Group(): |
|
gr.HTML('<div class="group-title">π§ Code Actions</div>') |
|
|
|
copy_btn = gr.Button("π Copy Code", size="sm") |
|
download_btn = gr.Button("πΎ Download", size="sm") |
|
format_btn = gr.Button("β¨ Format", size="sm") |
|
|
|
|
|
with gr.Group(): |
|
gr.HTML('<div class="group-title">π Code Stats</div>') |
|
code_stats = gr.HTML( |
|
'<div class="code-stats">Ready to generate...</div>', |
|
elem_classes=["code-stats"] |
|
) |
|
|
|
|
|
with gr.Tab("π Deploy", elem_classes=["deploy-tab"]): |
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
with gr.Group(): |
|
gr.HTML('<div class="group-title">π Deployment Options</div>') |
|
|
|
deploy_platform = gr.Dropdown( |
|
choices=[ |
|
("Hugging Face Spaces", "hf_spaces"), |
|
("Vercel", "vercel"), |
|
("Netlify", "netlify"), |
|
("GitHub Pages", "github_pages") |
|
], |
|
value="hf_spaces", |
|
label="Platform", |
|
container=False |
|
) |
|
|
|
app_name = gr.Textbox( |
|
label="Application Name", |
|
placeholder="my-awesome-app", |
|
container=False |
|
) |
|
|
|
deploy_btn = gr.Button( |
|
"π Deploy Now", |
|
variant="primary", |
|
size="lg" |
|
) |
|
|
|
with gr.Column(scale=1): |
|
deployment_status = gr.HTML( |
|
'<div class="deployment-status">Ready to deploy</div>', |
|
elem_classes=["deployment-status"] |
|
) |
|
|
|
|
|
generation_status = gr.HTML( |
|
visible=False, |
|
elem_classes=["generation-status"] |
|
) |
|
|
|
|
|
self.main_components = { |
|
'input_textbox': input_textbox, |
|
'generate_btn': generate_btn, |
|
'clear_btn': clear_btn, |
|
'sandbox': sandbox, |
|
'code_output': code_output, |
|
'code_stats': code_stats, |
|
'copy_btn': copy_btn, |
|
'download_btn': download_btn, |
|
'format_btn': format_btn, |
|
'deploy_platform': deploy_platform, |
|
'app_name': app_name, |
|
'deploy_btn': deploy_btn, |
|
'deployment_status': deployment_status, |
|
'generation_status': generation_status |
|
} |
|
|
|
def setup_event_handlers(self, app, history, setting, current_model, session_state): |
|
"""Setup all event handlers for the application""" |
|
|
|
|
|
self.main_components['generate_btn'].click( |
|
self.handle_generation, |
|
inputs=[ |
|
self.main_components['input_textbox'], |
|
self.sidebar_components['file_input'], |
|
self.sidebar_components['website_url_input'], |
|
self.sidebar_components['image_input'], |
|
self.sidebar_components['language_dropdown'], |
|
self.sidebar_components['search_toggle'], |
|
current_model, |
|
history, |
|
session_state |
|
], |
|
outputs=[ |
|
self.main_components['code_output'], |
|
self.main_components['sandbox'], |
|
self.main_components['code_stats'], |
|
history |
|
] |
|
) |
|
|
|
|
|
self.sidebar_components['model_dropdown'].change( |
|
self.handle_model_change, |
|
inputs=[self.sidebar_components['model_dropdown']], |
|
outputs=[current_model, self.sidebar_components['model_info']] |
|
) |
|
|
|
|
|
self.main_components['clear_btn'].click( |
|
self.handle_clear, |
|
outputs=[ |
|
self.main_components['input_textbox'], |
|
self.main_components['code_output'], |
|
self.main_components['sandbox'], |
|
self.main_components['code_stats'], |
|
history |
|
] |
|
) |
|
|
|
|
|
self.sidebar_components['example_gallery'].select( |
|
self.handle_example_select, |
|
inputs=[self.sidebar_components['example_gallery']], |
|
outputs=[self.main_components['input_textbox']] |
|
) |
|
|
|
def handle_generation(self, prompt, file, website_url, image, language, |
|
enable_search, current_model_state, history_state, session_state): |
|
"""Handle code generation with advanced features""" |
|
|
|
if not prompt.strip(): |
|
return ( |
|
gr.update(), |
|
"<div class='error-message'>Please enter a description of what you'd like to build.</div>", |
|
"<div class='code-stats error'>No input provided</div>", |
|
history_state |
|
) |
|
|
|
try: |
|
|
|
session_id = session_state.get('session_id', str(uuid.uuid4())) |
|
session_state['session_id'] = session_id |
|
|
|
|
|
enhanced_prompt = prompt |
|
if file: |
|
file_content = extract_text_from_file(file.name) |
|
if file_content: |
|
enhanced_prompt = f"{prompt}\n\n[Reference file content]\n{file_content[:5000]}" |
|
|
|
|
|
if website_url and website_url.strip(): |
|
website_content = extract_website_content(website_url.strip()) |
|
if website_content and not website_content.startswith("Error"): |
|
enhanced_prompt = f"{enhanced_prompt}\n\n[Website content to redesign]\n{website_content[:8000]}" |
|
|
|
|
|
if enable_search: |
|
enhanced_prompt = enhance_query_with_search(enhanced_prompt, True) |
|
|
|
|
|
generated_code = self.generate_code_with_model( |
|
enhanced_prompt, current_model_state, language, image |
|
) |
|
|
|
|
|
processed_code = remove_code_block(generated_code) |
|
|
|
|
|
if any([ |
|
session_state.get('enable_images', False), |
|
session_state.get('enable_videos', False), |
|
session_state.get('enable_music', False) |
|
]): |
|
processed_code = apply_generated_media_to_html( |
|
processed_code, |
|
prompt, |
|
enable_text_to_image=session_state.get('enable_images', False), |
|
enable_text_to_video=session_state.get('enable_videos', False), |
|
enable_text_to_music=session_state.get('enable_music', False), |
|
session_id=session_id |
|
) |
|
|
|
|
|
preview_html = self.generate_preview(processed_code, language) |
|
|
|
|
|
stats_html = self.generate_code_stats(processed_code, language) |
|
|
|
|
|
history_state.append([prompt, processed_code]) |
|
|
|
return ( |
|
gr.update(value=processed_code, language=get_gradio_language(language)), |
|
preview_html, |
|
stats_html, |
|
history_state |
|
) |
|
|
|
except Exception as e: |
|
error_html = f"<div class='error-message'>Generation Error: {str(e)}</div>" |
|
return ( |
|
gr.update(value=f"// Error: {str(e)}"), |
|
error_html, |
|
"<div class='code-stats error'>Generation failed</div>", |
|
history_state |
|
) |
|
|
|
def generate_code_with_model(self, prompt, model_state, language, image): |
|
"""Generate code using the selected model""" |
|
|
|
try: |
|
client = get_inference_client(model_state['id'], "auto") |
|
|
|
|
|
system_prompts = { |
|
'html': HTML_SYSTEM_PROMPT, |
|
'streamlit': "You are an expert Streamlit developer. Create modern, interactive Streamlit applications with clean code and professional UI.", |
|
'gradio': "You are an expert Gradio developer. Create modern, interactive Gradio applications with clean interfaces and robust functionality.", |
|
'transformers.js': "You are an expert in Transformers.js. Create modern web applications using Transformers.js for AI/ML functionality.", |
|
'svelte': "You are an expert Svelte developer. Create modern, reactive Svelte applications with TypeScript and clean architecture." |
|
} |
|
|
|
system_prompt = system_prompts.get(language, HTML_SYSTEM_PROMPT) |
|
|
|
|
|
messages = [ |
|
{"role": "system", "content": system_prompt} |
|
] |
|
|
|
if image: |
|
messages.append(create_multimodal_message(prompt, image)) |
|
else: |
|
messages.append({"role": "user", "content": prompt}) |
|
|
|
|
|
if hasattr(client, 'chat') and hasattr(client.chat, 'completions'): |
|
completion = client.chat.completions.create( |
|
model=model_state['id'], |
|
messages=messages, |
|
max_tokens=16384, |
|
temperature=0.7, |
|
stream=False |
|
) |
|
|
|
return completion.choices[0].message.content |
|
else: |
|
|
|
return "Generated code would appear here..." |
|
|
|
except Exception as e: |
|
raise Exception(f"Model generation failed: {str(e)}") |
|
|
|
def generate_preview(self, code, language): |
|
"""Generate HTML preview for the code""" |
|
|
|
try: |
|
if language == "html": |
|
|
|
files = parse_multipage_html_output(code) |
|
if files and files.get('index.html'): |
|
files = validate_and_autofix_files(files) |
|
preview_code = inline_multipage_into_single_preview(files) |
|
else: |
|
preview_code = extract_html_document(code) |
|
|
|
return self.send_to_sandbox(preview_code) |
|
|
|
elif language == "transformers.js": |
|
files = parse_transformers_js_output(code) |
|
if files['index.html'] and files['index.js'] and files['style.css']: |
|
merged_html = build_transformers_inline_html(files) |
|
return self.send_to_sandbox(merged_html) |
|
else: |
|
return "<div class='preview-message'>β³ Generating Transformers.js application...</div>" |
|
|
|
elif language == "streamlit": |
|
if is_streamlit_code(code): |
|
return self.send_streamlit_to_stlite(code) |
|
else: |
|
return "<div class='preview-message'>Add <code>import streamlit as st</code> to enable preview</div>" |
|
|
|
elif language == "gradio": |
|
if is_gradio_code(code): |
|
return self.send_gradio_to_lite(code) |
|
else: |
|
return "<div class='preview-message'>Add <code>import gradio as gr</code> to enable preview</div>" |
|
|
|
else: |
|
return f"<div class='preview-message'>π» {language.upper()} code generated successfully. Preview not available for this language.</div>" |
|
|
|
except Exception as e: |
|
return f"<div class='error-message'>Preview Error: {str(e)}</div>" |
|
|
|
def send_to_sandbox(self, html_code): |
|
"""Send HTML to sandboxed iframe""" |
|
if not html_code.strip(): |
|
return "<div class='preview-message'>No content to preview</div>" |
|
|
|
try: |
|
encoded_html = base64.b64encode(html_code.encode('utf-8')).decode('utf-8') |
|
data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}" |
|
iframe = f''' |
|
<iframe |
|
src="{data_uri}" |
|
width="100%" |
|
height="800px" |
|
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals" |
|
style="border: 1px solid #e5e7eb; border-radius: 8px; background: white;" |
|
allow="display-capture"> |
|
</iframe> |
|
''' |
|
return iframe |
|
except Exception as e: |
|
return f"<div class='error-message'>Sandbox Error: {str(e)}</div>" |
|
|
|
def send_streamlit_to_stlite(self, code): |
|
"""Send Streamlit code to stlite preview""" |
|
html_doc = f""" |
|
<!doctype html> |
|
<html> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> |
|
<title>Streamlit Preview</title> |
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@stlite/[email protected]/build/stlite.css" /> |
|
<script type="module" src="https://cdn.jsdelivr.net/npm/@stlite/[email protected]/build/stlite.js"></script> |
|
</head> |
|
<body> |
|
<streamlit-app>{code}</streamlit-app> |
|
</body> |
|
</html> |
|
""" |
|
return self.send_to_sandbox(html_doc) |
|
|
|
def send_gradio_to_lite(self, code): |
|
"""Send Gradio code to gradio-lite preview""" |
|
html_doc = f""" |
|
<!doctype html> |
|
<html> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> |
|
<title>Gradio Preview</title> |
|
<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script> |
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" /> |
|
</head> |
|
<body> |
|
<gradio-lite>{code}</gradio-lite> |
|
</body> |
|
</html> |
|
""" |
|
return self.send_to_sandbox(html_doc) |
|
|
|
def generate_code_stats(self, code, language): |
|
"""Generate code statistics""" |
|
if not code: |
|
return "<div class='code-stats'>No code generated</div>" |
|
|
|
try: |
|
lines = len(code.split('\n')) |
|
chars = len(code) |
|
words = len(code.split()) |
|
|
|
|
|
if language == "html": |
|
tags = len([m for m in code.split('<') if m.strip()]) |
|
stats_content = f""" |
|
<div class='stats-grid'> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{lines}</span> |
|
<span class='stat-label'>Lines</span> |
|
</div> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{tags}</span> |
|
<span class='stat-label'>HTML Tags</span> |
|
</div> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{chars}</span> |
|
<span class='stat-label'>Characters</span> |
|
</div> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{round(chars/1024, 1)}KB</span> |
|
<span class='stat-label'>Size</span> |
|
</div> |
|
</div> |
|
""" |
|
else: |
|
stats_content = f""" |
|
<div class='stats-grid'> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{lines}</span> |
|
<span class='stat-label'>Lines</span> |
|
</div> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{words}</span> |
|
<span class='stat-label'>Words</span> |
|
</div> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{chars}</span> |
|
<span class='stat-label'>Characters</span> |
|
</div> |
|
<div class='stat-item'> |
|
<span class='stat-number'>{language.upper()}</span> |
|
<span class='stat-label'>Language</span> |
|
</div> |
|
</div> |
|
""" |
|
|
|
return f"<div class='code-stats'>{stats_content}</div>" |
|
|
|
except Exception: |
|
return "<div class='code-stats'>Unable to analyze code</div>" |
|
|
|
def handle_model_change(self, model_selection): |
|
"""Handle model selection change""" |
|
try: |
|
|
|
model_name = model_selection.split(" (")[0] |
|
|
|
|
|
selected_model = None |
|
for model in AVAILABLE_MODELS: |
|
if model['name'] == model_name: |
|
selected_model = model |
|
break |
|
|
|
if selected_model: |
|
model_info_html = self.get_model_info_html(selected_model) |
|
return selected_model, model_info_html |
|
|
|
return DEFAULT_MODEL, self.get_model_info_html(DEFAULT_MODEL) |
|
|
|
except Exception: |
|
return DEFAULT_MODEL, self.get_model_info_html(DEFAULT_MODEL) |
|
|
|
def handle_clear(self): |
|
"""Handle clear button""" |
|
return ( |
|
gr.update(value=""), |
|
gr.update(value="", language="html"), |
|
"<div class='preview-message'>Ready to generate your next application</div>", |
|
"<div class='code-stats'>Ready to generate...</div>", |
|
[] |
|
) |
|
|
|
def handle_example_select(self, evt: gr.SelectData): |
|
"""Handle example selection from gallery""" |
|
try: |
|
if evt.index is not None and evt.index < len(DEMO_LIST): |
|
return DEMO_LIST[evt.index]['description'] |
|
return "" |
|
except Exception: |
|
return "" |
|
|
|
def get_model_info_html(self, model): |
|
"""Generate HTML for model information""" |
|
vision_badge = '<span class="feature-badge vision">ποΈ Vision</span>' if model.get('supports_vision') else '' |
|
category_color = { |
|
'General': '#3b82f6', |
|
'Code Specialist': '#10b981', |
|
'Vision-Language': '#f59e0b', |
|
'Premium': '#8b5cf6' |
|
}.get(model.get('category', 'General'), '#6b7280') |
|
|
|
return f""" |
|
<div class="model-info"> |
|
<div class="model-header"> |
|
<div class="model-name">{model['name']}</div> |
|
<span class="category-badge" style="background-color: {category_color}"> |
|
{model.get('category', 'General')} |
|
</span> |
|
</div> |
|
<div class="model-description">{model.get('description', '')}</div> |
|
<div class="model-features"> |
|
{vision_badge} |
|
<span class="feature-badge">π Latest</span> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def get_custom_css(self): |
|
"""Get custom CSS for the application""" |
|
return """ |
|
/* Modern Professional Styling */ |
|
.gradio-container { |
|
max-width: none !important; |
|
padding: 0 !important; |
|
} |
|
|
|
.app-header { |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
color: white; |
|
padding: 20px; |
|
border-radius: 0 0 16px 16px; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.header-content { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
max-width: 1400px; |
|
margin: 0 auto; |
|
} |
|
|
|
.logo-section { |
|
display: flex; |
|
align-items: center; |
|
gap: 15px; |
|
} |
|
|
|
.logo { |
|
font-size: 2.5rem; |
|
font-weight: bold; |
|
} |
|
|
|
.app-title h1 { |
|
font-size: 2rem; |
|
margin: 0; |
|
font-weight: 700; |
|
} |
|
|
|
.app-title p { |
|
margin: 5px 0 0 0; |
|
opacity: 0.9; |
|
font-size: 1rem; |
|
} |
|
|
|
.status-indicators { |
|
display: flex; |
|
flex-direction: column; |
|
gap: 8px; |
|
} |
|
|
|
.status-item { |
|
display: flex; |
|
align-items: center; |
|
gap: 8px; |
|
font-size: 0.9rem; |
|
} |
|
|
|
.status-dot { |
|
width: 8px; |
|
height: 8px; |
|
border-radius: 50%; |
|
background: #10b981; |
|
} |
|
|
|
.status-dot.active { |
|
animation: pulse 2s infinite; |
|
} |
|
|
|
@keyframes pulse { |
|
0%, 100% { opacity: 1; } |
|
50% { opacity: 0.5; } |
|
} |
|
|
|
.sidebar { |
|
background: #f8fafc; |
|
padding: 20px; |
|
border-radius: 12px; |
|
border: 1px solid #e2e8f0; |
|
height: fit-content; |
|
} |
|
|
|
.main-content { |
|
padding-left: 20px; |
|
} |
|
|
|
.control-group { |
|
margin-bottom: 24px; |
|
background: white; |
|
padding: 16px; |
|
border-radius: 8px; |
|
border: 1px solid #e5e7eb; |
|
} |
|
|
|
.group-title { |
|
font-weight: 600; |
|
font-size: 0.95rem; |
|
color: #374151; |
|
margin-bottom: 12px; |
|
display: flex; |
|
align-items: center; |
|
gap: 8px; |
|
} |
|
|
|
.input-group { |
|
background: white; |
|
padding: 24px; |
|
border-radius: 12px; |
|
border: 1px solid #e2e8f0; |
|
margin-bottom: 20px; |
|
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
.main-input textarea { |
|
font-size: 16px !important; |
|
line-height: 1.5 !important; |
|
} |
|
|
|
.generate-btn { |
|
background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important; |
|
border: none !important; |
|
font-weight: 600 !important; |
|
font-size: 1.1rem !important; |
|
padding: 16px 32px !important; |
|
} |
|
|
|
.generate-btn:hover { |
|
transform: translateY(-1px); |
|
box-shadow: 0 10px 25px rgba(16, 185, 129, 0.3) !important; |
|
} |
|
|
|
.output-tabs .tab-nav { |
|
background: #f8fafc; |
|
border-radius: 8px 8px 0 0; |
|
border-bottom: 1px solid #e2e8f0; |
|
} |
|
|
|
.preview-container iframe { |
|
border-radius: 8px; |
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
.code-editor { |
|
border-radius: 8px; |
|
border: 1px solid #e2e8f0; |
|
} |
|
|
|
.code-sidebar { |
|
padding-left: 16px; |
|
} |
|
|
|
.code-sidebar .control-group { |
|
margin-bottom: 16px; |
|
padding: 12px; |
|
} |
|
|
|
.code-stats { |
|
background: white; |
|
padding: 16px; |
|
border-radius: 8px; |
|
border: 1px solid #e5e7eb; |
|
} |
|
|
|
.stats-grid { |
|
display: grid; |
|
grid-template-columns: 1fr 1fr; |
|
gap: 12px; |
|
} |
|
|
|
.stat-item { |
|
text-align: center; |
|
padding: 8px; |
|
background: #f8fafc; |
|
border-radius: 6px; |
|
} |
|
|
|
.stat-number { |
|
display: block; |
|
font-size: 1.25rem; |
|
font-weight: 700; |
|
color: #1f2937; |
|
} |
|
|
|
.stat-label { |
|
font-size: 0.75rem; |
|
color: #6b7280; |
|
text-transform: uppercase; |
|
letter-spacing: 0.05em; |
|
} |
|
|
|
.model-info { |
|
background: white; |
|
padding: 12px; |
|
border-radius: 6px; |
|
border: 1px solid #e5e7eb; |
|
margin-top: 8px; |
|
} |
|
|
|
.model-header { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
margin-bottom: 8px; |
|
} |
|
|
|
.model-name { |
|
font-weight: 600; |
|
color: #1f2937; |
|
} |
|
|
|
.category-badge { |
|
padding: 2px 8px; |
|
border-radius: 12px; |
|
font-size: 0.75rem; |
|
font-weight: 500; |
|
color: white; |
|
} |
|
|
|
.model-description { |
|
font-size: 0.85rem; |
|
color: #6b7280; |
|
margin-bottom: 8px; |
|
} |
|
|
|
.model-features { |
|
display: flex; |
|
gap: 4px; |
|
} |
|
|
|
.feature-badge { |
|
padding: 2px 6px; |
|
border-radius: 8px; |
|
font-size: 0.7rem; |
|
font-weight: 500; |
|
background: #f3f4f6; |
|
color: #374151; |
|
} |
|
|
|
.feature-badge.vision { |
|
background: #fef3c7; |
|
color: #92400e; |
|
} |
|
|
|
.example-gallery { |
|
border-radius: 8px; |
|
border: 1px solid #e5e7eb; |
|
} |
|
|
|
.preview-message { |
|
text-align: center; |
|
padding: 40px 20px; |
|
color: #6b7280; |
|
background: #f9fafb; |
|
border-radius: 8px; |
|
border: 2px dashed #d1d5db; |
|
} |
|
|
|
.error-message { |
|
text-align: center; |
|
padding: 20px; |
|
color: #dc2626; |
|
background: #fef2f2; |
|
border: 1px solid #fecaca; |
|
border-radius: 8px; |
|
} |
|
|
|
.deployment-status { |
|
background: white; |
|
padding: 16px; |
|
border-radius: 8px; |
|
border: 1px solid #e5e7eb; |
|
text-align: center; |
|
color: #6b7280; |
|
} |
|
|
|
/* Dark mode adjustments */ |
|
.dark .sidebar { |
|
background: #1f2937; |
|
border-color: #374151; |
|
} |
|
|
|
.dark .control-group { |
|
background: #111827; |
|
border-color: #374151; |
|
} |
|
|
|
.dark .input-group { |
|
background: #111827; |
|
border-color: #374151; |
|
} |
|
|
|
/* Responsive design */ |
|
@media (max-width: 768px) { |
|
.header-content { |
|
flex-direction: column; |
|
gap: 20px; |
|
text-align: center; |
|
} |
|
|
|
.stats-grid { |
|
grid-template-columns: 1fr; |
|
} |
|
|
|
.main-content { |
|
padding-left: 0; |
|
margin-top: 20px; |
|
} |
|
} |
|
""" |
|
|
|
def get_head_html(self): |
|
"""Get additional head HTML""" |
|
return """ |
|
<meta name="description" content="AnyCoder - Professional AI Development Suite for creating modern applications"> |
|
<meta name="keywords" content="AI, code generation, web development, automation"> |
|
<meta name="author" content="AnyCoder"> |
|
<link rel="preconnect" href="https://fonts.googleapis.com"> |
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> |
|
<style> |
|
body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; } |
|
</style> |
|
""" |
|
|
|
def main(): |
|
"""Main application entry point""" |
|
print("π Starting AnyCoder Professional AI Development Suite...") |
|
|
|
|
|
app_instance = AnyCoder() |
|
demo = app_instance.create_advanced_ui() |
|
|
|
|
|
demo.queue(api_open=False, default_concurrency_limit=20).launch( |
|
show_api=False, |
|
share=False, |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
show_error=True, |
|
quiet=False |
|
) |
|
|
|
if __name__ == "__main__": |
|
main() |