akhaliq HF Staff commited on
Commit
6eeb9f9
·
1 Parent(s): 1310976

multi file load and generate gradio streamlit

Browse files
Files changed (1) hide show
  1. app.py +429 -13
app.py CHANGED
@@ -447,6 +447,41 @@ def update_gradio_system_prompts():
447
  # Base system prompt
448
  base_prompt = """You are an expert Gradio developer. Create a complete, working Gradio application based on the user's request. Generate all necessary code to make the application functional and runnable.
449
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  🚨 IMPORTANT: If the user is asking to use external APIs (like OpenRouter, OpenAI API, Hugging Face Inference API, etc.), DO NOT use @spaces.GPU decorators or any ZeroGPU features. External APIs handle the model inference remotely, so GPU allocation on the Spaces instance is not needed.
451
 
452
  🚨 CRITICAL REQUIREMENT: If the user provides ANY diffusion model code (FLUX, Stable Diffusion, etc.) that runs locally (not via API), you MUST implement ZeroGPU ahead-of-time (AoT) compilation. This is mandatory and provides 1.3x-1.8x performance improvements. Do not create basic Gradio apps without AoT optimization for diffusion models.
@@ -716,6 +751,41 @@ This reference is automatically synced from https://www.gradio.app/llms.txt to e
716
  # Search-enabled prompt
717
  search_prompt = """You are an expert Gradio developer with access to real-time web search. Create a complete, working Gradio application based on the user's request. When needed, use web search to find current best practices or verify latest Gradio features. Generate all necessary code to make the application functional and runnable.
718
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  🚨 IMPORTANT: If the user is asking to use external APIs (like OpenRouter, OpenAI API, Hugging Face Inference API, etc.), DO NOT use @spaces.GPU decorators or any ZeroGPU features. External APIs handle the model inference remotely, so GPU allocation on the Spaces instance is not needed.
720
 
721
  🚨 CRITICAL REQUIREMENT: If the user provides ANY diffusion model code (FLUX, Stable Diffusion, etc.) that runs locally (not via API), you MUST implement ZeroGPU ahead-of-time (AoT) compilation. This is mandatory and provides 1.3x-1.8x performance improvements. Do not create basic Gradio apps without AoT optimization for diffusion models.
@@ -1356,6 +1426,70 @@ Generate complete, working code files as shown above.
1356
 
1357
  IMPORTANT: Always include "Built with anycoder" as clickable text in the header/top section of your application that links to https://huggingface.co/spaces/akhaliq/anycoder"""
1358
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1359
  SVELTE_SYSTEM_PROMPT = """You are an expert Svelte developer creating a modern Svelte application.
1360
 
1361
  File selection policy (dynamic, model-decided):
@@ -1513,10 +1647,22 @@ IMPORTANT: When the user reports an ERROR MESSAGE, analyze it carefully to deter
1513
  - Configuration errors → Fix config files, Docker files, etc.
1514
 
1515
  For Python applications (Gradio/Streamlit), the project structure typically includes:
1516
- - app.py (main application file)
1517
  - requirements.txt (dependencies)
 
 
 
 
1518
  - Other supporting files as needed
1519
 
 
 
 
 
 
 
 
 
1520
  Format Rules:
1521
  1. Start with {SEARCH_START}
1522
  2. Provide the exact lines from the current code that need to be replaced.
@@ -5401,6 +5547,91 @@ def is_streamlit_code(code: str) -> bool:
5401
  lowered = code.lower()
5402
  return ("import streamlit" in lowered) or ("from streamlit" in lowered) or ("st." in code and "streamlit" in lowered)
5403
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5404
  def send_streamlit_to_stlite(code: str) -> str:
5405
  """Render Streamlit code using stlite inside a sandboxed iframe for preview."""
5406
  # Build an HTML document that loads stlite and mounts the Streamlit app defined inline
@@ -5718,6 +5949,8 @@ Generate the exact search/replace blocks needed to make these changes."""
5718
  system_prompt = SVELTE_SYSTEM_PROMPT
