Spaces:
Running
Running
| <html lang="en" class="h-full"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AgentFlow Nexus - Modern AI Workspace</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/lucide@latest"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/javascript.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
| * { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 6px; | |
| height: 6px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: rgba(99, 102, 241, 0.3); | |
| border-radius: 3px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: rgba(99, 102, 241, 0.5); | |
| } | |
| /* Glassmorphism effects */ | |
| .glass { | |
| background: rgba(255, 255, 255, 0.03); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| .glass-strong { | |
| background: rgba(30, 41, 59, 0.8); | |
| backdrop-filter: blur(16px); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| /* Animations */ | |
| @keyframes slideIn { | |
| from { opacity: 0; transform: translateX(-10px); } | |
| to { opacity: 1; transform: translateX(0); } | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @keyframes pulse-ring { | |
| 0% { transform: scale(0.8); opacity: 0.5; } | |
| 100% { transform: scale(2); opacity: 0; } | |
| } | |
| @keyframes float { | |
| 0%, 100% { transform: translateY(0px); } | |
| 50% { transform: translateY(-5px); } | |
| } | |
| .animate-slide-in { | |
| animation: slideIn 0.3s ease-out forwards; | |
| } | |
| .animate-fade-in { | |
| animation: fadeIn 0.3s ease-out forwards; | |
| } | |
| .animate-float { | |
| animation: float 3s ease-in-out infinite; | |
| } | |
| /* Message bubbles */ | |
| .message-bubble { | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); | |
| } | |
| .message-bubble:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| } | |
| /* Typing indicator */ | |
| .typing-dot { | |
| animation: typing 1.4s infinite; | |
| } | |
| .typing-dot:nth-child(2) { animation-delay: 0.2s; } | |
| .typing-dot:nth-child(3) { animation-delay: 0.4s; } | |
| @keyframes typing { | |
| 0%, 60%, 100% { transform: translateY(0); } | |
| 30% { transform: translateY(-4px); } | |
| } | |
| /* Code block styling */ | |
| .code-block-wrapper { | |
| position: relative; | |
| margin: 0.5rem 0; | |
| border-radius: 0.5rem; | |
| overflow: hidden; | |
| } | |
| .code-header { | |
| background: rgba(0, 0, 0, 0.4); | |
| padding: 0.5rem 1rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| font-size: 0.75rem; | |
| color: #9ca3af; | |
| } | |
| .copy-btn { | |
| transition: all 0.2s; | |
| } | |
| .copy-btn:hover { | |
| color: white; | |
| transform: scale(1.05); | |
| } | |
| /* Task priorities */ | |
| .priority-high { border-left: 3px solid #ef4444; } | |
| .priority-medium { border-left: 3px solid #f59e0b; } | |
| .priority-low { border-left: 3px solid #10b981; } | |
| /* Agent status indicator */ | |
| .status-ring::before { | |
| content: ''; | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| border-radius: 50%; | |
| background: #10b981; | |
| animation: pulse-ring 2s cubic-bezier(0.215, 0.61, 0.355, 1) infinite; | |
| z-index: -1; | |
| } | |
| /* Responsive sidebar */ | |
| .sidebar-transition { | |
| transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| /* Input focus effects */ | |
| .input-glow:focus { | |
| box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2); | |
| border-color: rgba(99, 102, 241, 0.5); | |
| } | |
| /* Theme transitions */ | |
| .theme-transition { | |
| transition: background-color 0.3s, color 0.3s, border-color 0.3s; | |
| } | |
| /* Drag and drop zone */ | |
| .drop-zone { | |
| border: 2px dashed rgba(99, 102, 241, 0.3); | |
| transition: all 0.3s; | |
| } | |
| .drop-zone.drag-over { | |
| border-color: #6366f1; | |
| background: rgba(99, 102, 241, 0.1); | |
| } | |
| /* Custom checkbox */ | |
| .custom-checkbox { | |
| appearance: none; | |
| width: 1.2rem; | |
| height: 1.2rem; | |
| border: 2px solid rgba(99, 102, 241, 0.4); | |
| border-radius: 0.35rem; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| position: relative; | |
| } | |
| .custom-checkbox:checked { | |
| background: #6366f1; | |
| border-color: #6366f1; | |
| } | |
| .custom-checkbox:checked::after { | |
| content: ''; | |
| position: absolute; | |
| left: 5px; | |
| top: 2px; | |
| width: 5px; | |
| height: 9px; | |
| border: solid white; | |
| border-width: 0 2px 2px 0; | |
| transform: rotate(45deg); | |
| } | |
| /* Modal overlay */ | |
| .modal-overlay { | |
| background: rgba(0, 0, 0, 0.6); | |
| backdrop-filter: blur(4px); | |
| } | |
| /* Notification badge */ | |
| .notification-badge { | |
| animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; | |
| } | |
| @keyframes ping { | |
| 75%, 100% { | |
| transform: scale(2); | |
| opacity: 0; | |
| } | |
| } | |
| /* Line numbers for editor */ | |
| .line-numbers { | |
| counter-reset: line; | |
| } | |
| .line-numbers > div::before { | |
| counter-increment: line; | |
| content: counter(line); | |
| display: inline-block; | |
| width: 2rem; | |
| margin-right: 1rem; | |
| color: #6b7280; | |
| text-align: right; | |
| user-select: none; | |
| } | |
| </style> | |
| </head> | |
| <body class="h-full bg-slate-900 text-slate-100 overflow-hidden theme-transition" id="app-body"> | |
| <!-- Mobile Sidebar Overlay --> | |
| <div id="sidebar-overlay" class="fixed inset-0 bg-black/60 backdrop-blur-sm z-40 hidden lg:hidden modal-overlay" onclick="toggleSidebar()"></div> | |
| <div class="flex h-full overflow-hidden"> | |
| <!-- Sidebar --> | |
| <aside id="sidebar" class="sidebar-transition fixed lg:static inset-y-0 left-0 z-50 w-72 bg-slate-800/95 border-r border-slate-700/50 flex flex-col transform -translate-x-full lg:translate-x-0 glass-strong"> | |
| <!-- Logo --> | |
| <div class="p-5 border-b border-slate-700/50 flex items-center justify-between"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="relative"> | |
| <div class="w-10 h-10 rounded-xl bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center shadow-lg animate-float"> | |
| <i data-lucide="cpu" class="text-white w-5 h-5"></i> | |
| </div> | |
| <div class="absolute -bottom-1 -right-1 w-4 h-4 bg-green-500 rounded-full border-2 border-slate-800 status-ring"></div> | |
| </div> | |
| <div> | |
| <h2 class="font-bold text-lg tracking-tight">AgentFlow</h2> | |
| <p class="text-xs text-slate-400 flex items-center gap-1"> | |
| <span class="w-1.5 h-1.5 rounded-full bg-green-400 animate-pulse"></span> | |
| System Active | |
| </p> | |
| </div> | |
| </div> | |
| <button onclick="toggleSidebar()" class="lg:hidden p-2 hover:bg-slate-700 rounded-lg transition-colors"> | |
| <i data-lucide="x" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| <!-- Navigation --> | |
| <div class="flex-1 overflow-y-auto p-4 space-y-6"> | |
| <!-- Agent Selector --> | |
| <div class="space-y-2"> | |
| <div class="flex items-center justify-between mb-2"> | |
| <h3 class="text-xs font-semibold uppercase tracking-wider text-slate-400">Active Agent</h3> | |
| <button onclick="showAgentSelector()" class="text-xs text-indigo-400 hover:text-indigo-300 transition-colors">Change</button> | |
| </div> | |
| <div class="glass rounded-xl p-3 cursor-pointer hover:bg-slate-700/50 transition-all group" onclick="showAgentSelector()"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-10 h-10 rounded-lg bg-indigo-500/20 flex items-center justify-center group-hover:scale-110 transition-transform"> | |
| <i data-lucide="bot" class="text-indigo-400 w-5 h-5"></i> | |
| </div> | |
| <div class="flex-1"> | |
| <p class="font-medium text-sm" id="current-agent-name">Chat Agent</p> | |
| <p class="text-xs text-slate-400">GPT-4 Turbo</p> | |
| </div> | |
| <i data-lucide="chevron-right" class="w-4 h-4 text-slate-500"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Quick Actions --> | |
| <div class="space-y-1"> | |
| <h3 class="text-xs font-semibold uppercase tracking-wider text-slate-400 mb-2">Quick Actions</h3> | |
| <button onclick="newChat()" class="w-full flex items-center space-x-3 p-2.5 rounded-lg hover:bg-slate-700/50 text-left transition-all group"> | |
| <div class="w-8 h-8 rounded-lg bg-blue-500/20 flex items-center justify-center group-hover:scale-110 transition-transform"> | |
| <i data-lucide="plus" class="w-4 h-4 text-blue-400"></i> | |
| </div> | |
| <span class="text-sm font-medium">New Chat</span> | |
| </button> | |
| <button onclick="clearContext()" class="w-full flex items-center space-x-3 p-2.5 rounded-lg hover:bg-slate-700/50 text-left transition-all group"> | |
| <div class="w-8 h-8 rounded-lg bg-orange-500/20 flex items-center justify-center group-hover:scale-110 transition-transform"> | |
| <i data-lucide="rotate-ccw" class="w-4 h-4 text-orange-400"></i> | |
| </div> | |
| <span class="text-sm font-medium">Clear Context</span> | |
| </button> | |
| <button onclick="exportChat()" class="w-full flex items-center space-x-3 p-2.5 rounded-lg hover:bg-slate-700/50 text-left transition-all group"> | |
| <div class="w-8 h-8 rounded-lg bg-purple-500/20 flex items-center justify-center group-hover:scale-110 transition-transform"> | |
| <i data-lucide="download" class="w-4 h-4 text-purple-400"></i> | |
| </div> | |
| <span class="text-sm font-medium">Export Chat</span> | |
| </button> | |
| </div> | |
| <!-- Recent Projects --> | |
| <div class="space-y-1"> | |
| <div class="flex items-center justify-between mb-2"> | |
| <h3 class="text-xs font-semibold uppercase tracking-wider text-slate-400">Projects</h3> | |
| <button onclick="addProject()" class="p-1 hover:bg-slate-700 rounded transition-colors"> | |
| <i data-lucide="plus" class="w-3 h-3"></i> | |
| </button> | |
| </div> | |
| <div id="project-list" class="space-y-1"> | |
| <!-- Projects injected by JS --> | |
| </div> | |
| </div> | |
| <!-- Recent Chats --> | |
| <div class="space-y-1"> | |
| <h3 class="text-xs font-semibold uppercase tracking-wider text-slate-400 mb-2">Recent</h3> | |
| <div id="recent-chats" class="space-y-1"> | |
| <!-- Recent chats injected by JS --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Bottom Actions --> | |
| <div class="p-4 border-t border-slate-700/50 space-y-2"> | |
| <button onclick="toggleTheme()" class="w-full flex items-center space-x-3 p-2.5 rounded-lg hover:bg-slate-700/50 text-left transition-all"> | |
| <i data-lucide="palette" class="w-4 h-4 text-slate-400"></i> | |
| <span class="text-sm">Toggle Theme</span> | |
| </button> | |
| <button onclick="showKeyboardShortcuts()" class="w-full flex items-center space-x-3 p-2.5 rounded-lg hover:bg-slate-700/50 text-left transition-all"> | |
| <i data-lucide="command" class="w-4 h-4 text-slate-400"></i> | |
| <span class="text-sm">Shortcuts</span> | |
| </button> | |
| <button onclick="openSettings()" class="w-full flex items-center space-x-3 p-2.5 rounded-lg hover:bg-slate-700/50 text-left transition-all"> | |
| <i data-lucide="settings" class="w-4 h-4 text-slate-400"></i> | |
| <span class="text-sm">Settings</span> | |
| </button> | |
| </div> | |
| </aside> | |
| <!-- Main Content --> | |
| <main class="flex-1 flex flex-col overflow-hidden bg-slate-900/50 relative"> | |
| <!-- Top Bar --> | |
| <header class="h-16 border-b border-slate-700/50 flex items-center justify-between px-4 lg:px-6 glass z-30"> | |
| <div class="flex items-center space-x-4"> | |
| <button onclick="toggleSidebar()" class="lg:hidden p-2 hover:bg-slate-800 rounded-lg transition-colors"> | |
| <i data-lucide="menu" class="w-5 h-5"></i> | |
| </button> | |
| <div class="hidden sm:flex items-center space-x-2 text-sm text-slate-400"> | |
| <span>Workspace</span> | |
| <i data-lucide="chevron-right" class="w-4 h-4"></i> | |
| <span class="text-slate-200" id="header-project">AgentFlow Core</span> | |
| </div> | |
| </div> | |
| <div class="flex items-center space-x-3"> | |
| <button onclick="toggleSearch()" class="hidden md:flex items-center space-x-2 px-3 py-1.5 rounded-lg bg-slate-800/50 hover:bg-slate-700/50 border border-slate-700/50 text-sm text-slate-400 transition-all"> | |
| <i data-lucide="search" class="w-4 h-4"></i> | |
| <span>Search...</span> | |
| <span class="text-xs bg-slate-700 px-1.5 py-0.5 rounded">⌘K</span> | |
| </button> | |
| <div class="relative"> | |
| <button onclick="toggleNotifications()" class="p-2 hover:bg-slate-800 rounded-lg transition-colors relative"> | |
| <i data-lucide="bell" class="w-5 h-5"></i> | |
| <span id="notification-count" class="absolute top-1.5 right-1.5 w-2 h-2 bg-red-500 rounded-full hidden notification-badge"></span> | |
| </button> | |
| <!-- Notifications Dropdown --> | |
| <div id="notifications-panel" class="hidden absolute right-0 top-full mt-2 w-80 glass-strong rounded-xl shadow-2xl border border-slate-700/50 overflow-hidden z-50 animate-fade-in"> | |
| <div class="p-4 border-b border-slate-700/50 flex items-center justify-between"> | |
| <h3 class="font-semibold">Notifications</h3> | |
| <button onclick="markAllRead()" class="text-xs text-indigo-400 hover:text-indigo-300">Mark all read</button> | |
| </div> | |
| <div id="notifications-list" class="max-h-64 overflow-y-auto"> | |
| <!-- Notifications injected by JS --> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="relative group"> | |
| <button class="flex items-center space-x-2 p-1.5 rounded-lg hover:bg-slate-800 transition-colors"> | |
| <div class="w-8 h-8 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center text-white font-semibold text-sm"> | |
| JD | |
| </div> | |
| </button> | |
| <!-- User Dropdown --> | |
| <div class="hidden group-hover:block absolute right-0 top-full mt-2 w-48 glass-strong rounded-xl shadow-2xl border border-slate-700/50 overflow-hidden z-50 animate-fade-in"> | |
| <div class="p-3 border-b border-slate-700/50"> | |
| <p class="font-medium text-sm">John Doe</p> | |
| <p class="text-xs text-slate-400">john@agentflow.ai</p> | |
| </div> | |
| <div class="p-1"> | |
| <button onclick="openProfile()" class="w-full flex items-center space-x-2 p-2 rounded-lg hover:bg-slate-700/50 text-left text-sm transition-colors"> | |
| <i data-lucide="user" class="w-4 h-4"></i> | |
| <span>Profile</span> | |
| </button> | |
| <button onclick="openSettings()" class="w-full flex items-center space-x-2 p-2 rounded-lg hover:bg-slate-700/50 text-left text-sm transition-colors"> | |
| <i data-lucide="settings" class="w-4 h-4"></i> | |
| <span>Settings</span> | |
| </button> | |
| <div class="border-t border-slate-700/50 my-1"></div> | |
| <button onclick="logout()" class="w-full flex items-center space-x-2 p-2 rounded-lg hover:bg-red-500/20 text-left text-sm text-red-400 transition-colors"> | |
| <i data-lucide="log-out" class="w-4 h-4"></i> | |
| <span>Logout</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Content Grid --> | |
| <div class="flex-1 flex flex-col lg:flex-row overflow-hidden"> | |
| <!-- Chat Area --> | |
| <div class="flex-1 flex flex-col min-w-0 border-r border-slate-700/50"> | |
| <!-- Chat Header --> | |
| <div class="h-14 border-b border-slate-700/50 flex items-center justify-between px-4 lg:px-6 glass"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-2 h-2 rounded-full bg-green-400 animate-pulse"></div> | |
| <h2 class="font-semibold text-slate-200">Agent Conversation</h2> | |
| <span class="text-xs px-2 py-0.5 rounded-full bg-slate-700 text-slate-400" id="message-count">0 messages</span> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <button onclick="toggleChatSettings()" class="p-2 hover:bg-slate-800 rounded-lg transition-colors"> | |
| <i data-lucide="sliders" class="w-4 h-4 text-slate-400"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Messages --> | |
| <div id="chat-messages" class="flex-1 overflow-y-auto p-4 lg:p-6 space-y-4 scroll-smooth"> | |
| <!-- Welcome Message --> | |
| <div class="flex justify-start animate-fade-in"> | |
| <div class="max-w-[85%] lg:max-w-[70%] message-bubble bg-slate-800/80 rounded-2xl rounded-tl-sm px-4 py-3 border border-slate-700/50"> | |
| <div class="flex items-start space-x-3"> | |
| <div class="w-8 h-8 rounded-lg bg-indigo-500/20 flex-shrink-0 flex items-center justify-center mt-0.5"> | |
| <i data-lucide="bot" class="w-4 h-4 text-indigo-400"></i> | |
| </div> | |
| <div class="flex-1 space-y-1"> | |
| <p class="text-sm text-slate-200">Welcome to <strong>AgentFlow Nexus</strong>! 🚀</p> | |
| <p class="text-sm text-slate-400">I'm your AI assistant powered by GPT-4. I can help you with:</p> | |
| <ul class="text-sm text-slate-400 list-disc list-inside space-y-1 ml-1"> | |
| <li>Writing and analyzing code</li> | |
| <li>Managing tasks and projects</li> | |
| <li>Processing files and data</li> | |
| <li>Research and brainstorming</li> | |
| </ul> | |
| <p class="text-xs text-slate-500 mt-2">Try typing a message or use the code editor on the right!</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Input Area --> | |
| <div class="p-4 lg:p-6 border-t border-slate-700/50 glass"> | |
| <div class="max-w-4xl mx-auto space-y-3"> | |
| <!-- Attachment Preview --> | |
| <div id="attachment-preview" class="hidden flex items-center space-x-2 p-2 bg-slate-800/50 rounded-lg border border-slate-700/50"> | |
| <i data-lucide="file" class="w-4 h-4 text-indigo-400"></i> | |
| <span class="text-sm text-slate-300 flex-1 truncate" id="attachment-name">file.txt</span> | |
| <button onclick="clearAttachment()" class="p-1 hover:bg-slate-700 rounded transition-colors"> | |
| <i data-lucide="x" class="w-4 h-4"></i> | |
| </button> | |
| </div> | |
| <div class="relative flex items-end space-x-2 bg-slate-800/50 rounded-xl border border-slate-700/50 focus-within:border-indigo-500/50 focus-within:ring-2 focus-within:ring-indigo-500/20 transition-all input-glow"> | |
| <button onclick="attachFile()" class="p-3 text-slate-400 hover:text-slate-200 transition-colors"> | |
| <i data-lucide="paperclip" class="w-5 h-5"></i> | |
| </button> | |
| <textarea id="message-input" rows="1" placeholder="Type your message... (Shift+Enter for new line)" | |
| class="flex-1 bg-transparent border-0 py-3 px-0 text-slate-200 placeholder-slate-500 resize-none focus:outline-none max-h-32" | |
| oninput="autoResize(this)" | |
| onkeydown="handleKeyDown(event)"></textarea> | |
| <div class="flex items-center space-x-1 pr-2 pb-2"> | |
| <button onclick="toggleEmojiPicker()" class="p-2 text-slate-400 hover:text-slate-200 transition-colors"> | |
| <i data-lucide="smile" class="w-5 h-5"></i> | |
| </button> | |
| <button onclick="sendMessage()" id="send-button" class="p-2 bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg transition-all transform hover:scale-105 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed"> | |
| <i data-lucide="send" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="flex items-center justify-between text-xs text-slate-500 px-1"> | |
| <span>Press <kbd class="px-1.5 py-0.5 bg-slate-800 rounded text-slate-400">⌘</kbd> <kbd class="px-1.5 py-0.5 bg-slate-800 rounded text-slate-400">K</kbd> to search</span> | |
| <span id="input-stats">0/2000</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Right Panel --> | |
| <div class="w-full lg:w-[450px] flex flex-col bg-slate-900/30 border-l border-slate-700/50"> | |
| <!-- Tabs --> | |
| <div class="flex border-b border-slate-700/50 glass"> | |
| <button onclick="switchTab('editor')" data-tab="editor" class="tab-btn flex-1 py-3 px-4 text-sm font-medium text-indigo-400 border-b-2 border-indigo-500 transition-all hover:bg-slate-800/50 flex items-center justify-center space-x-2"> | |
| <i data-lucide="code-2" class="w-4 h-4"></i> | |
| <span>Editor</span> | |
| </button> | |
| <button onclick="switchTab('tasks')" data-tab="tasks" class="tab-btn flex-1 py-3 px-4 text-sm font-medium text-slate-400 border-b-2 border-transparent transition-all hover:bg-slate-800/50 flex items-center justify-center space-x-2"> | |
| <i data-lucide="check-square" class="w-4 h-4"></i> | |
| <span>Tasks</span> | |
| <span id="task-badge" class="hidden ml-1.5 px-1.5 py-0.5 text-xs bg-indigo-500/20 text-indigo-400 rounded-full">0</span> | |
| </button> | |
| <button onclick="switchTab('files')" data-tab="files" class="tab-btn flex-1 py-3 px-4 text-sm font-medium text-slate-400 border-b-2 border-transparent transition-all hover:bg-slate-800/50 flex items-center justify-center space-x-2"> | |
| <i data-lucide="folder" class="w-4 h-4"></i> | |
| <span>Files</span> | |
| </button> | |
| </div> | |
| <!-- Tab Contents --> | |
| <div class="flex-1 overflow-hidden relative"> | |
| <!-- Editor Panel --> | |
| <div id="editor-panel" class="tab-content absolute inset-0 flex flex-col p-4 overflow-y-auto"> | |
| <div class="flex items-center justify-between mb-3"> | |
| <div class="flex items-center space-x-2"> | |
| <select id="language-select" onchange="changeLanguage()" class="bg-slate-800 border border-slate-700 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:border-indigo-500/50"> | |
| <option value="javascript">JavaScript</option> | |
| <option value="python">Python</option> | |
| <option value="html">HTML</option> | |
| <option value="css">CSS</option> | |
| <option value="typescript">TypeScript</option> | |
| </select> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <button onclick="formatCode()" class="p-2 hover:bg-slate-800 rounded-lg text-slate-400 hover:text-slate-200 transition-colors" title="Format Code"> | |
| <i data-lucide="align-left" class="w-4 h-4"></i> | |
| </button> | |
| <button onclick="runCode()" class="flex items-center space-x-1 px-3 py-1.5 bg-green-600/20 text-green-400 hover:bg-green-600/30 rounded-lg text-sm font-medium transition-all"> | |
| <i data-lucide="play" class="w-4 h-4"></i> | |
| <span>Run</span> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="relative flex-1 min-h-[300px]"> | |
| <div class="absolute inset-0 bg-slate-950 rounded-lg border border-slate-800 overflow-hidden flex flex-col"> | |
| <div class="flex-1 relative"> | |
| <textarea id="code-editor" class="absolute inset-0 w-full h-full bg-transparent text-slate-300 font-mono text-sm p-4 resize-none focus:outline-none line-numbers leading-relaxed" | |
| placeholder="// Write your code here..." spellcheck="false">// Welcome to the Code Editor | |
| function greet(name) { | |
| return `Hello, ${name}! Welcome to AgentFlow.`; | |
| } | |
| console.log(greet('Developer'));</textarea> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="code-output" class="mt-3 p-3 bg-slate-950 rounded-lg border border-slate-800 hidden"> | |
| <div class="flex items-center justify-between mb-2"> | |
| <span class="text-xs font-medium text-slate-400 uppercase">Output</span> | |
| <button onclick="clearOutput()" class="text-xs text-slate-500 hover:text-slate-300">Clear</button> | |
| </div> | |
| <pre class="text-sm font-mono text-green-400 overflow-x-auto"></pre> | |
| </div> | |
| <div class="mt-3 flex items-center justify-between"> | |
| <button onclick="sendCodeToChat()" class="flex items-center space-x-2 text-sm text-indigo-400 hover:text-indigo-300 transition-colors"> | |
| <i data-lucide="message-square" class="w-4 h-4"></i> | |
| <span>Send to Chat</span> | |
| </button> | |
| <button onclick="saveCode()" class="flex items-center space-x-2 text-sm text-slate-400 hover:text-slate-200 transition-colors"> | |
| <i data-lucide="save" class="w-4 h-4"></i> | |
| <span>Save</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Tasks Panel --> | |
| <div id="tasks-panel" class="tab-content absolute inset-0 flex flex-col hidden"> | |
| <div class="p-4 border-b border-slate-700/50 flex items-center justify-between glass"> | |
| <div class="flex items-center space-x-2"> | |
| <h3 class="font-semibold">Task Board</h3> | |
| <span id="task-count" class="text-xs px-2 py-0.5 bg-slate-700 rounded-full text-slate-400">0</span> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <select id="task-filter" onchange="filterTasks()" class="bg-slate-800 border border-slate-700 rounded-lg px-2 py-1 text-xs focus:outline-none focus:border-indigo-500/50"> | |
| <option value="all">All</option> | |
| <option value="active">Active</option> | |
| <option value="completed">Completed</option> | |
| </select> | |
| <button onclick="addTask()" class="p-2 bg-indigo-600 hover:bg-indigo-500 rounded-lg transition-all hover:scale-105"> | |
| <i data-lucide="plus" class="w-4 h-4"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="flex-1 overflow-y-auto p-4 space-y-3" id="task-list"> | |
| <!-- Tasks injected by JS --> | |
| </div> | |
| <!-- Task Stats --> | |
| <div class="p-4 border-t border-slate-700/50 glass"> | |
| <div class="flex items-center justify-between text-sm"> | |
| <span class="text-slate-400" id="task-progress-text">0/0 completed</span> | |
| <div class="w-24 h-2 bg-slate-800 rounded-full overflow-hidden"> | |
| <div id="task-progress-bar" class="h-full bg-indigo-500 transition-all duration-500" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Files Panel --> | |
| <div id="files-panel" class="tab-content absolute inset-0 flex flex-col hidden"> | |
| <div class="p-4 border-b border-slate-700/50 flex items-center justify-between glass"> | |
| <h3 class="font-semibold">File Manager</h3> | |
| <div class="flex items-center space-x-2"> | |
| <button onclick="createFolder()" class="p-2 hover:bg-slate-800 rounded-lg transition-colors text-slate-400"> | |
| <i data-lucide="folder-plus" class="w-4 h-4"></i> | |
| </button> | |
| <label class="p-2 bg-indigo-600 hover:bg-indigo-500 rounded-lg transition-all hover:scale-105 cursor-pointer"> | |
| <i data-lucide="upload" class="w-4 h-4"></i> | |
| <input type="file" class="hidden" multiple onchange="handleFileUpload(event)"> | |
| </label> | |
| </div> | |
| </div> | |
| <!-- Drop Zone --> | |
| <div id="drop-zone" class="m-4 p-8 border-2 border-dashed border-slate-700 rounded-xl text-center drop-zone"> | |
| <i data-lucide="upload-cloud" class="w-8 h-8 text-slate-500 mx-auto mb-2"></i> | |
| <p class="text-sm text-slate-400">Drop files here or click upload</p> | |
| </div> | |
| <div class="flex-1 overflow-y-auto px-4 pb-4"> | |
| <div id="file-list" class="space-y-1"> | |
| <!-- Files injected by JS --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Status Bar --> | |
| <div class="h-8 bg-slate-950 border-t border-slate-800 flex items-center justify-between px-4 text-xs text-slate-500"> | |
| <div class="flex items-center space-x-4"> | |
| <span class="flex items-center space-x-1.5"> | |
| <span class="w-1.5 h-1.5 rounded-full bg-green-500"></span> | |
| <span>Connected</span> | |
| </span> | |
| <span class="hidden sm:inline" id="status-agent">Agent: Chat Agent</span> | |
| <span class="hidden md:inline" id="status-project">Project: AgentFlow Core</span> | |
| <span class="hidden lg:inline flex items-center space-x-1"> | |
| <i data-lucide="clock" class="w-3 h-3"></i> | |
| <span id="last-updated">Just now</span> | |
| </span> | |
| </div> | |
| <div class="flex items-center space-x-3"> | |
| <button onclick="showShortcuts()" class="hover:text-slate-300 transition-colors flex items-center space-x-1"> | |
| <i data-lucide="keyboard" class="w-3 h-3"></i> | |
| <span>Shortcuts</span> | |
| </button> | |
| <span>v2.0.0</span> | |
| </div> | |
| </div> | |
| <!-- Search Modal --> | |
| <div id="search-modal" class="fixed inset-0 z-50 hidden modal-overlay flex items-start justify-center pt-[20vh]"> | |
| <div class="w-full max-w-2xl mx-4 glass-strong rounded-xl shadow-2xl border border-slate-700/50 overflow-hidden animate-fade-in"> | |
| <div class="p-4 border-b border-slate-700/50 flex items-center space-x-3"> | |
| <i data-lucide="search" class="w-5 h-5 text-slate-400"></i> | |
| <input type="text" id="search-input" placeholder="Search messages, files, tasks..." | |
| class="flex-1 bg-transparent border-0 text-slate-200 placeholder-slate-500 focus:outline-none text-lg" | |
| oninput="performSearch(this.value)"> | |
| <kbd class="px-2 py-1 bg-slate-800 rounded text-xs text-slate-400">ESC</kbd> | |
| </div> | |
| <div id="search-results" class="max-h-[60vh] overflow-y-auto p-2"> | |
| <div class="p-8 text-center text-slate-500"> | |
| <i data-lucide="search" class="w-12 h-12 mx-auto mb-3 opacity-50"></i> | |
| <p>Start typing to search...</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Agent Selector Modal --> | |
| <div id="agent-modal" class="fixed inset-0 z-50 hidden modal-overlay flex items-center justify-center p-4"> | |
| <div class="w-full max-w-md glass-strong rounded-2xl shadow-2xl border border-slate-700/50 overflow-hidden animate-fade-in"> | |
| <div class="p-6 border-b border-slate-700/50"> | |
| <h3 class="text-xl font-bold mb-2">Select Agent</h3> | |
| <p class="text-sm text-slate-400">Choose an AI agent specialized for your task</p> | |
| </div> | |
| <div class="p-4 space-y-2" id="agent-list"> | |
| <!-- Agents injected by JS --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Keyboard Shortcuts Modal --> | |
| <div id="shortcuts-modal" class="fixed inset-0 z-50 hidden modal-overlay flex items-center justify-center p-4"> | |
| <div class="w-full max-w-lg glass-strong rounded-2xl shadow-2xl border border-slate-700/50 overflow-hidden animate-fade-in"> | |
| <div class="p-6 border-b border-slate-700/50 flex items-center justify-between"> | |
| <h3 class="text-xl font-bold">Keyboard Shortcuts</h3> | |
| <button onclick="closeModals()" class="p-2 hover:bg-slate-800 rounded-lg transition-colors"> | |
| <i data-lucide="x" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| <div class="p-6 grid grid-cols-2 gap-4 text-sm"> | |
| <div class="flex items-center justify-between p-3 bg-slate-800/50 rounded-lg"> | |
| <span class="text-slate-300">New Chat</span> | |
| <kbd class="px-2 py-1 bg-slate-700 rounded text-xs">⌘N</kbd> | |
| </div> | |
| <div class="flex items-center justify-between p-3 bg-slate-800/50 rounded-lg"> | |
| <span class="text-slate-300">Send Message</span> | |
| <kbd class="px-2 py-1 bg-slate-700 rounded text-xs">↵</kbd> | |
| </div> | |
| <div class="flex items-center justify-between p-3 bg-slate-800/50 rounded-lg"> | |
| <span class="text-slate-300">Search</span> | |
| <kbd class="px-2 py-1 bg-slate-700 rounded text-xs">⌘K</kbd> | |
| </div> | |
| <div class="flex items-center justify-between p-3 bg-slate-800/50 rounded-lg"> | |
| <span class="text-slate-300">Toggle Sidebar</span> | |
| <kbd class="px-2 py-1 bg-slate-700 rounded text-xs">⌘B</kbd> | |
| </div> | |
| <div class="flex items-center justify-between p-3 bg-slate-800/50 rounded-lg"> | |
| <span class="text-slate-300">Run Code</span> | |
| <kbd class="px-2 py-1 bg-slate-700 rounded text-xs">⌘↵</kbd> | |
| </div> | |
| <div class="flex items-center justify-between p-3 bg-slate-800/50 rounded-lg"> | |
| <span class="text-slate-300">Close Modal</span> | |
| <kbd class="px-2 py-1 bg-slate-700 rounded text-xs">ESC</kbd> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // State Management | |
| const state = { | |
| currentAgent: 'chat', | |
| currentProject: 'AgentFlow Core', | |
| theme: localStorage.getItem('theme') || 'dark', | |
| messages: JSON.parse(localStorage.getItem('messages')) || [], | |
| tasks: JSON.parse(localStorage.getItem('tasks')) || [ | |
| { id: 1, text: 'Review pull requests', completed: false, priority: 'high', dueDate: '2024-01-20' }, | |
| { id: 2, text: 'Update documentation', completed: true, priority: 'medium', dueDate: '2024-01-18' }, | |
| { id: 3, text: 'Fix navigation bug', completed: false, priority: 'low', dueDate: '2024-01-25' } | |
| ], | |
| files: JSON.parse(localStorage.getItem('files')) || [ | |
| { name: 'project_spec.md', size: '2.4 KB', type: 'text', date: '2024-01-15' }, | |
| { name: 'api_client.js', size: '12.8 KB', type: 'code', date: '2024-01-14' }, | |
| { name: 'design_mockup.png', size: '1.2 MB', type: 'image', date: '2024-01-13' } | |
| ], | |
| notifications: [ | |
| { id: 1, text: 'New task assigned to you', time: '2m ago', read: false }, | |
| { id: 2, text: 'Code execution completed', time: '5m ago', read: true }, | |
| { id: 3, text: 'File upload successful', time: '1h ago', read: true } | |
| ], | |
| agents: [ | |
| { id: 'chat', name: 'Chat Agent', model: 'GPT-4 Turbo', icon: 'message-square', desc: 'General conversation and assistance' }, | |
| { id: 'code', name: 'Code Agent', model: 'Codex', icon: 'code', desc: 'Programming and debugging' }, | |
| { id: 'data', name: 'Data Agent', model: 'GPT-4', icon: 'database', desc: 'Data analysis and processing' }, | |
| { id: 'creative', name: 'Creative Agent', model: 'GPT-4', icon: 'sparkles', desc: 'Content creation and design' } | |
| ], | |
| projects: [ | |
| { id: 1, name: 'AgentFlow Core', color: 'green', active: true }, | |
| { id: 2, name: 'UI Components', color: 'blue', active: false }, | |
| { id: 3, name: 'API Integration', color: 'yellow', active: false } | |
| ] | |
| }; | |
| // Initialization | |
| document.addEventListener('DOMContentLoaded', () => { | |
| lucide.createIcons(); | |
| applyTheme(state.theme); | |
| renderProjects(); | |
| renderTasks(); | |
| renderFiles(); | |
| renderAgents(); | |
| renderNotifications(); | |
| updateTaskStats(); | |
| loadMessages(); | |
| // Setup drag and drop | |
| setupDragAndDrop(); | |
| // Keyboard shortcuts | |
| document.addEventListener('keydown', handleGlobalKeys); | |
| // Auto-resize textarea | |
| const textarea = document.getElementById('message-input'); | |
| textarea.addEventListener('input', () => autoResize(textarea)); | |
| // Close modals on outside click | |
| document.querySelectorAll('.modal-overlay').forEach(modal => { | |
| modal.addEventListener('click', (e) => { | |
| if (e.target === modal) closeModals(); | |
| }); | |
| }); | |
| }); | |
| // Theme Management | |
| function toggleTheme() { | |
| state.theme = state.theme === 'dark' ? 'light' : 'dark'; | |
| localStorage.setItem('theme', state.theme); | |
| applyTheme(state.theme); | |
| } | |
| function applyTheme(theme) { | |
| const body = document.getElementById('app-body'); | |
| if (theme === 'light') { | |
| body.classList.remove('bg-slate-900', 'text-slate-100'); | |
| body.classList.add('bg-slate-50', 'text-slate-900'); | |
| // Add more light mode specific changes | |
| document.querySelectorAll('.glass, .glass-strong').forEach(el => { | |
| el.style.background = 'rgba(255, 255, 255, 0.8)'; | |
| el.style.borderColor = 'rgba(0, 0, 0, 0.1)'; | |
| }); | |
| } else { | |
| body.classList.add('bg-slate-900', 'text-slate-100'); | |
| body.classList.remove('bg-slate-50', 'text-slate-900'); | |
| document.querySelectorAll('.glass, .glass-strong').forEach(el => { | |
| el.style.background = ''; | |
| el.style.borderColor = ''; | |
| }); | |
| } | |
| } | |
| // Sidebar Toggle | |
| function toggleSidebar() { | |
| const sidebar = document.getElementById('sidebar'); | |
| const overlay = document.getElementById('sidebar-overlay'); | |
| const isOpen = !sidebar.classList.contains('-translate-x-full'); | |
| if (isOpen) { | |
| sidebar.classList.add('-translate-x-full'); | |
| overlay.classList.add('hidden'); | |
| } else { | |
| sidebar.classList.remove('-translate-x-full'); | |
| overlay.classList.remove('hidden'); | |
| } | |
| } | |
| // Chat Functions | |
| function autoResize(textarea) { | |
| textarea.style.height = 'auto'; | |
| textarea.style.height = Math.min(textarea.scrollHeight, 128) + 'px'; | |
| // Update stats | |
| const stats = document.getElementById('input-stats'); | |
| stats.textContent = `${textarea.value.length}/2000`; | |
| } | |
| function handleKeyDown(e) { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| sendMessage(); | |
| } | |
| } | |
| function sendMessage() { | |
| const input = document.getElementById('message-input'); | |
| const content = input.value.trim(); | |
| if (!content && !state.currentAttachment) return; | |
| // Add user message | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = 'flex justify-end animate-fade-in'; | |
| let attachmentHtml = ''; | |
| if (state.currentAttachment) { | |
| attachmentHtml = ` | |
| <div class="flex items-center space-x-2 mt-2 p-2 bg-indigo-700/30 rounded border border-indigo-500/30"> | |
| <i data-lucide="file" class="w-4 h-4"></i> | |
| <span class="text-sm">${state.currentAttachment.name}</span> | |
| </div> | |
| `; | |
| } | |
| messageDiv.innerHTML = ` | |
| <div class="max-w-[85%] lg:max-w-[70%] message-bubble bg-indigo-600 text-white rounded-2xl rounded-tr-sm px-4 py-3 shadow-lg"> | |
| <p class="text-sm leading-relaxed">${escapeHtml(content)}</p> | |
| ${attachmentHtml} | |
| <span class="text-xs text-indigo-200 mt-1 block text-right">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span> | |
| </div> | |
| `; | |
| document.getElementById('chat-messages').appendChild(messageDiv); | |
| lucide.createIcons(); | |
| // Save message | |
| state.messages.push({ content, type: 'user', time: new Date() }); | |
| localStorage.setItem('messages', JSON.stringify(state.messages)); | |
| // Clear input | |
| input.value = ''; | |
| input.style.height = 'auto'; | |
| document.getElementById('input-stats').textContent = '0/2000'; | |
| clearAttachment(); | |
| // Update count | |
| updateMessageCount(); | |
| // Scroll to bottom | |
| const container = document.getElementById('chat-messages'); | |
| container.scrollTop = container.scrollHeight; | |
| // Show typing indicator | |
| showTypingIndicator(); | |
| // Simulate response | |
| setTimeout(() => { | |
| removeTypingIndicator(); | |
| addBotResponse(content); | |
| }, 1500 + Math.random() * 1000); | |
| } | |
| function addBotResponse(userMessage) { | |
| const responses = [ | |
| "I've analyzed your request. Here's what I found...", | |
| "Great question! Let me break this down for you:\n\n1. First point\n2. Second point\n3. Third point", | |
| "I can help with that. Here's a code example:\n\n |