from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool import datetime import requests import pytz import yaml import base64 import io from PIL import Image from tools.final_answer import FinalAnswerTool from Gradio_UI import GradioUI # Enhanced design-to-code tool @tool def design_to_code_generator(design_prompt: str, image_path: str = None) -> str: """A tool that generates HTML, CSS, and JavaScript code based on a design description or image. Args: design_prompt: A detailed description of the desired web design/interface image_path: Optional path to an image file for visual reference """ # Base HTML template with modern styling capabilities html_template = """ {title} {html_content} """ # Analyze the design prompt to determine components and styling components = analyze_design_prompt(design_prompt) # Generate CSS based on design requirements css_content = generate_css_from_prompt(design_prompt, components) # Generate HTML structure html_content = generate_html_structure(design_prompt, components) # Generate JavaScript for interactivity js_content = generate_javascript_features(design_prompt, components) # Determine page title from prompt title = extract_title_from_prompt(design_prompt) # Combine everything final_code = html_template.format( title=title, css_content=css_content, html_content=html_content, js_content=js_content ) return f"Generated HTML/CSS/JS code:\n\n```html\n{final_code}\n```" def analyze_design_prompt(prompt: str) -> dict: """Analyze the design prompt to identify components and features needed.""" prompt_lower = prompt.lower() components = { 'has_header': any(word in prompt_lower for word in ['header', 'navigation', 'nav', 'menu']), 'has_hero': any(word in prompt_lower for word in ['hero', 'banner', 'main section', 'landing']), 'has_cards': any(word in prompt_lower for word in ['card', 'cards', 'grid', 'boxes']), 'has_form': any(word in prompt_lower for word in ['form', 'input', 'contact', 'signup', 'login']), 'has_footer': any(word in prompt_lower for word in ['footer', 'bottom']), 'has_sidebar': any(word in prompt_lower for word in ['sidebar', 'aside', 'side panel']), 'has_gallery': any(word in prompt_lower for word in ['gallery', 'images', 'photos', 'portfolio']), 'has_animation': any(word in prompt_lower for word in ['animate', 'animation', 'hover', 'interactive']), 'color_scheme': extract_colors_from_prompt(prompt), 'layout_type': determine_layout_type(prompt), 'style_theme': determine_style_theme(prompt) } return components def extract_colors_from_prompt(prompt: str) -> list: """Extract color preferences from the prompt.""" colors = [] color_words = ['blue', 'red', 'green', 'purple', 'orange', 'yellow', 'pink', 'black', 'white', 'gray', 'dark', 'light'] for color in color_words: if color in prompt.lower(): colors.append(color) return colors if colors else ['blue', 'white'] # Default colors def determine_layout_type(prompt: str) -> str: """Determine the layout type based on the prompt.""" prompt_lower = prompt.lower() if any(word in prompt_lower for word in ['dashboard', 'admin', 'panel']): return 'dashboard' elif any(word in prompt_lower for word in ['landing', 'homepage', 'marketing']): return 'landing' elif any(word in prompt_lower for word in ['blog', 'article', 'post']): return 'blog' elif any(word in prompt_lower for word in ['portfolio', 'gallery', 'showcase']): return 'portfolio' else: return 'general' def determine_style_theme(prompt: str) -> str: """Determine the visual style theme.""" prompt_lower = prompt.lower() if any(word in prompt_lower for word in ['modern', 'clean', 'minimal']): return 'modern' elif any(word in prompt_lower for word in ['dark', 'night', 'black']): return 'dark' elif any(word in prompt_lower for word in ['colorful', 'vibrant', 'bright']): return 'colorful' elif any(word in prompt_lower for word in ['professional', 'corporate', 'business']): return 'professional' else: return 'modern' def fix_zindex_conflicts(css_content: str) -> str: """Fix common z-index conflicts in generated CSS.""" # Define z-index hierarchy for common components zindex_hierarchy = { 'modal': 9999, 'modal-overlay': 9998, 'dropdown': 200, 'tooltip': 300, 'header': 1000, 'nav': 1001, 'sticky': 100, 'card-hover': 13, 'card': 12, 'form': 10, 'content': 1, 'background': -1 } # Add z-index management comment fixed_css = """ /* Z-Index Management System */ /* Modal: 9999, Dropdowns: 200-299, Headers: 1000-1099, Content: 1-99, Background: -1 */ """ + css_content return fixed_css def generate_css_from_prompt(prompt: str, components: dict) -> str: """Generate CSS based on the design requirements.""" # Base styles css = """ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Arial', sans-serif; line-height: 1.6; color: #333; } """ # Add theme-specific styles if components['style_theme'] == 'dark': css += """ body { background-color: #1a1a1a; color: #ffffff; } """ elif components['style_theme'] == 'colorful': css += """ body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; } """ # Add component-specific styles with proper z-index management if components['has_header']: css += """ .header { background-color: #2c3e50; color: white; padding: 1rem 0; position: sticky; top: 0; z-index: 1000; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .nav { display: flex; justify-content: space-between; align-items: center; max-width: 1200px; margin: 0 auto; padding: 0 2rem; position: relative; z-index: 1001; } .nav ul { display: flex; list-style: none; gap: 2rem; } .nav a { color: white; text-decoration: none; transition: color 0.3s; position: relative; z-index: 1002; } .nav a:hover { color: #3498db; } """ if components['has_hero']: css += """ .hero { background: linear-gradient(135deg, #3498db, #2c3e50); color: white; text-align: center; padding: 8rem 2rem; position: relative; z-index: 1; overflow: hidden; } .hero::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: inherit; z-index: -1; } .hero-content { position: relative; z-index: 2; max-width: 800px; margin: 0 auto; } .hero h1 { font-size: 3rem; margin-bottom: 1rem; position: relative; z-index: 3; } .hero p { font-size: 1.2rem; margin-bottom: 2rem; position: relative; z-index: 3; } .btn { display: inline-block; background-color: #e74c3c; color: white; padding: 1rem 2rem; text-decoration: none; border-radius: 5px; transition: all 0.3s; position: relative; z-index: 3; border: none; cursor: pointer; } .btn:hover { background-color: #c0392b; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3); } """ if components['has_cards']: css += """ .cards-section { padding: 4rem 2rem; max-width: 1200px; margin: 0 auto; position: relative; z-index: 10; } .cards-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; margin-top: 2rem; position: relative; z-index: 11; } .card { background: white; border-radius: 10px; padding: 2rem; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); transition: all 0.3s; position: relative; z-index: 12; overflow: hidden; } .card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(45deg, transparent, rgba(52, 152, 219, 0.1), transparent); opacity: 0; transition: opacity 0.3s; z-index: -1; } .card:hover { transform: translateY(-5px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); z-index: 13; } .card:hover::before { opacity: 1; } .card h3 { position: relative; z-index: 2; margin-bottom: 1rem; } .card p { position: relative; z-index: 2; } """ if components['has_form']: css += """ .form-section { padding: 4rem 2rem; background-color: #f8f9fa; position: relative; z-index: 5; } .form-container { max-width: 600px; margin: 0 auto; background: white; padding: 2rem; border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); position: relative; z-index: 6; } .form-group { margin-bottom: 1.5rem; position: relative; z-index: 7; } .form-group label { display: block; margin-bottom: 0.5rem; font-weight: bold; position: relative; z-index: 8; } .form-group input, .form-group textarea { width: 100%; padding: 0.75rem; border: 1px solid #ddd; border-radius: 5px; font-size: 1rem; position: relative; z-index: 8; background: white; transition: all 0.3s; } .form-group input:focus, .form-group textarea:focus { outline: none; border-color: #3498db; box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1); z-index: 9; } .form-group input:focus + .focus-indicator, .form-group textarea:focus + .focus-indicator { opacity: 1; transform: scaleX(1); } """ if components['has_footer']: css += """ .footer { background-color: #2c3e50; color: white; text-align: center; padding: 2rem 0; margin-top: 4rem; position: relative; z-index: 100; } .footer p { position: relative; z-index: 101; } """ # Add animations if requested with proper z-index if components['has_animation']: css += """ @keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideInFromLeft { from { opacity: 0; transform: translateX(-50px); } to { opacity: 1; transform: translateX(0); } } .animate-on-scroll { animation: fadeInUp 0.6s ease-out forwards; } .animate-slide { animation: slideInFromLeft 0.8s ease-out forwards; } /* Ensure animated elements don't interfere with z-index */ .animate-on-scroll, .animate-slide { position: relative; z-index: auto; } """ # Add modal and overlay styles with high z-index css += """ /* Modal and overlay z-index management */ .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 9998; display: none; } .modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 2rem; border-radius: 10px; z-index: 9999; max-width: 90vw; max-height: 90vh; overflow: auto; } /* Dropdown menus */ .dropdown { position: relative; z-index: 200; } .dropdown-menu { position: absolute; top: 100%; left: 0; background: white; border: 1px solid #ddd; border-radius: 5px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); z-index: 201; min-width: 200px; display: none; } .dropdown:hover .dropdown-menu { display: block; } /* Tooltips */ .tooltip { position: relative; z-index: 300; } .tooltip::after { content: attr(data-tooltip); position: absolute; bottom: 125%; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 0.5rem; border-radius: 4px; font-size: 0.875rem; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.3s; z-index: 301; } .tooltip:hover::after { opacity: 1; } /* Responsive z-index adjustments */ @media (max-width: 768px) { .header { z-index: 1100; } .nav { z-index: 1101; } .mobile-menu { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(44, 62, 80, 0.95); z-index: 1200; display: none; } .mobile-menu.active { display: flex; flex-direction: column; justify-content: center; align-items: center; } } """ # Fix z-index conflicts and return optimized CSS return fix_zindex_conflicts(css) def generate_html_structure(prompt: str, components: dict) -> str: """Generate HTML structure based on components.""" html = "" # Header if components['has_header']: html += """
""" # Hero section if components['has_hero']: html += """