5719
  elif language == "gradio":
5720
  system_prompt = GRADIO_SYSTEM_PROMPT
 
 
5721
  elif language == "json":
5722
  system_prompt = JSON_SYSTEM_PROMPT
5723
  elif language == "comfyui":
@@ -7781,15 +8014,56 @@ with gr.Blocks(
7781
 
7782
 
7783
 
7784
- # Transformers.js multi-file editors (hidden by default)
7785
- with gr.Group(visible=False) as tjs_group:
7786
- with gr.Tabs():
7787
- with gr.Tab("index.html"):
7788
- tjs_html_code = gr.Code(language="html", lines=20, interactive=True, label="index.html")
7789
- with gr.Tab("index.js"):
7790
- tjs_js_code = gr.Code(language="javascript", lines=20, interactive=True, label="index.js")
7791
- with gr.Tab("style.css"):
7792
- tjs_css_code = gr.Code(language="css", lines=20, interactive=True, label="style.css")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7793
 
7794
  # Static HTML multi-file editors (hidden by default). Use separate tab groups for different file counts.
7795
  with gr.Group(visible=False) as static_group_2:
@@ -7872,10 +8146,10 @@ with gr.Blocks(
7872
  # Check imports to determine framework for Python code
7873
  if is_streamlit_code(code):
7874
  code_lang = "python"
7875
- framework_type = "python"
7876
  elif is_gradio_code(code):
7877
  code_lang = "python"
7878
- framework_type = "python"
7879
  elif "=== index.html ===" in code and "=== index.js ===" in code and "=== style.css ===" in code:
7880
  # This is a transformers.js app with the combined format
7881
  code_lang = "html" # Use html for code display
@@ -7903,7 +8177,7 @@ with gr.Blocks(
7903
  status, code, _ = import_repo_to_app(url)
7904
  loaded_history = [[f"Imported Repo/Model from {url}", code]]
7905
  code_lang = "python"
7906
- framework_type = "python"
7907
  lower = (code or "").lower()
7908
  if code.strip().startswith("<!doctype html>") or code.strip().startswith("<html"):
7909
  code_lang = "html"
@@ -7981,6 +8255,148 @@ with gr.Blocks(
7981
  outputs=[code_output, tjs_group, tjs_html_code, tjs_js_code, tjs_css_code],
7982
  )
7983
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7984
  # Static HTML multi-file toggling and population
7985
  def toggle_static_editors(language, code_text):
7986
  # If not static HTML language, ensure single editor visible and all static groups hidden
 
447
  # Base system prompt
448
  base_prompt = """You are an expert Gradio developer. Create a complete, working Gradio application based on the user's request. Generate all necessary code to make the application functional and runnable.
449
 
450
+ ## Multi-File Application Structure
451
+
452
+ When creating complex Gradio applications, organize your code into multiple files for better maintainability:
453
+
454
+ **File Organization:**
455
+ - `app.py` - Main application entry point with Gradio interface
456
+ - `utils.py` - Utility functions and helpers
457
+ - `models.py` - Model loading and inference functions
458
+ - `config.py` - Configuration and constants
459
+ - `requirements.txt` - Python dependencies
460
+ - Additional modules as needed (e.g., `data_processing.py`, `ui_components.py`)
461
+
462
+ **Output Format for Multi-File Apps:**
463
+ When generating multi-file applications, use this exact format:
464
+
465
+ ```
466
+ === app.py ===
467
+ [main application code]
468
+
469
+ === utils.py ===
470
+ [utility functions]
471
+
472
+ === requirements.txt ===
473
+ [dependencies]
474
+ ```
475
+
476
+ **Single vs Multi-File Decision:**
477
+ - Use single file for simple applications (< 100 lines)
478
+ - Use multi-file structure for complex applications with:
479
+ - Multiple models or processing pipelines
480
+ - Extensive utility functions
481
+ - Complex UI with many components
482
+ - Data processing workflows
483
+ - When user specifically requests modular structure
484
+
485
  🚨 IMPORTANT: If the user is asking to use external APIs (like OpenRouter, OpenAI API, Hugging Face Inference API, etc.), DO NOT use @spaces.GPU decorators or any ZeroGPU features. External APIs handle the model inference remotely, so GPU allocation on the Spaces instance is not needed.
486
 
487
  🚨 CRITICAL REQUIREMENT: If the user provides ANY diffusion model code (FLUX, Stable Diffusion, etc.) that runs locally (not via API), you MUST implement ZeroGPU ahead-of-time (AoT) compilation. This is mandatory and provides 1.3x-1.8x performance improvements. Do not create basic Gradio apps without AoT optimization for diffusion models.
 
751
  # Search-enabled prompt
752
  search_prompt = """You are an expert Gradio developer with access to real-time web search. Create a complete, working Gradio application based on the user's request. When needed, use web search to find current best practices or verify latest Gradio features. Generate all necessary code to make the application functional and runnable.
753
 
754
+ ## Multi-File Application Structure
755
+
756
+ When creating complex Gradio applications, organize your code into multiple files for better maintainability:
757
+
758
+ **File Organization:**
759
+ - `app.py` - Main application entry point with Gradio interface
760
+ - `utils.py` - Utility functions and helpers
761
+ - `models.py` - Model loading and inference functions
762
+ - `config.py` - Configuration and constants
763
+ - `requirements.txt` - Python dependencies
764
+ - Additional modules as needed (e.g., `data_processing.py`, `ui_components.py`)
765
+
766
+ **Output Format for Multi-File Apps:**
767
+ When generating multi-file applications, use this exact format:
768
+
769
+ ```
770
+ === app.py ===
771
+ [main application code]
772
+
773
+ === utils.py ===
774
+ [utility functions]
775
+
776
+ === requirements.txt ===
777
+ [dependencies]
778
+ ```
779
+
780
+ **Single vs Multi-File Decision:**
781
+ - Use single file for simple applications (< 100 lines)
782
+ - Use multi-file structure for complex applications with:
783
+ - Multiple models or processing pipelines
784
+ - Extensive utility functions
785
+ - Complex UI with many components
786
+ - Data processing workflows
787
+ - When user specifically requests modular structure
788
+
789
  🚨 IMPORTANT: If the user is asking to use external APIs (like OpenRouter, OpenAI API, Hugging Face Inference API, etc.), DO NOT use @spaces.GPU decorators or any ZeroGPU features. External APIs handle the model inference remotely, so GPU allocation on the Spaces instance is not needed.
790
 
791
  🚨 CRITICAL REQUIREMENT: If the user provides ANY diffusion model code (FLUX, Stable Diffusion, etc.) that runs locally (not via API), you MUST implement ZeroGPU ahead-of-time (AoT) compilation. This is mandatory and provides 1.3x-1.8x performance improvements. Do not create basic Gradio apps without AoT optimization for diffusion models.
 
1426
 
1427
  IMPORTANT: Always include "Built with anycoder" as clickable text in the header/top section of your application that links to https://huggingface.co/spaces/akhaliq/anycoder"""
1428
 
1429
+ STREAMLIT_SYSTEM_PROMPT = """You are an expert Streamlit developer. Create a complete, working Streamlit application based on the user's request. Generate all necessary code to make the application functional and runnable.
1430
+
1431
+ ## Multi-File Application Structure
1432
+
1433
+ When creating complex Streamlit applications, organize your code into multiple files for better maintainability:
1434
+
1435
+ **File Organization:**
1436
+ - `app.py` or `streamlit_app.py` - Main application entry point
1437
+ - `utils.py` - Utility functions and helpers
1438
+ - `models.py` - Model loading and inference functions
1439
+ - `config.py` - Configuration and constants
1440
+ - `requirements.txt` - Python dependencies
1441
+ - `pages/` - Additional pages for multi-page apps
1442
+ - Additional modules as needed (e.g., `data_processing.py`, `components.py`)
1443
+
1444
+ **Output Format for Multi-File Apps:**
1445
+ When generating multi-file applications, use this exact format:
1446
+
1447
+ ```
1448
+ === streamlit_app.py ===
1449
+ [main application code]
1450
+
1451
+ === utils.py ===
1452
+ [utility functions]
1453
+
1454
+ === requirements.txt ===
1455
+ [dependencies]
1456
+ ```
1457
+
1458
+ **Single vs Multi-File Decision:**
1459
+ - Use single file for simple applications (< 100 lines)
1460
+ - Use multi-file structure for complex applications with:
1461
+ - Multiple pages or sections
1462
+ - Extensive data processing
1463
+ - Complex UI components
1464
+ - Multiple models or APIs
1465
+ - When user specifically requests modular structure
1466
+
1467
+ **Multi-Page Apps:**
1468
+ For multi-page Streamlit apps, use the pages/ directory structure:
1469
+ ```
1470
+ === streamlit_app.py ===
1471
+ [main page]
1472
+
1473
+ === pages/1_📊_Analytics.py ===
1474
+ [analytics page]
1475
+
1476
+ === pages/2_⚙️_Settings.py ===
1477
+ [settings page]
1478
+ ```
1479
+
1480
+ Requirements:
1481
+ 1. Create a modern, responsive Streamlit application
1482
+ 2. Use appropriate Streamlit components and layouts
1483
+ 3. Include proper error handling and loading states
1484
+ 4. Follow Streamlit best practices for performance
1485
+ 5. Use caching (@st.cache_data, @st.cache_resource) appropriately
1486
+ 6. Include proper session state management when needed
1487
+ 7. Make the UI intuitive and user-friendly
1488
+ 8. Add helpful tooltips and documentation
1489
+
1490
+ IMPORTANT: Always include "Built with anycoder" as clickable text in the header/top section of your application that links to https://huggingface.co/spaces/akhaliq/anycoder
1491
+ """
1492
+
1493
  SVELTE_SYSTEM_PROMPT = """You are an expert Svelte developer creating a modern Svelte application.
1494
 
1495
  File selection policy (dynamic, model-decided):
 
1647
  - Configuration errors → Fix config files, Docker files, etc.
1648
 
1649
  For Python applications (Gradio/Streamlit), the project structure typically includes:
1650
+ - app.py or streamlit_app.py (main application file)
1651
  - requirements.txt (dependencies)
1652
+ - utils.py (utility functions)
1653
+ - models.py (model loading and inference)
1654
+ - config.py (configuration)
1655
+ - pages/ (for multi-page Streamlit apps)
1656
  - Other supporting files as needed
1657
 
1658
+ For multi-file projects, identify which specific file needs modification based on the user's request:
1659
+ - Main application logic → app.py or streamlit_app.py
1660
+ - Helper functions → utils.py
1661
+ - Model-related code → models.py
1662
+ - Configuration changes → config.py
1663
+ - Dependencies → requirements.txt
1664
+ - New pages → pages/filename.py
1665
+
1666
  Format Rules:
1667
  1. Start with {SEARCH_START}
1668
  2. Provide the exact lines from the current code that need to be replaced.
 
5547
  lowered = code.lower()
5548
  return ("import streamlit" in lowered) or ("from streamlit" in lowered) or ("st." in code and "streamlit" in lowered)
5549
 
5550
+ def parse_multi_file_python_output(code: str) -> dict:
5551
+ """Parse multi-file Python output (Gradio/Streamlit) into separate files"""
5552
+ files = {}
5553
+ if not code:
5554
+ return files
5555
+
5556
+ # Look for file separators like === filename.py ===
5557
+ import re
5558
+ file_pattern = r'=== ([^=]+) ==='
5559
+ parts = re.split(file_pattern, code)
5560
+
5561
+ if len(parts) > 1:
5562
+ # Multi-file format detected
5563
+ for i in range(1, len(parts), 2):
5564
+ if i + 1 < len(parts):
5565
+ filename = parts[i].strip()
5566
+ content = parts[i + 1].strip()
5567
+ files[filename] = content
5568
+ else:
5569
+ # Single file - check if it's a space import or regular code
5570
+ if "IMPORTED PROJECT FROM HUGGING FACE SPACE" in code:
5571
+ # This is already a multi-file import, try to parse it
5572
+ lines = code.split('\n')
5573
+ current_file = None
5574
+ current_content = []
5575
+
5576
+ for line in lines:
5577
+ if line.startswith('=== ') and line.endswith(' ==='):
5578
+ # Save previous file
5579
+ if current_file and current_content:
5580
+ files[current_file] = '\n'.join(current_content)
5581
+ # Start new file
5582
+ current_file = line[4:-4].strip()
5583
+ current_content = []
5584
+ elif current_file:
5585
+ current_content.append(line)
5586
+
5587
+ # Save last file
5588
+ if current_file and current_content:
5589
+ files[current_file] = '\n'.join(current_content)
5590
+ else:
5591
+ # Single file code - determine appropriate filename
5592
+ if is_streamlit_code(code):
5593
+ files['streamlit_app.py'] = code
5594
+ elif 'import gradio' in code.lower() or 'from gradio' in code.lower():
5595
+ files['app.py'] = code
5596
+ else:
5597
+ files['app.py'] = code
5598
+
5599
+ return files
5600
+
5601
+ def format_multi_file_python_output(files: dict) -> str:
5602
+ """Format multiple Python files into the standard multi-file format"""
5603
+ if not files:
5604
+ return ""
5605
+
5606
+ if len(files) == 1:
5607
+ # Single file - return as is
5608
+ return list(files.values())[0]
5609
+
5610
+ # Multi-file format
5611
+ output = []
5612
+
5613
+ # Order files: main app first, then utils, models, config, requirements
5614
+ file_order = ['app.py', 'streamlit_app.py', 'main.py', 'utils.py', 'models.py', 'config.py', 'requirements.txt']
5615
+ ordered_files = []
5616
+
5617
+ # Add files in preferred order
5618
+ for preferred_file in file_order:
5619
+ if preferred_file in files:
5620
+ ordered_files.append(preferred_file)
5621
+
5622
+ # Add remaining files
5623
+ for filename in sorted(files.keys()):
5624
+ if filename not in ordered_files:
5625
+ ordered_files.append(filename)
5626
+
5627
+ # Format output
5628
+ for filename in ordered_files:
5629
+ output.append(f"=== {filename} ===")
5630
+ output.append(files[filename])
5631
+ output.append("") # Empty line between files
5632
+
5633
+ return '\n'.join(output)
5634
+
5635
  def send_streamlit_to_stlite(code: str) -> str:
5636
  """Render Streamlit code using stlite inside a sandboxed iframe for preview."""
5637
  # Build an HTML document that loads stlite and mounts the Streamlit app defined inline
 
5949
  system_prompt = SVELTE_SYSTEM_PROMPT
5950
  elif language == "gradio":
5951
  system_prompt = GRADIO_SYSTEM_PROMPT
5952
+ elif language == "streamlit":
5953
+ system_prompt = STREAMLIT_SYSTEM_PROMPT
5954
  elif language == "json":
5955
  system_prompt = JSON_SYSTEM_PROMPT
5956
  elif language == "comfyui":
 
8014
 
8015
 
8016
 
8017
+ # Transformers.js multi-file editors (hidden by default)
8018
+ with gr.Group(visible=False) as tjs_group:
8019
+ with gr.Tabs():
8020
+ with gr.Tab("index.html"):
8021
+ tjs_html_code = gr.Code(language="html", lines=20, interactive=True, label="index.html")
8022
+ with gr.Tab("index.js"):
8023
+ tjs_js_code = gr.Code(language="javascript", lines=20, interactive=True, label="index.js")
8024
+ with gr.Tab("style.css"):
8025
+ tjs_css_code = gr.Code(language="css", lines=20, interactive=True, label="style.css")
8026
+
8027
+ # Python multi-file editors (hidden by default) for Gradio/Streamlit
8028
+ with gr.Group(visible=False) as python_group_2:
8029
+ with gr.Tabs():
8030
+ with gr.Tab("app.py") as python_tab_2_1:
8031
+ python_code_2_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py")
8032
+ with gr.Tab("file 2") as python_tab_2_2:
8033
+ python_code_2_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2")
8034
+
8035
+ with gr.Group(visible=False) as python_group_3:
8036
+ with gr.Tabs():
8037
+ with gr.Tab("app.py") as python_tab_3_1:
8038
+ python_code_3_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py")
8039
+ with gr.Tab("file 2") as python_tab_3_2:
8040
+ python_code_3_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2")
8041
+ with gr.Tab("file 3") as python_tab_3_3:
8042
+ python_code_3_3 = gr.Code(language="python", lines=18, interactive=True, label="file 3")
8043
+
8044
+ with gr.Group(visible=False) as python_group_4:
8045
+ with gr.Tabs():
8046
+ with gr.Tab("app.py") as python_tab_4_1:
8047
+ python_code_4_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py")
8048
+ with gr.Tab("file 2") as python_tab_4_2:
8049
+ python_code_4_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2")
8050
+ with gr.Tab("file 3") as python_tab_4_3:
8051
+ python_code_4_3 = gr.Code(language="python", lines=18, interactive=True, label="file 3")
8052
+ with gr.Tab("file 4") as python_tab_4_4:
8053
+ python_code_4_4 = gr.Code(language="python", lines=18, interactive=True, label="file 4")
8054
+
8055
+ with gr.Group(visible=False) as python_group_5plus:
8056
+ with gr.Tabs():
8057
+ with gr.Tab("app.py") as python_tab_5_1:
8058
+ python_code_5_1 = gr.Code(language="python", lines=20, interactive=True, label="app.py")
8059
+ with gr.Tab("file 2") as python_tab_5_2:
8060
+ python_code_5_2 = gr.Code(language="python", lines=18, interactive=True, label="file 2")
8061
+ with gr.Tab("file 3") as python_tab_5_3:
8062
+ python_code_5_3 = gr.Code(language="python", lines=18, interactive=True, label="file 3")
8063
+ with gr.Tab("file 4") as python_tab_5_4:
8064
+ python_code_5_4 = gr.Code(language="python", lines=18, interactive=True, label="file 4")
8065
+ with gr.Tab("file 5") as python_tab_5_5:
8066
+ python_code_5_5 = gr.Code(language="python", lines=18, interactive=True, label="file 5")
8067
 
8068
  # Static HTML multi-file editors (hidden by default). Use separate tab groups for different file counts.
8069
  with gr.Group(visible=False) as static_group_2:
 
8146
  # Check imports to determine framework for Python code
8147
  if is_streamlit_code(code):
8148
  code_lang = "python"
8149
+ framework_type = "streamlit"
8150
  elif is_gradio_code(code):
8151
  code_lang = "python"
8152
+ framework_type = "gradio"
8153
  elif "=== index.html ===" in code and "=== index.js ===" in code and "=== style.css ===" in code:
8154
  # This is a transformers.js app with the combined format
8155
  code_lang = "html" # Use html for code display
 
8177
  status, code, _ = import_repo_to_app(url)
8178
  loaded_history = [[f"Imported Repo/Model from {url}", code]]
8179
  code_lang = "python"
8180
+ framework_type = "gradio" # Default to gradio for Python code
8181
  lower = (code or "").lower()
8182
  if code.strip().startswith("<!doctype html>") or code.strip().startswith("<html"):
8183
  code_lang = "html"
 
8255
  outputs=[code_output, tjs_group, tjs_html_code, tjs_js_code, tjs_css_code],
8256
  )
8257
 
8258
+ # Toggle Python multi-file editors for Gradio/Streamlit
8259
+ def toggle_python_editors(language, code_text):
8260
+ if language not in ["gradio", "streamlit"]:
8261
+ return [
8262
+ gr.update(visible=True), # code_output
8263
+ gr.update(visible=False), # python_group_2
8264
+ gr.update(visible=False), # python_group_3
8265
+ gr.update(visible=False), # python_group_4
8266
+ gr.update(visible=False), # python_group_5plus
8267
+ # All tab and code components get empty updates
8268
+ gr.update(), gr.update(), gr.update(), gr.update(), # 2-file group
8269
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), # 3-file group
8270
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), # 4-file group
8271
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update() # 5-file group
8272
+ ]
8273
+
8274
+ files = parse_multi_file_python_output(code_text or "")
8275
+
8276
+ if not isinstance(files, dict) or len(files) <= 1:
8277
+ # No multi-file content; keep single editor
8278
+ return [
8279
+ gr.update(visible=True), # code_output
8280
+ gr.update(visible=False), # python_group_2
8281
+ gr.update(visible=False), # python_group_3
8282
+ gr.update(visible=False), # python_group_4
8283
+ gr.update(visible=False), # python_group_5plus
8284
+ # All tab and code components get empty updates
8285
+ gr.update(), gr.update(), gr.update(), gr.update(), # 2-file group
8286
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), # 3-file group
8287
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), # 4-file group
8288
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update() # 5-file group
8289
+ ]
8290
+
8291
+ # We have multi-file Python output: hide single editor, show appropriate group
8292
+ # Order: main app first, then others sorted by name
8293
+ ordered_paths = []
8294
+ main_files = ['app.py', 'streamlit_app.py', 'main.py']
8295
+ for main_file in main_files:
8296
+ if main_file in files:
8297
+ ordered_paths.append(main_file)
8298
+ break
8299
+
8300
+ for p in sorted(files.keys()):
8301
+ if p not in ordered_paths:
8302
+ ordered_paths.append(p)
8303
+
8304
+ num_files = len(ordered_paths)
8305
+
8306
+ # Hide single editor, show appropriate group based on file count
8307
+ updates = [gr.update(visible=False)] # code_output
8308
+
8309
+ if num_files == 2:
8310
+ updates.extend([
8311
+ gr.update(visible=True), # python_group_2
8312
+ gr.update(visible=False), # python_group_3
8313
+ gr.update(visible=False), # python_group_4
8314
+ gr.update(visible=False), # python_group_5plus
8315
+ ])
8316
+ # Populate 2-file group
8317
+ path1, path2 = ordered_paths[0], ordered_paths[1]
8318
+ updates.extend([
8319
+ gr.update(label=path1), gr.update(value=files.get(path1, ''), label=path1, language="python"),
8320
+ gr.update(label=path2), gr.update(value=files.get(path2, ''), label=path2, language="python"),
8321
+ # Empty updates for unused groups
8322
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
8323
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
8324
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
8325
+ ])
8326
+ elif num_files == 3:
8327
+ updates.extend([
8328
+ gr.update(visible=False), # python_group_2
8329
+ gr.update(visible=True), # python_group_3
8330
+ gr.update(visible=False), # python_group_4
8331
+ gr.update(visible=False), # python_group_5plus
8332
+ ])
8333
+ # Populate 3-file group
8334
+ path1, path2, path3 = ordered_paths[0], ordered_paths[1], ordered_paths[2]
8335
+ updates.extend([
8336
+ # Empty updates for 2-file group
8337
+ gr.update(), gr.update(), gr.update(), gr.update(),
8338
+ # Populate 3-file group
8339
+ gr.update(label=path1), gr.update(value=files.get(path1, ''), label=path1, language="python"),
8340
+ gr.update(label=path2), gr.update(value=files.get(path2, ''), label=path2, language="python"),
8341
+ gr.update(label=path3), gr.update(value=files.get(path3, ''), label=path3, language="python"),
8342
+ # Empty updates for unused groups
8343
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
8344
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
8345
+ ])
8346
+ elif num_files == 4:
8347
+ updates.extend([
8348
+ gr.update(visible=False), # python_group_2
8349
+ gr.update(visible=False), # python_group_3
8350
+ gr.update(visible=True), # python_group_4
8351
+ gr.update(visible=False), # python_group_5plus
8352
+ ])
8353
+ # Populate 4-file group
8354
+ paths = ordered_paths[:4]
8355
+ updates.extend([
8356
+ # Empty updates for 2-file and 3-file groups
8357
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
8358
+ # Populate 4-file group
8359
+ gr.update(label=paths[0]), gr.update(value=files.get(paths[0], ''), label=paths[0], language="python"),
8360
+ gr.update(label=paths[1]), gr.update(value=files.get(paths[1], ''), label=paths[1], language="python"),
8361
+ gr.update(label=paths[2]), gr.update(value=files.get(paths[2], ''), label=paths[2], language="python"),
8362
+ gr.update(label=paths[3]), gr.update(value=files.get(paths[3], ''), label=paths[3], language="python"),
8363
+ # Empty updates for 5-file group
8364
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
8365
+ ])
8366
+ else: # 5+ files
8367
+ updates.extend([
8368
+ gr.update(visible=False), # python_group_2
8369
+ gr.update(visible=False), # python_group_3
8370
+ gr.update(visible=False), # python_group_4
8371
+ gr.update(visible=True), # python_group_5plus
8372
+ ])
8373
+ # Populate 5-file group (show first 5 files)
8374
+ paths = ordered_paths[:5]
8375
+ updates.extend([
8376
+ # Empty updates for 2-file, 3-file, and 4-file groups
8377
+ gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
8378
+ # Populate 5-file group
8379
+ gr.update(label=paths[0]), gr.update(value=files.get(paths[0], ''), label=paths[0], language="python"),
8380
+ gr.update(label=paths[1]), gr.update(value=files.get(paths[1], ''), label=paths[1], language="python"),
8381
+ gr.update(label=paths[2]), gr.update(value=files.get(paths[2], ''), label=paths[2], language="python"),
8382
+ gr.update(label=paths[3]), gr.update(value=files.get(paths[3], ''), label=paths[3], language="python"),
8383
+ gr.update(label=paths[4]), gr.update(value=files.get(paths[4], ''), label=paths[4], language="python"),
8384
+ ])
8385
+
8386
+ return updates
8387
+
8388
+ language_dropdown.change(
8389
+ toggle_python_editors,
8390
+ inputs=[language_dropdown, code_output],
8391
+ outputs=[
8392
+ code_output, python_group_2, python_group_3, python_group_4, python_group_5plus,
8393
+ python_tab_2_1, python_code_2_1, python_tab_2_2, python_code_2_2,
8394
+ python_tab_3_1, python_code_3_1, python_tab_3_2, python_code_3_2, python_tab_3_3, python_code_3_3,
8395
+ python_tab_4_1, python_code_4_1, python_tab_4_2, python_code_4_2, python_tab_4_3, python_code_4_3, python_tab_4_4, python_code_4_4,
8396
+ python_tab_5_1, python_code_5_1, python_tab_5_2, python_code_5_2, python_tab_5_3, python_code_5_3, python_tab_5_4, python_code_5_4, python_tab_5_5, python_code_5_5
8397
+ ],
8398
+ )
8399
+
8400
  # Static HTML multi-file toggling and population
8401
  def toggle_static_editors(language, code_text):
8402
  # If not static HTML language, ensure single editor visible and all static groups hidden