diff --git "a/anycoder_app/ui.py" "b/anycoder_app/ui.py" deleted file mode 100644--- "a/anycoder_app/ui.py" +++ /dev/null @@ -1,2102 +0,0 @@ -""" -Gradio user interface for AnyCoder. -Defines the main UI layout, components, and event handlers. -""" -import os -import gradio as gr -from typing import Dict, Optional -from huggingface_hub import HfApi -import httpx - -# Monkey-patch httpx to increase timeout for OAuth -# This prevents ReadTimeout errors during HuggingFace OAuth flow -_original_client_init = httpx.AsyncClient.__init__ - -def _patched_client_init(self, *args, **kwargs): - # If no timeout is specified, use longer timeouts - if 'timeout' not in kwargs: - kwargs['timeout'] = httpx.Timeout( - connect=30.0, # 30 seconds for connection - read=60.0, # 60 seconds for reading response (increased from default 5s) - write=30.0, # 30 seconds for writing - pool=30.0 # 30 seconds for pool operations - ) - return _original_client_init(self, *args, **kwargs) - -httpx.AsyncClient.__init__ = _patched_client_init - -from .config import ( - AVAILABLE_MODELS, DEFAULT_MODEL, DEFAULT_MODEL_NAME, - LANGUAGE_CHOICES, get_gradio_language -) -from .themes import THEME_CONFIGS, get_saved_theme, current_theme -from .prompts import HTML_SYSTEM_PROMPT -from .models import history_to_chatbot_messages -from .parsers import ( - history_render, clear_history, create_multimodal_message, - parse_multipage_html_output, parse_transformers_js_output, - parse_react_output, format_transformers_js_output, - validate_and_autofix_files, parse_multi_file_python_output, - is_streamlit_code, is_gradio_code -) -from .deploy import ( - check_authentication, update_ui_for_auth_status, - generation_code, deploy_to_spaces, add_anycoder_tag_to_readme, - _parse_repo_or_model_url, load_project_from_url, check_hf_space_url, - import_repo_to_app, extract_import_statements, - generate_requirements_txt_with_llm, prettify_comfyui_json_for_html, - get_trending_models, import_model_from_hf, get_trending_spaces, import_space_from_hf, - switch_model_code_type -) -from .agent import ( - agent_generate_with_questions, agent_process_answers_and_generate -) - -# Main application with proper Gradio theming -with gr.Blocks( - title="AnyCoder - AI Code Generator", - theme=current_theme, - css=""" - .theme-info { font-size: 0.9em; opacity: 0.8; } - .theme-description { padding: 8px 0; } - .theme-status { - padding: 10px; - border-radius: 8px; - background: rgba(34, 197, 94, 0.1); - border: 1px solid rgba(34, 197, 94, 0.2); - margin: 8px 0; - } - .restart-needed { - padding: 12px; - border-radius: 8px; - background: rgba(255, 193, 7, 0.1); - border: 1px solid rgba(255, 193, 7, 0.3); - margin: 8px 0; - text-align: center; - } - /* Authentication status styling */ - .auth-status { - padding: 8px 12px; - border-radius: 6px; - margin: 8px 0; - font-weight: 500; - text-align: center; - } - .auth-status:has-text("🔒") { - background: rgba(231, 76, 60, 0.1); - border: 1px solid rgba(231, 76, 60, 0.3); - color: #e74c3c; - } - .auth-status:has-text("✅") { - background: rgba(46, 204, 113, 0.1); - border: 1px solid rgba(46, 204, 113, 0.3); - color: #2ecc71; - } - /* App link styling (visible on all devices) */ - .app-link { - display: block; - padding: 12px; - border-radius: 8px; - background: rgba(59, 130, 246, 0.1); - border: 1px solid rgba(59, 130, 246, 0.3); - margin: 12px 0; - text-align: center; - } - """ -) as demo: - history = gr.State([]) - setting = gr.State({ - "system": HTML_SYSTEM_PROMPT, - }) - current_model = gr.State(DEFAULT_MODEL) - open_panel = gr.State(None) - last_login_state = gr.State(None) - models_first_change = gr.State(True) - spaces_first_change = gr.State(True) - agent_mode_enabled = gr.State(False) - current_trending_model_id = gr.State("") # Track current trending model for code switching - agent_conversation_state = gr.State({ - "stage": "initial", # initial, waiting_for_answers, generating - "original_query": "", - "questions": "" - }) - - with gr.Sidebar() as sidebar: - login_button = gr.LoginButton() - - # App link (visible on all devices) - mobile_link = gr.HTML( - """ - - """, - visible=True - ) - - - # Unified Import section - import_header_md = gr.Markdown("📥 Import Project (Space, GitHub, or Model)", visible=False) - load_project_url = gr.Textbox( - label="Project URL", - placeholder="https://huggingface.co/spaces/user/space OR https://huggingface.co/user/model OR https://github.com/owner/repo", - lines=1 - , visible=False) - load_project_btn = gr.Button("📥 Import Project", variant="secondary", size="sm", visible=True) - load_project_status = gr.Markdown(visible=False) - - # Trending HuggingFace Models section - trending_models_dropdown = gr.Dropdown( - label="🔥 Trending HuggingFace Models", - choices=[], # Will be populated on load - value=None, - interactive=True, - visible=True - ) - trending_models_status = gr.Markdown(visible=False) - switch_model_code_btn = gr.Button("🔄 Switch Code Type", visible=False, size="sm", variant="secondary") - - # Trending HuggingFace Spaces section - trending_spaces_dropdown = gr.Dropdown( - label="🚀 Trending HuggingFace Spaces", - choices=[], # Will be populated on load - value=None, - interactive=True, - visible=True - ) - trending_spaces_status = gr.Markdown(visible=False) - - # Chat history display in sidebar - chat_history = gr.Chatbot( - label="Conversation History", - type="messages", - height=300, - show_copy_button=True, - visible=True - ) - - # Input textbox for new messages - input = gr.Textbox( - label="What would you like to build?", - placeholder="🔒 Please log in with Hugging Face to use AnyCoder...", - lines=2, - visible=True, - interactive=False - ) - # Language dropdown for code generation (add Streamlit and Gradio as first-class options) - language_choices = [ - "html", "gradio", "transformers.js", "streamlit", "comfyui", "react" - ] - language_dropdown = gr.Dropdown( - choices=language_choices, - value="html", - label="Code Language", - visible=True - ) - - # Agent mode checkbox - agent_mode_checkbox = gr.Checkbox( - label="🤖 Enable Agent Mode", - value=False, - info="Agent will ask follow-up questions and create a task list before coding", - visible=True - ) - - # Removed image generation components - with gr.Row(): - btn = gr.Button("Generate", variant="secondary", size="lg", scale=2, visible=True, interactive=False) - clear_btn = gr.Button("Clear", variant="secondary", size="sm", scale=1, visible=True) - # --- Deploy components (visible by default) --- - deploy_header_md = gr.Markdown("", visible=False) - deploy_btn = gr.Button("Publish", variant="primary", visible=True) - deploy_status = gr.Markdown(visible=False, label="Deploy status") - # --- End move --- - # Removed media generation and web search UI components - - # Removed media generation toggle event handlers - model_dropdown = gr.Dropdown( - choices=[model['name'] for model in AVAILABLE_MODELS], - value=DEFAULT_MODEL_NAME, - label="Model", - visible=True - ) - provider_state = gr.State("auto") - # Removed web search availability indicator - def on_model_change(model_name): - for m in AVAILABLE_MODELS: - if m['name'] == model_name: - return m - return AVAILABLE_MODELS[0] - def save_prompt(input): - return {setting: {"system": input}} - model_dropdown.change( - lambda model_name: on_model_change(model_name), - inputs=model_dropdown, - outputs=[current_model] - ) - # --- Remove deploy/app name/sdk from bottom column --- - # (delete the gr.Column() block containing space_name_input, sdk_dropdown, deploy_btn, deploy_status) - - with gr.Column() as main_column: - with gr.Tabs(): - with gr.Tab("Code"): - code_output = gr.Code( - language="html", - lines=25, - interactive=True, - label="Generated code" - ) - - - - # Transformers.js multi-file editors (hidden by default) - with gr.Group(visible=False) as tjs_group: - with gr.Tabs(): - with gr.Tab("index.html"): - tjs_html_code = gr.Code(language="html", lines=20, interactive=True, label="index.html") - with gr.Tab("index.js"): - tjs_js_code = gr.Code(language="javascript", lines=20, interactive=True, label="index.js") - with gr.Tab("style.css"): - tjs_css_code = gr.Code(language="css", lines=20, interactive=True, label="style.css") - - # Python multi-file editors (hidden by default) for Gradio/Streamlit - with gr.Group(visible=False) as python_group_2: - with gr.Tabs(): - with gr.Tab("app.py") as python_tab_2_1: - python_code_2_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py") - with gr.Tab("file 2") as python_tab_2_2: - python_code_2_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2") - - with gr.Group(visible=False) as python_group_3: - with gr.Tabs(): - with gr.Tab("app.py") as python_tab_3_1: - python_code_3_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py") - with gr.Tab("file 2") as python_tab_3_2: - python_code_3_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2") - with gr.Tab("file 3") as python_tab_3_3: - python_code_3_3 = gr.Code(language="python", lines=18, interactive=True, label="file 3") - - with gr.Group(visible=False) as python_group_4: - with gr.Tabs(): - with gr.Tab("app.py") as python_tab_4_1: - python_code_4_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py") - with gr.Tab("file 2") as python_tab_4_2: - python_code_4_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2") - with gr.Tab("file 3") as python_tab_4_3: - python_code_4_3 = gr.Code(language="python", lines=18, interactive=True, label="file 3") - with gr.Tab("file 4") as python_tab_4_4: - python_code_4_4 = gr.Code(language="python", lines=18, interactive=True, label="file 4") - - with gr.Group(visible=False) as python_group_5plus: - with gr.Tabs(): - with gr.Tab("app.py") as python_tab_5_1: - python_code_5_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py") - with gr.Tab("file 2") as python_tab_5_2: - python_code_5_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2") - with gr.Tab("file 3") as python_tab_5_3: - python_code_5_3 = gr.Code(language="python", lines=18, interactive=True, label="file 3") - with gr.Tab("file 4") as python_tab_5_4: - python_code_5_4 = gr.Code(language="python", lines=18, interactive=True, label="file 4") - with gr.Tab("file 5") as python_tab_5_5: - python_code_5_5 = gr.Code(language="python", lines=18, interactive=True, label="file 5") - - # Static HTML multi-file editors (hidden by default). Use separate tab groups for different file counts. - with gr.Group(visible=False) as static_group_2: - with gr.Tabs(): - with gr.Tab("index.html") as static_tab_2_1: - static_code_2_1 = gr.Code(language="html", lines=20, interactive=True, label="index.html") - with gr.Tab("file 2") as static_tab_2_2: - static_code_2_2 = gr.Code(language="html", lines=18, interactive=True, label="file 2") - - with gr.Group(visible=False) as static_group_3: - with gr.Tabs(): - with gr.Tab("index.html") as static_tab_3_1: - static_code_3_1 = gr.Code(language="html", lines=20, interactive=True, label="index.html") - with gr.Tab("file 2") as static_tab_3_2: - static_code_3_2 = gr.Code(language="html", lines=18, interactive=True, label="file 2") - with gr.Tab("file 3") as static_tab_3_3: - static_code_3_3 = gr.Code(language="html", lines=18, interactive=True, label="file 3") - - with gr.Group(visible=False) as static_group_4: - with gr.Tabs(): - with gr.Tab("index.html") as static_tab_4_1: - static_code_4_1 = gr.Code(language="html", lines=20, interactive=True, label="index.html") - with gr.Tab("file 2") as static_tab_4_2: - static_code_4_2 = gr.Code(language="html", lines=18, interactive=True, label="file 2") - with gr.Tab("file 3") as static_tab_4_3: - static_code_4_3 = gr.Code(language="html", lines=18, interactive=True, label="file 3") - with gr.Tab("file 4") as static_tab_4_4: - static_code_4_4 = gr.Code(language="html", lines=18, interactive=True, label="file 4") - - with gr.Group(visible=False) as static_group_5plus: - with gr.Tabs(): - with gr.Tab("index.html") as static_tab_5_1: - static_code_5_1 = gr.Code(language="html", lines=20, interactive=True, label="index.html") - with gr.Tab("file 2") as static_tab_5_2: - static_code_5_2 = gr.Code(language="html", lines=18, interactive=True, label="file 2") - with gr.Tab("file 3") as static_tab_5_3: - static_code_5_3 = gr.Code(language="html", lines=18, interactive=True, label="file 3") - with gr.Tab("file 4") as static_tab_5_4: - static_code_5_4 = gr.Code(language="html", lines=18, interactive=True, label="file 4") - with gr.Tab("file 5") as static_tab_5_5: - static_code_5_5 = gr.Code(language="html", lines=18, interactive=True, label="file 5") - # React Next.js multi-file editors (hidden by default) - with gr.Group(visible=False) as react_group: - with gr.Tabs(): - with gr.Tab("Dockerfile"): - react_code_dockerfile = gr.Code(language="dockerfile", lines=15, interactive=True, label="Dockerfile") - with gr.Tab("package.json"): - react_code_package_json = gr.Code(language="json", lines=20, interactive=True, label="package.json") - with gr.Tab("next.config.js"): - react_code_next_config = gr.Code(language="javascript", lines=15, interactive=True, label="next.config.js") - with gr.Tab("postcss.config.js"): - react_code_postcss_config = gr.Code(language="javascript", lines=10, interactive=True, label="postcss.config.js") - with gr.Tab("tailwind.config.js"): - react_code_tailwind_config = gr.Code(language="javascript", lines=15, interactive=True, label="tailwind.config.js") - with gr.Tab("pages/_app.js"): - react_code_pages_app = gr.Code(language="javascript", lines=15, interactive=True, label="pages/_app.js") - with gr.Tab("pages/index.js"): - react_code_pages_index = gr.Code(language="javascript", lines=20, interactive=True, label="pages/index.js") - with gr.Tab("components/ChatApp.jsx"): - react_code_components = gr.Code(language="javascript", lines=25, interactive=True, label="components/ChatApp.jsx") - with gr.Tab("styles/globals.css"): - react_code_styles = gr.Code(language="css", lines=20, interactive=True, label="styles/globals.css") - - # Removed Import Logs tab for cleaner UI - # History tab hidden per user request - # with gr.Tab("History"): - # history_output = gr.Chatbot(show_label=False, height=400, type="messages") - - # Keep history_output as hidden component to maintain functionality - history_output = gr.Chatbot(show_label=False, height=400, type="messages", visible=False) - - # Global generation status view (disabled placeholder) - generating_status = gr.Markdown("", visible=False) - - # Unified import handler - def handle_import_project(url): - if not url.strip(): - return [ - gr.update(value="Please enter a URL.", visible=True), - gr.update(), - gr.update(), - [], - [], - gr.update(value="Publish", visible=False), - gr.update(), # keep import header as-is - gr.update(), # keep import button as-is - gr.update(), # language dropdown - no change - [] # chat_history - ] - - kind, meta = _parse_repo_or_model_url(url) - if kind == "hf_space": - status, code = load_project_from_url(url) - # Extract space info for deployment - is_valid, username, project_name = check_hf_space_url(url) - space_name = f"{username}/{project_name}" if is_valid else "" - loaded_history = [[f"Imported Space from {url}", code]] - - # Determine the correct language/framework based on the imported content - code_lang = "html" # default - framework_type = "html" # for language dropdown - - # Check imports to determine framework for Python code - if is_streamlit_code(code): - code_lang = "python" - framework_type = "streamlit" - elif is_gradio_code(code): - code_lang = "python" - framework_type = "gradio" - elif "=== index.html ===" in code and "=== index.js ===" in code and "=== style.css ===" in code: - # This is a transformers.js app with the combined format - code_lang = "html" # Use html for code display - framework_type = "transformers.js" # But set dropdown to transformers.js - elif ("import " in code or "def " in code) and not ("" in code or "") or code.strip().startswith("") or code.strip().startswith("