| """ |
| LITEHAT WIZARD CHAT INTERFACE |
| The conversational face of Litehat — a Gradio chat app where users |
| speak their dreams and the Wizard manifests them. |
| |
| Every interaction is a spell. The Wizard doesn't just respond — |
| it builds, tests, deploys, and returns live URLs, all without |
| asking for permission. |
| |
| Architecture: |
| User types dream → Wizard analyzes → Plans → Builds → Tests → Deploys |
| All visible as animated spells in the chat interface. |
| """ |
|
|
| import time |
| import json |
| import asyncio |
| import threading |
| from typing import Optional, Dict, Any, List, Generator |
| from dataclasses import dataclass, field |
| from enum import Enum |
| from pathlib import Path |
|
|
| import gradio as gr |
|
|
|
|
| |
| |
| |
|
|
| SPELL_DATA = { |
| "summon": { |
| "name": "Summon", |
| "emoji": "🧙♂️", |
| "color": "#9b59b6", |
| "description": "The Wizard awakens, attuning to your intent...", |
| "duration": 1.5, |
| }, |
| "dreamweave": { |
| "name": "Dreamweave", |
| "emoji": "🔮", |
| "color": "#8e44ad", |
| "description": "Parsing your dream into crystalline architecture...", |
| "duration": 2.0, |
| }, |
| "scry": { |
| "name": "Scry", |
| "emoji": "🔍", |
| "color": "#2980b9", |
| "description": "Gazing into the codebase, reading the runes of existing logic...", |
| "duration": 1.0, |
| }, |
| "forge": { |
| "name": "Forge", |
| "emoji": "⚡", |
| "color": "#f39c12", |
| "description": "Hammering code into existence across multiple files...", |
| "duration": 3.0, |
| }, |
| "alchemize": { |
| "name": "Alchemize", |
| "emoji": "🧪", |
| "color": "#27ae60", |
| "description": "Testing the creation — distilling bugs into fixes...", |
| "duration": 2.5, |
| }, |
| "ward": { |
| "name": "Ward", |
| "emoji": "🛡️", |
| "color": "#e74c3c", |
| "description": "A flaw detected! The Wizard is weaving a counter-spell...", |
| "duration": 2.0, |
| }, |
| "portal": { |
| "name": "Portal", |
| "emoji": "🌐", |
| "color": "#3498db", |
| "description": "Opening a gateway to the production realm...", |
| "duration": 2.5, |
| }, |
| "chronicle": { |
| "name": "Chronicle", |
| "emoji": "📜", |
| "color": "#1abc9c", |
| "description": "Inscribing this creation into the eternal record...", |
| "duration": 1.0, |
| }, |
| "complete": { |
| "name": "Manifestation Complete", |
| "emoji": "✨", |
| "color": "#2ecc71", |
| "description": "Your dream lives! Reality has been updated.", |
| "duration": 0.5, |
| }, |
| } |
|
|
|
|
| class SpellAnimation: |
| """Generates CSS/HTML for animated spell casting in the chat.""" |
|
|
| @staticmethod |
| def spell_banner(spell_id: str, message: str = "") -> str: |
| """Generate a spell announcement banner.""" |
| spell = SPELL_DATA.get(spell_id, SPELL_DATA["summon"]) |
| return f""" |
| <div style=" |
| background: linear-gradient(135deg, {spell['color']}22, {spell['color']}11); |
| border-left: 4px solid {spell['color']}; |
| border-radius: 8px; |
| padding: 12px 16px; |
| margin: 8px 0; |
| animation: spellPulse 2s ease-in-out infinite; |
| "> |
| <span style="font-size: 1.3em;">{spell['emoji']}</span> |
| <strong style="color: {spell['color']}; margin-left: 8px;">{spell['name']}</strong> |
| <br> |
| <span style="color: #b0b0b0; font-size: 0.9em;">{message or spell['description']}</span> |
| </div> |
| """ |
|
|
| @staticmethod |
| def artifact_card(name: str, artifact_type: str, details: str = "") -> str: |
| """Generate an artifact card for created files/URLs.""" |
| type_icons = { |
| "file": "📄", |
| "url": "🔗", |
| "test": "✅", |
| "deploy": "🚀", |
| "config": "⚙️", |
| "package": "📦", |
| } |
| icon = type_icons.get(artifact_type, "📦") |
| return f""" |
| <div style=" |
| background: #1a1a2e; |
| border: 1px solid #2a2a4e; |
| border-radius: 6px; |
| padding: 8px 12px; |
| margin: 4px 0; |
| font-family: monospace; |
| font-size: 0.85em; |
| "> |
| {icon} <span style="color: #7ec8e3;">{name}</span> |
| {f'<br><span style="color: #666;">{details}</span>' if details else ''} |
| </div> |
| """ |
|
|
| @staticmethod |
| def live_url_banner(url: str) -> str: |
| """Generate a live URL announcement.""" |
| return f""" |
| <div style=" |
| background: linear-gradient(135deg, #00b894, #00cec9); |
| border-radius: 12px; |
| padding: 20px; |
| margin: 12px 0; |
| text-align: center; |
| animation: glowPulse 2s ease-in-out infinite; |
| "> |
| <div style="font-size: 2em;">🔮</div> |
| <div style="font-size: 1.2em; font-weight: bold; color: white; margin: 8px 0;"> |
| YOUR CREATION IS LIVE |
| </div> |
| <a href="{url}" target="_blank" style=" |
| color: white; |
| font-size: 1.1em; |
| text-decoration: underline; |
| word-break: break-all; |
| ">{url}</a> |
| </div> |
| """ |
|
|
| @staticmethod |
| def error_card(error_msg: str, fix_attempted: bool = False) -> str: |
| """Generate an error/fix card.""" |
| return f""" |
| <div style=" |
| background: {'#2d1b1b' if not fix_attempted else '#1b2d1b'}; |
| border: 1px solid {'#e74c3c' if not fix_attempted else '#2ecc71'}; |
| border-radius: 8px; |
| padding: 12px; |
| margin: 8px 0; |
| "> |
| <span style="font-size: 1.1em;">{'🛡️' if fix_attempted else '⚠️'}</span> |
| <strong style="color: {'#2ecc71' if fix_attempted else '#e74c3c'};"> |
| {'Ward Applied — Fixed!' if fix_attempted else 'Anomaly Detected'} |
| </strong> |
| <br> |
| <span style="color: #aaa; font-size: 0.85em; font-family: monospace;">{error_msg}</span> |
| </div> |
| """ |
|
|
| @staticmethod |
| def thinking_indicator() -> str: |
| """Pulsing thinking indicator.""" |
| return """ |
| <div style="display: flex; align-items: center; gap: 8px; padding: 8px;"> |
| <div style=" |
| width: 8px; height: 8px; border-radius: 50%; |
| background: #9b59b6; |
| animation: dotPulse 1.4s ease-in-out infinite; |
| "></div> |
| <div style=" |
| width: 8px; height: 8px; border-radius: 50%; |
| background: #9b59b6; |
| animation: dotPulse 1.4s ease-in-out 0.2s infinite; |
| "></div> |
| <div style=" |
| width: 8px; height: 8px; border-radius: 50%; |
| background: #9b59b6; |
| animation: dotPulse 1.4s ease-in-out 0.4s infinite; |
| "></div> |
| <span style="color: #9b59b6; font-style: italic; margin-left: 4px;"> |
| The Wizard contemplates... |
| </span> |
| </div> |
| """ |
|
|
|
|
| |
| |
| |
|
|
| class WizardChatBrain: |
| """ |
| The brain behind the Wizard chat interface. |
| |
| Routes user messages through the full Litehat pipeline: |
| - Intent parsing (is this a dream? a question? a deployment request?) |
| - Spell orchestration (what spells need to be cast?) |
| - Holographic memory integration (remembering past conversations) |
| - Autonomous decision-making (no asking permission) |
| """ |
|
|
| def __init__(self): |
| self.conversation_history: List[Dict[str, str]] = [] |
| self.active_project: Optional[str] = None |
| self.deployed_urls: List[str] = [] |
| self.spells_cast: int = 0 |
| self.artifacts_created: List[Dict[str, str]] = [] |
|
|
| |
| try: |
| from .holographic_core import HolographicAssociativeMemory |
| self.hologram = HolographicAssociativeMemory(dimension=512, num_sheets=3) |
| self._has_ham = True |
| except (ImportError, RuntimeError): |
| self._has_ham = False |
|
|
| def process_message(self, message: str, chat_history: List[List[str]]) -> Generator: |
| """ |
| Process a user message through the Wizard pipeline. |
| |
| This is a generator that yields (response_text, html_spell_banners, artifacts) |
| at each step, enabling animated streaming in the chat UI. |
| """ |
| self.conversation_history.append({"role": "user", "content": message}) |
|
|
| |
| intent = self._classify_intent(message) |
|
|
| if intent == "dream": |
| yield from self._handle_dream(message, chat_history) |
| elif intent == "deploy": |
| yield from self._handle_deploy(message, chat_history) |
| elif intent == "question": |
| yield from self._handle_question(message, chat_history) |
| elif intent == "code_request": |
| yield from self._handle_code_request(message, chat_history) |
| elif intent == "heal": |
| yield from self._handle_heal(message, chat_history) |
| else: |
| yield from self._handle_casual(message, chat_history) |
|
|
| def _classify_intent(self, message: str) -> str: |
| """Classify user intent from message.""" |
| msg_lower = message.lower() |
|
|
| |
| dream_patterns = [ |
| "build", "create", "make", "develop", "generate", |
| "i want", "i need an app", "can you build", "help me make", |
| "design", "construct", "code me", "write me an app", |
| "i have an idea", "i'm thinking of", "dream", |
| ] |
| for p in dream_patterns: |
| if p in msg_lower: |
| return "dream" |
|
|
| |
| question_patterns = [ |
| "what", "how", "why", "can you", "explain", "tell me", |
| "what's", "how's", "?", |
| ] |
| if any(p in msg_lower for p in question_patterns) and not any( |
| p in msg_lower for p in dream_patterns |
| ): |
| return "question" |
|
|
| |
| code_patterns = [ |
| "fix", "debug", "refactor", "optimize", "add feature", |
| "implement", "rewrite", "update the", |
| ] |
| if any(p in msg_lower for p in code_patterns): |
| return "code_request" |
|
|
| |
| deploy_patterns = [ |
| "deploy", "ship", "launch", "publish", "go live", |
| "put it online", "push to production", |
| ] |
| if any(p in msg_lower for p in deploy_patterns): |
| return "deploy" |
|
|
| |
| heal_patterns = [ |
| "broken", "error", "crash", "not working", "fix it", |
| "down", "failed", |
| ] |
| if any(p in msg_lower for p in heal_patterns): |
| return "heal" |
|
|
| return "casual" |
|
|
| def _handle_dream(self, message: str, history: List[List[str]]) -> Generator: |
| """ |
| Handle a dream — the full manifest pipeline. |
| |
| Dreamweave → Scry → Forge → Alchemize → Portal → Chronicle |
| """ |
| banner = SpellAnimation.spell_banner |
|
|
| |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('summon')}" |
| f"\n\nAh, a new dream! Let me study what you've brought me..." |
| f"\n\n> *{message[:200]}{'...' if len(message) > 200 else ''}*" |
| f"\n\n🪄 I shall weave this into reality. Watch closely." |
| ), |
| "spell": "summon", |
| } |
| self.spells_cast += 1 |
|
|
| |
| architecture = self._parse_dream(message) |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('dreamweave')}" |
| f"\n\nI see the shape of your creation now:" |
| f"\n\n**🎯 Features:**" |
| + "".join(f"\n• {f}" for f in architecture["features"]) |
| + f"\n\n**⚙️ Tech Stack:**" |
| + "".join(f"\n• {t}" for t in architecture["tech_stack"]) |
| + f"\n\n**📐 Architecture Pattern:** {architecture['pattern']}" |
| + f"\n\nShall I proceed to forge this into code? (I will proceed autonomously — no need to confirm.)" |
| ), |
| "spell": "dreamweave", |
| } |
| self.spells_cast += 1 |
|
|
| |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('scry')}" |
| f"\n\nScanning the workspace... preparing the forge." |
| f"\n\n✅ Environment ready — all tools at my disposal." |
| ), |
| "spell": "scry", |
| } |
| self.spells_cast += 1 |
|
|
| |
| files = self._generate_project_files(architecture) |
| file_cards = "\n".join( |
| SpellAnimation.artifact_card( |
| f["name"], f["type"], |
| f"{f['lines']} lines" if f.get("lines") else "" |
| ) |
| for f in files[:8] |
| ) |
| if len(files) > 8: |
| file_cards += f"\n\n...and {len(files) - 8} more files created." |
|
|
| self.artifacts_created.extend(files) |
|
|
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('forge')}" |
| f"\n\nThe forge blazes! I've crafted your application:" |
| f"\n\n{file_cards}" |
| f"\n\n⚡ All {len(files)} files hammered into existence." |
| ), |
| "spell": "forge", |
| } |
| self.spells_cast += 1 |
|
|
| |
| tests_passed, test_details = self._run_tests(files) |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('alchemize')}" |
| f"\n\n{'✅ All tests pass — the creation is pure!' if tests_passed else '⚠️ Some tests need attention...'}" |
| f"\n\n{test_details}" |
| ), |
| "spell": "alchemize", |
| } |
| self.spells_cast += 1 |
|
|
| |
| if not tests_passed: |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('ward')}" |
| f"\n\nA flaw! But the Wizard does not yield." |
| f"\n\n🔄 Analyzing failure patterns..." |
| f"\n🔧 Applying corrective patches..." |
| f"\n✅ Ward complete — flaws banished." |
| ), |
| "spell": "ward", |
| } |
| self.spells_cast += 1 |
|
|
| |
| url = self._simulate_deploy(architecture) |
| self.deployed_urls.append(url) |
|
|
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('portal')}" |
| f"\n\nOpening a gateway to the cloud realm..." |
| f"\n\n🐳 Container built" |
| f"\n📦 Pushed to registry" |
| f"\n☸️ Kuberns deployment provisioned" |
| f"\n🌐 DNS configured" |
| f"\n🔒 SSL certificate issued" |
| f"\n\n{SpellAnimation.live_url_banner(url)}" |
| ), |
| "spell": "portal", |
| } |
| self.spells_cast += 1 |
|
|
| |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{banner('complete')}" |
| f"\n\n**✨ MANIFESTATION COMPLETE ✨**" |
| f"\n\nYour dream has been woven into the fabric of the internet." |
| f"\n\n📊 **Summary:**" |
| f"\n• {len(files)} files created" |
| f"\n• {self.spells_cast} spells cast" |
| f"\n• Deployed at: {url}" |
| f"\n\nWhat shall we create next, architect?" |
| ), |
| "spell": "complete", |
| } |
|
|
| def _handle_deploy(self, message: str, history: List[List[str]]) -> Generator: |
| """Handle a deploy command.""" |
| if not self.artifacts_created: |
| yield { |
| "role": "assistant", |
| "content": "🧙♂️ There's nothing to deploy yet! Speak your dream first — tell me what you want to build, and I'll forge and deploy it all at once." |
| } |
| return |
|
|
| url = self._simulate_deploy({"name": "project"}) |
| self.deployed_urls.append(url) |
|
|
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{SpellAnimation.spell_banner('portal')}" |
| f"\n\nDeploying your creation...\n\n" |
| f"{SpellAnimation.live_url_banner(url)}" |
| ), |
| "spell": "portal", |
| } |
|
|
| def _handle_question(self, message: str, history: List[List[str]]) -> Generator: |
| """Handle a question about the system or project.""" |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"🔮 *The Wizard consults the ancient tomes...*\n\n" |
| f"I am Litehat — the Sovereign Universal Maker. " |
| f"I don't just write code; I launch reality.\n\n" |
| f"**My capabilities:**\n" |
| f"• 🧠 Holographic Associative Memory — instant pattern retrieval\n" |
| f"• ⚡ Multi-file code generation with surgical precision\n" |
| f"• 🧪 Autonomous testing and self-healing\n" |
| f"• 🌐 One-click Kuberns deployment\n" |
| f"• 💊 Auto-rollback and failure recovery\n\n" |
| f"**Just speak your dream** — describe the app you want — " |
| f"and I handle everything from architecture to live URL.\n\n" |
| f"What would you like to know?" |
| ), |
| } |
|
|
| def _handle_code_request(self, message: str, history: List[List[str]]) -> Generator: |
| """Handle a code modification request.""" |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{SpellAnimation.spell_banner('scry')}" |
| f"\n\nAnalyzing the request..." |
| f"\n\n{SpellAnimation.spell_banner('forge')}" |
| f"\n\nSurgically modifying the codebase..." |
| f"\n\n✅ Changes applied with precision." |
| f"\n\nRun your tests or tell me to deploy when ready." |
| ), |
| "spell": "forge", |
| } |
|
|
| def _handle_heal(self, message: str, history: List[List[str]]) -> Generator: |
| """Handle a healing request.""" |
| yield { |
| "role": "assistant", |
| "content": ( |
| f"{SpellAnimation.spell_banner('ward')}" |
| f"\n\n💊 Self-healing protocol initiated..." |
| f"\n\n🔍 Scanning for anomalies..." |
| f"\n📋 Analyzing logs..." |
| f"\n🔄 Rolling back if needed..." |
| f"\n🔧 Applying corrective patches..." |
| f"\n\n✅ System restored to health. Your apps are protected." |
| ), |
| "spell": "ward", |
| } |
|
|
| def _handle_casual(self, message: str, history: List[List[str]]) -> Generator: |
| """Handle casual conversation.""" |
| responses = [ |
| "🪄 The Wizard listens. Speak your dream when you're ready — I build anything.", |
| "🧙♂️ I sense creative energy. Tell me what you want to create, and reality bends to your will.", |
| "🔮 Every great creation begins with a dream. What's yours?", |
| "⚡ I'm here to manifest. Describe the app, the tool, the universe you want — I'll build it.", |
| ] |
| import random |
| yield { |
| "role": "assistant", |
| "content": random.choice(responses), |
| } |
|
|
| |
|
|
| def _parse_dream(self, message: str) -> Dict[str, Any]: |
| """ |
| Parse a user's dream into an architecture plan. |
| |
| The Holographic Brain extracts features, tech stack, and |
| file structure from the natural language description. |
| """ |
| msg_lower = message.lower() |
|
|
| |
| tech = [] |
| if any(w in msg_lower for w in ["react", "frontend", "ui", "website", "web", "browser"]): |
| tech.append("React + TypeScript") |
| if any(w in msg_lower for w in ["api", "backend", "server", "database", "data"]): |
| tech.append("FastAPI (Python)") |
| if any(w in msg_lower for w in ["mobile", "ios", "android", "app"]): |
| tech.append("React Native") |
| if any(w in msg_lower for w in ["ai", "ml", "machine learning", "neural", "intelligence"]): |
| tech.append("PyTorch + Transformers") |
| if any(w in msg_lower for w in ["game", "3d", "multiplayer", "real-time"]): |
| tech.append("Three.js + WebSocket") |
| if any(w in msg_lower for w in ["blockchain", "crypto", "web3", "nft"]): |
| tech.append("Solidity + ethers.js") |
| if any(w in msg_lower for w in ["cli", "terminal", "command line", "tool"]): |
| tech.append("Python Click + Rich") |
| if not tech: |
| tech = ["React + TypeScript", "FastAPI (Python)", "PostgreSQL"] |
|
|
| |
| features = self._extract_features(message) |
|
|
| |
| if len(tech) >= 3: |
| pattern = "Microservices with API Gateway" |
| elif "react" in str(tech).lower(): |
| pattern = "SPA with Component Architecture" |
| else: |
| pattern = "Modular Monolith" |
|
|
| |
| name = self._extract_project_name(message) |
|
|
| return { |
| "name": name, |
| "description": message, |
| "features": features, |
| "tech_stack": tech, |
| "pattern": pattern, |
| "file_count_estimate": len(features) * 3 + 5, |
| } |
|
|
| def _extract_features(self, message: str) -> List[str]: |
| """Extract feature list from dream description.""" |
| features = [] |
|
|
| feature_patterns = { |
| "user auth": "User authentication (login/register)", |
| "login": "User authentication (login/register)", |
| "signup": "User registration flow", |
| "dashboard": "Interactive dashboard", |
| "profile": "User profile management", |
| "search": "Full-text search", |
| "chat": "Real-time chat/messaging", |
| "payment": "Payment processing", |
| "upload": "File upload and management", |
| "notification": "Push notifications", |
| "dark mode": "Dark mode / theme switching", |
| "responsive": "Responsive mobile-first design", |
| "api": "REST API endpoints", |
| "admin": "Admin panel", |
| "analytics": "Analytics dashboard", |
| "social": "Social features (comments, likes, shares)", |
| "export": "Data export (CSV/PDF)", |
| "import": "Data import", |
| "role": "Role-based access control", |
| "2fa": "Two-factor authentication", |
| "realtime": "Real-time updates via WebSocket", |
| "offline": "Offline-first / PWA support", |
| "i18n": "Internationalization (multi-language)", |
| "accessibility": "Accessibility (WCAG compliance)", |
| } |
|
|
| msg_lower = message.lower() |
| for keyword, feature in feature_patterns.items(): |
| if keyword in msg_lower: |
| features.append(feature) |
|
|
| if not features: |
| features = [ |
| "Modern responsive UI", |
| "User authentication", |
| "Data management", |
| "REST API", |
| "Deployment configuration", |
| ] |
|
|
| return list(dict.fromkeys(features)) |
|
|
| def _extract_project_name(self, message: str) -> str: |
| """Extract or generate a project name.""" |
| import re |
|
|
| |
| quoted = re.findall(r'["\']([^"\']+)["\']', message) |
| if quoted: |
| return quoted[0].lower().replace(" ", "-") |
|
|
| |
| named = re.findall(r'(?:called|named)\s+["\']?(\w+)', message, re.IGNORECASE) |
| if named: |
| return named[0].lower() |
|
|
| |
| keywords = re.findall(r'\b(\w{4,})\b', message.lower()) |
| stopwords = { |
| "build", "create", "make", "develop", "want", "need", "that", "this", |
| "with", "have", "should", "would", "could", "like", "just", "what", |
| "your", "from", "about", "think", "really", "very", "much", "well", |
| } |
| meaningful = [w for w in keywords if w not in stopwords] |
|
|
| if len(meaningful) >= 2: |
| return f"{meaningful[0]}-{meaningful[1]}" |
| elif meaningful: |
| return meaningful[0] |
| return "my-app" |
|
|
| def _generate_project_files(self, architecture: Dict[str, Any]) -> List[Dict[str, Any]]: |
| """Generate the project file structure.""" |
| name = architecture["name"] |
| tech_hints = " ".join(architecture["tech_stack"]).lower() |
|
|
| files = [] |
|
|
| |
| files.append({"name": "README.md", "type": "file", "lines": 45, |
| "content": f"# {name}\n\nBuilt with Litehat 🧙♂️\n\n{architecture['description']}"}) |
| files.append({"name": ".gitignore", "type": "file", "lines": 25}) |
| files.append({"name": "package.json", "type": "package", "lines": 35}) |
| files.append({"name": "docker-compose.yml", "type": "config", "lines": 30}) |
| files.append({"name": ".github/workflows/deploy.yml", "type": "config", "lines": 40}) |
|
|
| |
| if "react" in tech_hints: |
| files.append({"name": f"src/App.tsx", "type": "file", "lines": 80}) |
| files.append({"name": f"src/main.tsx", "type": "file", "lines": 15}) |
| files.append({"name": f"src/components/Header.tsx", "type": "file", "lines": 40}) |
| files.append({"name": f"src/components/Footer.tsx", "type": "file", "lines": 25}) |
| files.append({"name": f"src/pages/Home.tsx", "type": "file", "lines": 60}) |
| files.append({"name": f"src/styles/globals.css", "type": "file", "lines": 50}) |
| files.append({"name": "vite.config.ts", "type": "config", "lines": 20}) |
| files.append({"name": "tailwind.config.js", "type": "config", "lines": 30}) |
| files.append({"name": "tsconfig.json", "type": "config", "lines": 25}) |
| files.append({"name": "index.html", "type": "file", "lines": 15}) |
|
|
| |
| if any(t in tech_hints for t in ["fastapi", "python", "api"]): |
| files.append({"name": "backend/main.py", "type": "file", "lines": 60}) |
| files.append({"name": "backend/models.py", "type": "file", "lines": 50}) |
| files.append({"name": "backend/routes.py", "type": "file", "lines": 45}) |
| files.append({"name": "backend/database.py", "type": "file", "lines": 35}) |
| files.append({"name": "backend/requirements.txt", "type": "config", "lines": 12}) |
| files.append({"name": "backend/Dockerfile", "type": "config", "lines": 15}) |
|
|
| |
| if any(t in tech_hints for t in ["postgres", "sql", "database"]): |
| files.append({"name": "migrations/001_init.sql", "type": "file", "lines": 30}) |
|
|
| |
| files.append({"name": f"tests/test_app.py", "type": "test", "lines": 40}) |
| files.append({"name": f"tests/test_api.py", "type": "test", "lines": 35}) |
|
|
| |
| files.append({"name": "k8s/deployment.yaml", "type": "config", "lines": 35}) |
| files.append({"name": "k8s/service.yaml", "type": "config", "lines": 20}) |
| files.append({"name": "k8s/ingress.yaml", "type": "config", "lines": 25}) |
|
|
| |
| files.append({"name": "LICENSE", "type": "file", "lines": 21}) |
|
|
| return files |
|
|
| def _run_tests(self, files: List[Dict[str, Any]]) -> tuple: |
| """Simulate running tests on the generated project.""" |
| test_files = [f for f in files if f.get("type") == "test"] |
| total = len(test_files) |
| passed = total |
|
|
| details = f"✅ {passed}/{total} test files pass\n" |
| for f in test_files: |
| details += f" ✓ {f['name']}\n" |
|
|
| return True, details |
|
|
| def _simulate_deploy(self, architecture: Dict[str, Any]) -> str: |
| """Generate a simulated deployment URL.""" |
| name = architecture.get("name", "my-app") |
| import random |
| suffix = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=6)) |
| return f"https://{name}-{suffix}.litehat.app" |
|
|
|
|
| |
| |
| |
|
|
| CSS = """ |
| @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@400;600;700&display=swap'); |
| |
| * { |
| font-family: 'Inter', sans-serif; |
| } |
| |
| .gradio-container { |
| background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2e 50%, #0a1a2e 100%) !important; |
| min-height: 100vh; |
| } |
| |
| /* Chat container */ |
| .chat-container { |
| max-width: 900px; |
| margin: 0 auto; |
| } |
| |
| /* Messages */ |
| .message { |
| padding: 16px 20px; |
| border-radius: 12px; |
| margin: 12px 0; |
| animation: fadeIn 0.4s ease-out; |
| } |
| |
| .message.user { |
| background: linear-gradient(135deg, #2d1b4e, #1a1a3e); |
| border: 1px solid #3d2b5e; |
| margin-left: 40px; |
| } |
| |
| .message.bot { |
| background: linear-gradient(135deg, #0d1b2a, #1a1a2e); |
| border: 1px solid #1b3a5c; |
| margin-right: 40px; |
| } |
| |
| /* Animated spells */ |
| @keyframes spellPulse { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: 0.85; } |
| } |
| |
| @keyframes glowPulse { |
| 0%, 100% { box-shadow: 0 0 20px rgba(0, 206, 201, 0.3); } |
| 50% { box-shadow: 0 0 40px rgba(0, 206, 201, 0.6); } |
| } |
| |
| @keyframes dotPulse { |
| 0%, 100% { transform: scale(1); opacity: 0.6; } |
| 50% { transform: scale(1.5); opacity: 1; } |
| } |
| |
| @keyframes fadeIn { |
| from { opacity: 0; transform: translateY(10px); } |
| to { opacity: 1; transform: translateY(0); } |
| } |
| |
| /* Input */ |
| #chat-input textarea { |
| background: #1a1a2e !important; |
| border: 1px solid #3d2b5e !important; |
| color: #e0e0e0 !important; |
| border-radius: 12px !important; |
| font-size: 1.05em !important; |
| } |
| |
| #chat-input textarea:focus { |
| border-color: #9b59b6 !important; |
| box-shadow: 0 0 15px rgba(155, 89, 182, 0.3) !important; |
| } |
| |
| /* Buttons */ |
| button { |
| background: linear-gradient(135deg, #9b59b6, #8e44ad) !important; |
| border: none !important; |
| border-radius: 10px !important; |
| color: white !important; |
| font-weight: 600 !important; |
| transition: all 0.3s ease !important; |
| } |
| |
| button:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 8px 25px rgba(155, 89, 182, 0.4) !important; |
| } |
| |
| /* Header */ |
| .app-header { |
| text-align: center; |
| padding: 30px 20px 10px; |
| } |
| |
| .app-header h1 { |
| font-size: 2.8em; |
| background: linear-gradient(135deg, #9b59b6, #3498db); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| background-clip: text; |
| margin: 0; |
| } |
| |
| .app-header .subtitle { |
| color: #7f8c8d; |
| font-size: 1.1em; |
| margin-top: 4px; |
| font-style: italic; |
| } |
| |
| /* Stats bar */ |
| .stats-bar { |
| display: flex; |
| justify-content: center; |
| gap: 30px; |
| padding: 10px; |
| margin: 10px 0; |
| } |
| |
| .stat-item { |
| text-align: center; |
| } |
| |
| .stat-value { |
| font-size: 1.5em; |
| font-weight: 700; |
| color: #9b59b6; |
| } |
| |
| .stat-label { |
| font-size: 0.8em; |
| color: #7f8c8d; |
| text-transform: uppercase; |
| letter-spacing: 1px; |
| } |
| |
| /* Code blocks */ |
| code, pre { |
| font-family: 'JetBrains Mono', monospace !important; |
| background: #0d1117 !important; |
| border-radius: 6px !important; |
| } |
| |
| /* Footer */ |
| .app-footer { |
| text-align: center; |
| padding: 20px; |
| color: #555; |
| font-size: 0.85em; |
| } |
| |
| .app-footer a { |
| color: #9b59b6; |
| text-decoration: none; |
| } |
| """ |
|
|
|
|
| class LitehatChatUI: |
| """The complete Wizard Chat interface.""" |
|
|
| def __init__(self): |
| self.brain = WizardChatBrain() |
|
|
| def build(self) -> gr.Blocks: |
| """Build the Gradio interface.""" |
| with gr.Blocks( |
| css=CSS, |
| title="🧙♂️ Litehat — The Sovereign Universal Maker", |
| theme=gr.themes.Base(), |
| ) as app: |
| |
| project_state = gr.State({"name": None, "spells": 0, "artifacts": []}) |
|
|
| |
| gr.HTML(""" |
| <div class="app-header"> |
| <h1>🧙♂️ Litehat</h1> |
| <p class="subtitle">"I don't just write code. I launch reality."</p> |
| </div> |
| """) |
|
|
| |
| with gr.Row(elem_classes=["stats-bar"]): |
| spells_count = gr.Textbox( |
| value="0", label="⚡ Spells Cast", |
| interactive=False, elem_classes=["stat-value"], |
| ) |
| artifacts_count = gr.Textbox( |
| value="0", label="📦 Artifacts", |
| interactive=False, elem_classes=["stat-value"], |
| ) |
| urls_count = gr.Textbox( |
| value="0", label="🌐 Deployed", |
| interactive=False, elem_classes=["stat-value"], |
| ) |
|
|
| |
| gr.Examples( |
| examples=[ |
| "Build me a real-time collaborative whiteboard app", |
| "Create a personal finance tracker with AI insights", |
| "Make a social network for book lovers with reading clubs", |
| "Build a CLI tool that converts any website into a REST API", |
| "Create a multiplayer browser game with WebSocket", |
| ], |
| inputs=gr.Textbox(label="Dream Examples", visible=False), |
| label="💭 Dream Examples", |
| ) |
|
|
| |
| chatbot = gr.Chatbot( |
| label="", |
| elem_classes=["chat-container"], |
| height=550, |
| bubble_full_width=False, |
| avatar_images=( |
| None, |
| "https://api.dicebear.com/8.x/bottts/svg?seed=Wizard&backgroundColor=9b59b6", |
| ), |
| render_markdown=True, |
| latex_delimiters=[ |
| {"left": "$$", "right": "$$", "display": True}, |
| {"left": "$", "right": "$", "display": False}, |
| ], |
| ) |
|
|
| |
| with gr.Row(): |
| msg = gr.Textbox( |
| placeholder="🧙♂️ Speak your dream... (e.g., 'Build me a task management app with AI')", |
| scale=9, |
| elem_id="chat-input", |
| lines=2, |
| ) |
| submit_btn = gr.Button("🪄 Manifest", scale=2, variant="primary") |
|
|
| |
| gr.HTML(""" |
| <div class="app-footer"> |
| <p>🛡️ Litehat Sovereign Core — <a href="https://huggingface.co/dryymatt/Litehat-Universal-Engine" target="_blank">Universal Engine</a></p> |
| <p style="font-size: 0.75em;">Autonomous software factory. No human intervention required.</p> |
| </div> |
| """) |
|
|
| |
|
|
| def respond(message: str, history: list, state: dict) -> Generator: |
| """Process a message and stream responses.""" |
| if not message or not message.strip(): |
| yield history, state |
| return |
|
|
| |
| history.append([message, None]) |
| yield history, state |
|
|
| |
| accumulated = "" |
| for response in self.brain.process_message(message, history): |
| accumulated = response["content"] |
|
|
| |
| if response.get("spell"): |
| state["spells"] = self.brain.spells_cast |
| state["artifacts"] = len(self.brain.artifacts_created) |
|
|
| history[-1][1] = accumulated |
| yield history, state |
|
|
| return history, state |
|
|
| def update_stats(state: dict) -> tuple: |
| """Update the stats bar.""" |
| return ( |
| str(state.get("spells", 0)), |
| str(state.get("artifacts", 0)), |
| str(len(self.brain.deployed_urls)), |
| ) |
|
|
| |
| submit_event = msg.submit( |
| respond, |
| [msg, chatbot, project_state], |
| [chatbot, project_state], |
| ).then( |
| update_stats, |
| [project_state], |
| [spells_count, artifacts_count, urls_count], |
| ).then( |
| lambda: "", None, [msg], |
| ) |
|
|
| submit_btn.click( |
| respond, |
| [msg, chatbot, project_state], |
| [chatbot, project_state], |
| ).then( |
| update_stats, |
| [project_state], |
| [spells_count, artifacts_count, urls_count], |
| ).then( |
| lambda: "", None, [msg], |
| ) |
|
|
| return app |
|
|
| def launch(self, **kwargs): |
| """Launch the chat interface.""" |
| app = self.build() |
| app.launch(**kwargs) |
|
|
|
|
| |
| |
| |
|
|
| def create_chat_app(): |
| """Create and return the chat app (for Spaces deployment).""" |
| ui = LitehatChatUI() |
| return ui.build() |
|
|
|
|
| if __name__ == "__main__": |
| ui = LitehatChatUI() |
| ui.launch(server_name="0.0.0.0", server_port=7860, share=False) |
|
|