Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>NEXUS | Multi-Agent AI Workspace</title> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --bg-deep: #030712; | |
| --bg-panel: #0f172a; | |
| --bg-glass: rgba(15, 23, 42, 0.7); | |
| --border-color: rgba(255, 255, 255, 0.08); | |
| --accent-primary: #3b82f6; | |
| --accent-glow: #60a5fa; | |
| --accent-secondary: #8b5cf6; | |
| --text-main: #f8fafc; | |
| --text-muted: #94a3b8; | |
| --success: #10b981; | |
| --warning: #f59e0b; | |
| --danger: #ef4444; | |
| --font-ui: 'Inter', system-ui, -apple-system, sans-serif; | |
| --font-mono: 'JetBrains Mono', 'Fira Code', monospace; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| body { | |
| background-color: var(--bg-deep); | |
| color: var(--text-main); | |
| font-family: var(--font-ui); | |
| height: 100vh; | |
| overflow: hidden; | |
| background-image: | |
| radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.08) 0%, transparent 40%), | |
| radial-gradient(circle at 90% 80%, rgba(139, 92, 246, 0.08) 0%, transparent 40%); | |
| } | |
| /* --- Layout Grid --- */ | |
| .app-container { | |
| display: grid; | |
| grid-template-columns: 280px 1fr 320px; | |
| grid-template-rows: 60px 1fr 80px; | |
| height: 100vh; | |
| gap: 1px; | |
| background-color: var(--border-color); /* Creates borders via gap */ | |
| } | |
| /* --- Header --- */ | |
| header { | |
| grid-column: 1 / -1; | |
| background: var(--bg-panel); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 24px; | |
| border-bottom: 1px solid var(--border-color); | |
| z-index: 10; | |
| } | |
| .brand { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| font-weight: 700; | |
| font-size: 1.2rem; | |
| letter-spacing: -0.5px; | |
| } | |
| .brand i { | |
| color: var(--accent-primary); | |
| font-size: 1.4rem; | |
| } | |
| .anycoder-link { | |
| font-size: 0.85rem; | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| padding: 6px 12px; | |
| border-radius: 6px; | |
| background: rgba(255,255,255,0.03); | |
| border: 1px solid var(--border-color); | |
| transition: all 0.2s ease; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .anycoder-link:hover { | |
| color: var(--accent-primary); | |
| border-color: var(--accent-primary); | |
| background: rgba(59, 130, 246, 0.1); | |
| } | |
| /* --- Sidebar (Agents) --- */ | |
| .sidebar { | |
| grid-row: 2 / 3; | |
| background: var(--bg-panel); | |
| padding: 20px; | |
| overflow-y: auto; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 16px; | |
| } | |
| .section-title { | |
| font-size: 0.75rem; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| color: var(--text-muted); | |
| margin-bottom: 8px; | |
| font-weight: 600; | |
| } | |
| .agent-card { | |
| background: rgba(255,255,255,0.02); | |
| border: 1px solid var(--border-color); | |
| border-radius: 12px; | |
| padding: 16px; | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| cursor: pointer; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .agent-card:hover { | |
| transform: translateY(-2px); | |
| background: rgba(255,255,255,0.04); | |
| border-color: rgba(255,255,255,0.15); | |
| } | |
| .agent-card.active { | |
| border-color: var(--accent-primary); | |
| box-shadow: 0 0 20px rgba(59, 130, 246, 0.15); | |
| } | |
| .agent-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| margin-bottom: 12px; | |
| } | |
| .agent-avatar { | |
| width: 36px; | |
| height: 36px; | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1rem; | |
| background: linear-gradient(135deg, #1e293b, #0f172a); | |
| border: 1px solid var(--border-color); | |
| } | |
| .agent-info h4 { | |
| font-size: 0.9rem; | |
| font-weight: 600; | |
| } | |
| .agent-info span { | |
| font-size: 0.75rem; | |
| color: var(--text-muted); | |
| } | |
| .status-indicator { | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: var(--text-muted); | |
| margin-left: auto; | |
| } | |
| .agent-card.working .status-indicator { | |
| background: var(--warning); | |
| box-shadow: 0 0 8px var(--warning); | |
| animation: pulse 1.5s infinite; | |
| } | |
| .agent-card.done .status-indicator { | |
| background: var(--success); | |
| } | |
| .agent-progress { | |
| height: 4px; | |
| background: rgba(255,255,255,0.05); | |
| border-radius: 2px; | |
| overflow: hidden; | |
| margin-top: 8px; | |
| } | |
| .agent-progress-bar { | |
| height: 100%; | |
| background: var(--accent-primary); | |
| width: 0%; | |
| transition: width 0.5s ease; | |
| } | |
| /* --- Main Workspace --- */ | |
| .workspace { | |
| grid-row: 2 / 3; | |
| background: var(--bg-deep); | |
| position: relative; | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| } | |
| .chat-area { | |
| flex: 1; | |
| padding: 40px; | |
| overflow-y: auto; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 24px; | |
| scroll-behavior: smooth; | |
| } | |
| /* Custom Scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 6px; | |
| height: 6px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: rgba(255,255,255,0.1); | |
| border-radius: 3px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: rgba(255,255,255,0.2); | |
| } | |
| .message { | |
| max-width: 80%; | |
| display: flex; | |
| gap: 16px; | |
| animation: slideIn 0.3s ease-out forwards; | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| .message.user { | |
| align-self: flex-end; | |
| flex-direction: row-reverse; | |
| } | |
| .message-content { | |
| background: rgba(30, 41, 59, 0.8); | |
| border: 1px solid var(--border-color); | |
| padding: 16px 20px; | |
| border-radius: 16px; | |
| font-size: 0.95rem; | |
| line-height: 1.5; | |
| position: relative; | |
| } | |
| .message.user .message-content { | |
| background: rgba(59, 130, 246, 0.15); | |
| border-color: rgba(59, 130, 246, 0.3); | |
| border-bottom-right-radius: 4px; | |
| } | |
| .message.agent .message-content { | |
| border-bottom-left-radius: 4px; | |
| } | |
| .message-meta { | |
| font-size: 0.75rem; | |
| color: var(--text-muted); | |
| margin-top: 8px; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .tool-card { | |
| background: #000; | |
| border: 1px solid var(--border-color); | |
| border-radius: 8px; | |
| padding: 12px; | |
| margin-top: 12px; | |
| font-family: var(--font-mono); | |
| font-size: 0.8rem; | |
| color: var(--success); | |
| } | |
| .tool-header { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 8px; | |
| color: var(--text-muted); | |
| font-size: 0.7rem; | |
| text-transform: uppercase; | |
| } | |
| /* --- Right Panel (Logs) --- */ | |
| .logs-panel { | |
| grid-row: 2 / 3; | |
| background: var(--bg-panel); | |
| border-left: 1px solid var(--border-color); | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .logs-header { | |
| padding: 16px; | |
| border-bottom: 1px solid var(--border-color); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .terminal-window { | |
| flex: 1; | |
| padding: 16px; | |
| font-family: var(--font-mono); | |
| font-size: 0.8rem; | |
| overflow-y: auto; | |
| background: rgba(0,0,0,0.2); | |
| } | |
| .log-entry { | |
| margin-bottom: 8px; | |
| opacity: 0; | |
| animation: fadeIn 0.2s forwards; | |
| } | |
| .log-time { | |
| color: var(--text-muted); | |
| margin-right: 8px; | |
| } | |
| .log-info { color: var(--accent-primary); } | |
| .log-warn { color: var(--warning); } | |
| .log-success { color: var(--success); } | |
| .log-sys { color: var(--secondary); } | |
| /* --- Input Area --- */ | |
| .input-container { | |
| grid-column: 1 / -1; | |
| grid-row: 3 / 4; | |
| background: var(--bg-panel); | |
| border-top: 1px solid var(--border-color); | |
| padding: 16px 24px; | |
| display: flex; | |
| align-items: center; | |
| gap: 16px; | |
| z-index: 20; | |
| } | |
| .input-wrapper { | |
| flex: 1; | |
| position: relative; | |
| background: rgba(0,0,0,0.3); | |
| border-radius: 12px; | |
| border: 1px solid var(--border-color); | |
| transition: border-color 0.2s; | |
| } | |
| .input-wrapper:focus-within { | |
| border-color: var(--accent-primary); | |
| box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); | |
| } | |
| textarea { | |
| width: 100%; | |
| background: transparent; | |
| border: none; | |
| color: var(--text-main); | |
| padding: 14px 16px; | |
| font-family: var(--font-ui); | |
| font-size: 0.95rem; | |
| resize: none; | |
| height: 52px; | |
| outline: none; | |
| } | |
| .send-btn { | |
| background: var(--accent-primary); | |
| color: white; | |
| border: none; | |
| width: 44px; | |
| height: 44px; | |
| border-radius: 10px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.2s; | |
| } | |
| .send-btn:hover { | |
| background: var(--accent-glow); | |
| transform: scale(1.05); | |
| } | |
| /* --- Animations --- */ | |
| @keyframes pulse { | |
| 0% { opacity: 1; transform: scale(1); } | |
| 50% { opacity: 0.5; transform: scale(1.2); } | |
| 100% { opacity: 1; transform: scale(1); } | |
| } | |
| @keyframes slideIn { | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @keyframes fadeIn { | |
| to { opacity: 1; } | |
| } | |
| @keyframes typing { | |
| from { width: 0 } | |
| to { width: 100% } | |
| } | |
| /* --- Responsive --- */ | |
| @media (max-width: 1024px) { | |
| .app-container { | |
| grid-template-columns: 1fr; | |
| grid-template-rows: 60px 1fr auto auto; | |
| } | |
| .sidebar { grid-row: 2; display: none; } /* Hide sidebar on small screens for simplicity */ | |
| .logs-panel { grid-row: 3; height: 200px; border-left: none; border-top: 1px solid var(--border-color); } | |
| .input-container { grid-row: 4; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="app-container"> | |
| <!-- Header --> | |
| <header> | |
| <div class="brand"> | |
| <i class="fa-solid fa-network-wired"></i> | |
| <span>NEXUS</span> | |
| </div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link"> | |
| <i class="fa-solid fa-robot"></i> Built with anycoder | |
| </a> | |
| </header> | |
| <!-- Left Sidebar: Agents --> | |
| <aside class="sidebar"> | |
| <div class="section-title">Active Agents</div> | |
| <div class="agent-card" id="agent-orchestrator"> | |
| <div class="agent-header"> | |
| <div class="agent-avatar" style="color: #f472b6;"><i class="fa-solid fa-brain"></i></div> | |
| <div class="agent-info"> | |
| <h4>Orchestrator</h4> | |
| <span>Task Management</span> | |
| </div> | |
| <div class="status-indicator"></div> | |
| </div> | |
| <div class="agent-progress"><div class="agent-progress-bar" style="width: 100%"></div></div> | |
| </div> | |
| <div class="agent-card" id="agent-researcher"> | |
| <div class="agent-header"> | |
| <div class="agent-avatar" style="color: #38bdf8;"><i class="fa-solid fa-magnifying-glass"></i></div> | |
| <div class="agent-info"> | |
| <h4>Researcher</h4> | |
| <span>Data Retrieval</span> | |
| </div> | |
| <div class="status-indicator"></div> | |
| </div> | |
| <div class="agent-progress"><div class="agent-progress-bar" style="width: 0%"></div></div> | |
| </div> | |
| <div class="agent-card" id="agent-coder"> | |
| <div class="agent-header"> | |
| <div class="agent-avatar" style="color: #a78bfa;"><i class="fa-solid fa-code"></i></div> | |
| <div class="agent-info"> | |
| <h4>Dev Agent</h4> | |
| <span>Code Generation</span> | |
| </div> | |
| <div class="status-indicator"></div> | |
| </div> | |
| <div class="agent-progress"><div class="agent-progress-bar" style="width: 0%"></div></div> | |
| </div> | |
| <div class="agent-card" id="agent-reviewer"> | |
| <div class="agent-header"> | |
| <div class="agent-avatar" style="color: #34d399;"><i class="fa-solid fa-shield-halved"></i></div> | |
| <div class="agent-info"> | |
| <h4>Reviewer</h4> | |
| <span>Quality Assurance</span> | |
| </div> | |
| <div class="status-indicator"></div> | |
| </div> | |
| <div class="agent-progress"><div class="agent-progress-bar" style="width: 0%"></div></div> | |
| </div> | |
| </aside> | |
| <!-- Main Workspace --> | |
| <main class="workspace"> | |
| <div class="chat-area" id="chat-container"> | |
| <!-- Initial Message --> | |
| <div class="message agent"> | |
| <div class="agent-avatar" style="width: 32px; height: 32px; font-size: 0.8rem; color: #f472b6;"><i class="fa-solid fa-brain"></i></div> | |
| <div class="message-content"> | |
| Hello! I am the Nexus Orchestrator. I manage a team of specialized AI agents. How can we help you today? | |
| <div class="message-meta">Orchestrator • Just now</div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Right Panel: Logs --> | |
| <aside class="logs-panel"> | |
| <div class="logs-header"> | |
| <span class="section-title" style="margin:0">System Logs</span> | |
| <i class="fa-solid fa-terminal" style="color: var(--text-muted)"></i> | |
| </div> | |
| <div class="terminal-window" id="terminal-output"> | |
| <div class="log-entry"><span class="log-time">10:00:01</span> <span class="log-sys">SYSTEM</span> initialized.</div> | |
| <div class="log-entry"><span class="log-time">10:00:02</span> <span class="log-info">NET</span> Connected to agent cluster.</div> | |
| </div> | |
| </aside> | |
| <!-- Input Area --> | |
| <div class="input-container"> | |
| <div class="input-wrapper"> | |
| <textarea id="user-input" placeholder="Describe your task (e.g., 'Create a Python script to scrape weather data')..." onkeydown="handleEnter(event)"></textarea> | |
| </div> | |
| <button class="send-btn" onclick="processInput()"> | |
| <i class="fa-solid fa-paper-plane"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| const chatContainer = document.getElementById('chat-container'); | |
| const terminalOutput = document.getElementById('terminal-output'); | |
| const userInput = document.getElementById('user-input'); | |
| // Agent State Management | |
| const agents = { | |
| orchestrator: { id: 'agent-orchestrator', name: 'Orchestrator', color: '#f472b6', icon: 'fa-brain' }, | |
| researcher: { id: 'agent-researcher', name: 'Researcher', color: '#38bdf8', icon: 'fa-magnifying-glass' }, | |
| coder: { id: 'agent-coder', name: 'Dev Agent', color: '#a78bfa', icon: 'fa-code' }, | |
| reviewer: { id: 'agent-reviewer', name: 'Reviewer', color: '#34d399', icon: 'fa-shield-halved' } | |
| }; | |
| function handleEnter(e) { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| processInput(); | |
| } | |
| } | |
| function addLog(type, message) { | |
| const now = new Date(); | |
| const timeString = now.toLocaleTimeString('en-US', { hour12: false }); | |
| const div = document.createElement('div'); | |
| div.className = 'log-entry'; | |
| div.innerHTML = `<span class="log-time">${timeString}</span> <span class="log-${type}">${type.toUpperCase()}</span> ${message}`; | |
| terminalOutput.appendChild(div); | |
| terminalOutput.scrollTop = terminalOutput.scrollHeight; | |
| } | |
| function addMessage(agentKey, text, isTool = false, toolData = null) { | |
| const agent = agents[agentKey]; | |
| const div = document.createElement('div'); | |
| div.className = `message ${agentKey === 'user' ? 'user' : 'agent'}`; | |
| let avatarHtml = ''; | |
| if (agentKey !== 'user') { | |
| avatarHtml = `<div class="agent-avatar" style="width: 32px; height: 32px; font-size: 0.8rem; color: ${agent.color}"><i class="fa-solid ${agent.icon}"></i></div>`; | |
| } | |
| let contentHtml = text; | |
| if (isTool && toolData) { | |
| contentHtml += ` | |
| <div class="tool-card"> | |
| <div class="tool-header"> | |
| <span>${toolData.tool}</span> | |
| <span>${toolData.status}</span> | |
| </div> | |
| <div>${toolData.code || toolData.output}</div> | |
| </div> | |
| `; | |
| } | |
| div.innerHTML = ` | |
| ${avatarHtml} | |
| <div class="message-content"> | |
| ${contentHtml} | |
| <div class="message-meta">${agent ? agent.name : 'You'} • Just now</div> | |
| </div> | |
| `; | |
| chatContainer.appendChild(div); | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| } | |
| function setAgentStatus(agentKey, status) { | |
| const card = document.getElementById(agents[agentKey].id); | |
| card.classList.remove('working', 'done'); | |
| if (status === 'working') card.classList.add('working'); | |
| if (status === 'done') card.classList.add('done'); | |
| } | |
| function updateProgress(agentKey, percent) { | |
| const card = document.getElementById(agents[agentKey].id); | |
| const bar = card.querySelector('.agent-progress-bar'); | |
| bar.style.width = `${percent}%`; | |
| } | |
| async function processInput() { | |
| const text = userInput.value.trim(); | |
| if (!text) return; | |
| // 1. User Message | |
| addMessage('user', text); | |
| userInput.value = ''; | |
| addLog('info', `User input received: "${text.substring(0, 30)}..."`); | |
| // Reset all agents | |
| Object.keys(agents).forEach(k => { | |
| setAgentStatus(k, ''); | |
| updateProgress(k, 0); | |
| }); | |
| // Simulate Workflow | |
| await simulateWorkflow(text); | |
| } | |
| async function simulateWorkflow(task) { | |
| // Step 1: Orchestrator analyzes | |
| setAgentStatus('orchestrator', 'working'); | |
| addLog('sys', 'Orchestrator analyzing intent...'); | |
| await wait(1000); | |
| updateProgress('orchestrator', 100); | |
| setAgentStatus('orchestrator', 'done'); | |
| addMessage('orchestrator', `I've analyzed your request. I'm delegating research tasks to the Researcher agent.`); | |
| // Step 2: Researcher works | |
| setAgentStatus('researcher', 'working'); | |
| addLog('warn', 'Researcher agent activated.'); | |
| updateProgress('researcher', 30); | |
| await wait(1500); | |
| updateProgress('researcher', 70); | |
| await wait(1000); | |
| updateProgress('researcher', 100); | |
| setAgentStatus('researcher', 'done'); | |
| addMessage('researcher', 'Research complete. Found relevant documentation and API endpoints.', true, { | |
| tool: 'Web Search', | |
| status: 'Success', | |
| output: 'Found 3 relevant sources regarding Python scraping libraries.' | |
| }); | |
| addLog('success', 'Research data compiled.'); | |
| // Step 3: Coder works | |
| setAgentStatus('coder', 'working'); | |
| addLog('info', 'Dev Agent generating code...'); | |
| updateProgress('coder', 20); | |
| await wait(800); | |
| updateProgress('coder', 60); | |
| await wait(1200); | |
| updateProgress('coder', 100); | |
| setAgentStatus('coder', 'done'); | |
| const codeSnippet = `import requests\nfrom bs4 import BeautifulSoup\n\ndef get_weather(city):\n # Implementation logic here\n pass`; | |
| addMessage('coder', 'Code generation complete. Passing to Reviewer.', true, { | |
| tool: 'Python Script', | |
| status: 'Generated', | |
| code: codeSnippet | |
| }); | |
| // Step 4: Reviewer works | |
| setAgentStatus('reviewer', 'working'); | |
| addLog('sys', 'Reviewer analyzing code quality...'); | |
| updateProgress('reviewer', 50); | |
| await wait(1000); | |
| updateProgress('reviewer', 100); | |
| setAgentStatus('reviewer', 'done'); | |
| addMessage('reviewer', 'Code review passed. No security vulnerabilities detected. Ready for deployment.'); | |
| addLog('success', 'Workflow completed successfully.'); | |
| // Final Orchestrator Message | |
| setAgentStatus('orchestrator', 'working'); | |
| await wait(500); | |
| setAgentStatus('orchestrator', 'done'); | |
| addMessage('orchestrator', 'Task completed. All agents have finished their sub-tasks.'); | |
| } | |
| function wait(ms) { | |
| return new Promise(resolve => setTimeout(resolve, ms)); | |
| } | |
| </script> | |
| </body> | |
| </html> |