Welcome to Our Amazing Service

Transform your ideas into reality with our cutting-edge solutions

Get Started
""" # Cards section if components['has_cards']: html += """

Our Services

Service One

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Service Two

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Service Three

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

""" # Form section if components['has_form']: html += """

Contact Us

""" # Footer if components['has_footer']: html += """ """ return html def generate_javascript_features(prompt: str, components: dict) -> str: """Generate JavaScript for interactivity.""" js = """ // Smooth scrolling for navigation links document.addEventListener('DOMContentLoaded', function() { const links = document.querySelectorAll('a[href^="#"]'); links.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); """ # Add form handling if form exists if components['has_form']: js += """ // Form submission handling const contactForm = document.getElementById('contactForm'); if (contactForm) { contactForm.addEventListener('submit', function(e) { e.preventDefault(); // Get form data const formData = new FormData(this); const name = formData.get('name'); const email = formData.get('email'); const message = formData.get('message'); // Simple validation if (name && email && message) { alert('Thank you for your message! We will get back to you soon.'); this.reset(); } else { alert('Please fill in all fields.'); } }); } """ # Add scroll animations if requested if components['has_animation']: js += """ // Scroll animations const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-on-scroll'); } }); }, observerOptions); // Observe cards and other elements const animatedElements = document.querySelectorAll('.card, .hero-content'); animatedElements.forEach(el => observer.observe(el)); """ js += """ }); """ return js def extract_title_from_prompt(prompt: str) -> str: """Extract a suitable title from the design prompt.""" prompt_lower = prompt.lower() if 'dashboard' in prompt_lower: return 'Dashboard' elif 'portfolio' in prompt_lower: return 'Portfolio' elif 'landing' in prompt_lower or 'homepage' in prompt_lower: return 'Welcome' elif 'blog' in prompt_lower: return 'Blog' elif 'contact' in prompt_lower: return 'Contact Us' else: return 'My Website' @tool def get_current_time_in_timezone(timezone: str) -> str: """A tool that fetches the current local time in a specified timezone. Args: timezone: A string representing a valid timezone (e.g., 'America/New_York'). """ try: # Create timezone object tz = pytz.timezone(timezone) # Get current time in that timezone local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S") return f"The current local time in {timezone} is: {local_time}" except Exception as e: return f"Error fetching time for timezone '{timezone}': {str(e)}" @tool def image_analyzer_for_design(image_path: str, analysis_type: str = "design") -> str: """Analyze an uploaded image to extract design elements and generate code suggestions. Args: image_path: Path to the image file analysis_type: Type of analysis to perform ('design', 'layout', 'colors') """ try: # This is a placeholder for image analysis # In a real implementation, you would use computer vision or AI models return f"Image analysis for {image_path}: Detected modern layout with clean design elements. Suggested color scheme: blue and white. Layout appears to be a landing page with header, hero section, and cards." except Exception as e: return f"Error analyzing image: {str(e)}" final_answer = FinalAnswerTool() # Model configuration model = HfApiModel( max_tokens=2096, temperature=0.5, model_id='Qwen/Qwen2.5-Coder-32B-Instruct', custom_role_conversions=None, ) # Load additional tools try: image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True) except: print("Image generation tool not available") image_generation_tool = None # Load prompts with open("prompts.yaml", 'r') as stream: prompt_templates = yaml.safe_load(stream) # Create agent with enhanced tools tools = [ final_answer, design_to_code_generator, get_current_time_in_timezone, image_analyzer_for_design, ] # Add image generation tool if available if image_generation_tool: tools.append(image_generation_tool) agent = CodeAgent( model=model, tools=tools, max_steps=6, verbosity_level=1, grammar=None, planning_interval=None, name="DesignToCodeAgent", # Fixed: removed spaces and hyphens description="An AI agent that converts design descriptions and images into functional HTML, CSS, and JavaScript code.", prompt_templates=prompt_templates ) # Launch the Gradio interface GradioUI(agent).launch()