| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>π€ AI-Robotic Orchestrator v3.0</title> |
| <style> |
| :root { |
| --bg-dark: #0a0f14; |
| --bg-panel: #141a20; |
| --neon-green: #00ffaa; |
| --neon-blue: #00d4ff; |
| --neon-red: #ff3366; |
| --text-main: #e0e6ed; |
| --text-muted: #7a8b9e; |
| --border-glow: rgba(0, 255, 170, 0.2); |
| } |
| |
| * { box-sizing: border-box; margin: 0; padding: 0; } |
| |
| body { |
| font-family: 'Segoe UI', 'Courier New', monospace, sans-serif; |
| background-color: var(--bg-dark); |
| color: var(--text-main); |
| padding: 20px; |
| display: flex; |
| justify-content: center; |
| min-height: 100vh; |
| background-image: |
| linear-gradient(rgba(0, 255, 170, 0.03) 1px, transparent 1px), |
| linear-gradient(90deg, rgba(0, 255, 170, 0.03) 1px, transparent 1px); |
| background-size: 40px 40px; |
| } |
| |
| .container { |
| max-width: 1100px; |
| width: 100%; |
| background: var(--bg-panel); |
| border: 1px solid var(--border-glow); |
| border-radius: 16px; |
| padding: 30px; |
| box-shadow: 0 0 30px rgba(0, 255, 170, 0.05); |
| position: relative; |
| } |
| |
| |
| h1 { text-align: center; color: var(--neon-green); text-shadow: 0 0 15px rgba(0, 255, 170, 0.4); margin-bottom: 5px; letter-spacing: 2px; } |
| .subtitle { text-align: center; color: var(--text-muted); margin-bottom: 25px; border-bottom: 1px solid #2a3540; padding-bottom: 15px; } |
| |
| |
| .robot-status-panel { |
| display: flex; justify-content: space-between; background: #0d1219; |
| border: 1px solid #2a3540; border-radius: 8px; padding: 15px 20px; |
| margin-bottom: 25px; flex-wrap: wrap; gap: 10px; |
| } |
| .stat-item { display: flex; flex-direction: column; } |
| .stat-label { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px;} |
| .stat-value { font-weight: bold; font-size: 1.1rem; font-family: 'Courier New', monospace; } |
| .blink { animation: blinker 1.5s linear infinite; } |
| @keyframes blinker { 50% { opacity: 0.3; } } |
| |
| |
| .server-grid { display: flex; justify-content: space-between; gap: 15px; flex-wrap: wrap; margin-bottom: 25px; } |
| .server-card { |
| flex: 1; min-width: 180px; background: #11181f; border: 1px solid #2a3540; |
| border-radius: 10px; padding: 20px 15px; text-align: center; transition: 0.3s; |
| } |
| .server-card h3 { margin: 0 0 15px 0; color: var(--neon-blue); } |
| |
| .status-badge { |
| display: inline-block; padding: 6px 16px; border-radius: 20px; font-size: 0.8rem; |
| font-weight: bold; text-transform: uppercase; background: #2a3540; color: var(--text-muted); |
| } |
| .status-primary { background: rgba(0, 255, 170, 0.2); color: var(--neon-green); border: 1px solid var(--neon-green); box-shadow: 0 0 10px rgba(0,255,170,0.1); } |
| .status-secondary { background: rgba(0, 212, 255, 0.1); color: var(--neon-blue); border: 1px solid var(--neon-blue); } |
| .status-excluded { background: rgba(255, 51, 102, 0.1); color: var(--neon-red); border: 1px solid var(--neon-red); } |
| |
| .db-box { margin-top: 12px; font-size: 0.8rem; background: #0d1219; padding: 6px; border-radius: 4px; border-left: 2px solid #2a3540; } |
| .db-box.ha { border-left-color: var(--neon-green); } |
| |
| |
| .ai-control-panel { background: rgba(0, 0, 0, 0.4); border: 1px solid #2a3540; border-radius: 10px; padding: 20px; margin-bottom: 25px; } |
| .ai-control-panel h2 { margin-top: 0; color: var(--neon-blue); font-size: 1.1rem; border-bottom: 1px solid #2a3540; padding-bottom: 10px; } |
| .control-group { display: flex; gap: 10px; flex-wrap: wrap; margin: 15px 0; } |
| |
| button { |
| background: transparent; color: var(--text-main); border: 1px solid #2a3540; |
| padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: 600; transition: 0.2s; |
| } |
| button:hover { background: #2a3540; } |
| button.primary-act { border-color: var(--neon-green); color: var(--neon-green); } |
| button.primary-act:hover { box-shadow: 0 0 15px rgba(0,255,170,0.2); background: rgba(0,255,170,0.1); } |
| button.danger { border-color: var(--neon-red); color: var(--neon-red); } |
| button.danger:hover { background: rgba(255,51,102,0.1); box-shadow: 0 0 15px rgba(255,51,102,0.2); } |
| button:disabled { opacity: 0.5; cursor: not-allowed; } |
| |
| |
| .explorer-panel { |
| background: rgba(0,0,0,0.3); |
| border: 2px solid var(--neon-blue); |
| border-radius: 10px; |
| padding: 20px; |
| margin: 20px 0; |
| max-height: 0; |
| overflow: hidden; |
| transition: max-height 0.5s ease-out; |
| } |
| .explorer-panel.open { max-height: 600px; overflow-y: auto; } |
| .explorer-panel::-webkit-scrollbar { width: 5px; } |
| .explorer-panel::-webkit-scrollbar-track { background: #0d1219; } |
| .explorer-panel::-webkit-scrollbar-thumb { background: var(--neon-blue); border-radius: 10px; } |
| |
| .search-box { width: 100%; background: #141a20; border: 1px solid #2a3540; color: white; padding: 10px; border-radius: 6px; margin-bottom: 15px; outline: none; } |
| .search-box:focus { border-color: var(--neon-blue); } |
| |
| .lib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; } |
| .lib-item { |
| background: #11181f; border: 1px solid #2a3540; border-radius: 6px; |
| padding: 10px; text-align: center; transition: 0.2s; cursor: pointer; |
| } |
| .lib-item:hover { border-color: var(--neon-green); background: #1a232c; transform: scale(1.02); } |
| .lib-name { color: var(--neon-green); font-size: 0.9rem; font-weight: bold; } |
| .lib-desc { color: var(--text-muted); font-size: 0.75rem; margin-top: 5px; } |
| |
| |
| .ai-terminal { background: #0a0b0d; border: 1px solid #2a3540; border-radius: 8px; padding: 5px; margin-bottom: 20px; } |
| .terminal-header { background: #141a20; padding: 8px 15px; border-bottom: 1px solid #2a3540; color: var(--text-muted); display: flex; justify-content: space-between; border-radius: 8px 8px 0 0; } |
| .terminal-window { padding: 15px; height: 140px; overflow-y: auto; font-family: 'Courier New', monospace; font-size: 0.9rem; color: #bbb; } |
| .terminal-window::-webkit-scrollbar { width: 5px; } |
| .terminal-window::-webkit-scrollbar-track { background: #0a0b0d; } |
| .terminal-window::-webkit-scrollbar-thumb { background: #2a3540; border-radius: 10px; } |
| .log-line { margin-bottom: 3px; } |
| .log-error { color: var(--neon-red); } |
| .log-success { color: var(--neon-green); } |
| .log-info { color: var(--neon-blue); } |
| .log-warn { color: #ffaa00; } |
| |
| |
| .chat-container { |
| margin-top: 10px; |
| background: #0d1219; |
| border: 1px solid var(--neon-blue); |
| border-radius: 10px; |
| padding: 15px; |
| box-shadow: 0 0 20px rgba(0, 212, 255, 0.1); |
| } |
| .chat-header { color: var(--neon-blue); font-weight: bold; border-bottom: 1px solid #2a3540; padding-bottom: 10px; margin-bottom: 10px; display: flex; justify-content: space-between; } |
| .chat-messages { height: 150px; overflow-y: auto; margin-bottom: 15px; padding-right: 5px;} |
| .chat-messages::-webkit-scrollbar { width: 5px; } |
| .chat-messages::-webkit-scrollbar-track { background: #0d1219; } |
| .chat-messages::-webkit-scrollbar-thumb { background: var(--neon-blue); border-radius: 10px; } |
| |
| .msg { display: flex; margin-bottom: 10px; } |
| .msg.user { justify-content: flex-end; } |
| .msg.bot { justify-content: flex-start; } |
| .bubble { max-width: 80%; padding: 8px 15px; border-radius: 15px; font-size: 0.9rem; } |
| .user .bubble { background: #005c99; color: white; border-bottom-right-radius: 2px; } |
| .bot .bubble { background: #2a3540; color: #e0e6ed; border-bottom-left-radius: 2px; } |
| .typing-indicator { color: var(--neon-blue); font-size: 0.8rem; font-style: italic; margin-left: 10px; display: none; } |
| |
| .chat-input-group { display: flex; gap: 10px; } |
| .chat-input-group input { flex: 1; background: #141a20; border: 1px solid #2a3540; color: white; padding: 10px; border-radius: 6px; outline: none; } |
| .chat-input-group input:focus { border-color: var(--neon-blue); } |
| .chat-input-group button { border-color: var(--neon-blue); color: var(--neon-blue); padding: 10px 20px; border-radius: 6px;} |
| |
| |
| .social-footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #2a3540; text-align: center; } |
| .social-links { display: flex; justify-content: center; gap: 15px; flex-wrap: wrap; margin-top: 10px; } |
| .social-btn { display: inline-flex; align-items: center; gap: 8px; background: transparent; border: 1px solid #2a3540; padding: 8px 18px; border-radius: 30px; text-decoration: none; color: var(--text-muted); font-size: 0.9rem; transition: 0.2s; } |
| .social-btn:hover { background: #2a3540; border-color: var(--neon-blue); color: white; } |
| .creator-credit { margin-top: 20px; font-size: 0.9rem; color: #555; border-top: 1px solid #1a232c; padding-top: 15px; } |
| .creator-credit strong { color: var(--neon-blue); } |
| </style> |
| </head> |
| <body> |
|
|
| <div class="container"> |
| <h1>π€ AI-Robotic Orchestrator v3.0</h1> |
| <div class="subtitle">AG1-Sample :: Autonomous AI Library & Hub Explorer</div> |
|
|
| |
| <div class="robot-status-panel"> |
| <div class="stat-item"><span class="stat-label">System Status</span><span class="stat-value blink" style="color: var(--neon-green);">β ACTIVE</span></div> |
| <div class="stat-item"><span class="stat-label">Uptime</span><span class="stat-value" id="robotUptime">00:00:00</span></div> |
| <div class="stat-item"><span class="stat-label">Active Primary</span><span class="stat-value" id="currentPrimaryDisplay" style="color: var(--neon-green);">Server1</span></div> |
| <div class="stat-item"><span class="stat-label">CPU Load</span><span class="stat-value" id="cpuLoad">12%</span></div> |
| </div> |
|
|
| |
| <div class="server-grid" id="serverGrid"></div> |
|
|
| |
| <div class="ai-control-panel"> |
| <h2>β‘ Manual Command Center</h2> |
| <div class="control-group"> |
| <button class="danger" onclick="simulateFailover('Server2')">β‘ Failover to S2</button> |
| <button class="danger" onclick="simulateFailover('Server3')">β‘ Failover to S3</button> |
| <button class="primary-act" onclick="resetSimulation()">β³ Reset System</button> |
| <button onclick="simulateJobRun('Server1')">Run Job S1</button> |
| <button onclick="simulateJobRun('Server2')">Run Job S2</button> |
| <button onclick="simulateJobRun('Server3')">Run Job S3</button> |
| </div> |
| </div> |
|
|
| |
| <div style="background: #0d1219; border: 1px solid #2a3540; border-radius: 10px; padding: 15px; margin:20px 0;"> |
| <div style="display:flex; justify-content:space-between; align-items:center;"> |
| <div> |
| <h3 style="color:var(--neon-blue); margin-bottom:0;">π Hugging Face Library Explorer</h3> |
| <div style="font-size:0.85rem; color:var(--text-muted);">Access Docs for 200+ AI Model Libraries</div> |
| </div> |
| <button class="primary-act" onclick="toggleExplorer()">π Open Explorer</button> |
| </div> |
| </div> |
| |
| <div id="libraryExplorer" class="explorer-panel"> |
| <input type="text" class="search-box" id="libSearch" placeholder="Search for a library (e.g., 'diffusers', 'transformers')..." onkeyup="filterLibraries()"> |
| <div class="lib-grid" id="libGrid"> |
| |
| </div> |
| </div> |
|
|
| |
| <div class="ai-terminal"> |
| <div class="terminal-header"> |
| <span>π TERMINAL LOG</span> |
| <span>Operator: A.P.PATHUm LAKMAL</span> |
| </div> |
| <div class="terminal-window" id="logFeed"> |
| <div class="log-line log-success">[INIT] System initialized. A.P.PATHUm LAKMAL ready.</div> |
| </div> |
| </div> |
|
|
| |
| <div class="chat-container"> |
| <div class="chat-header"> |
| <span>π§ AI System Bot (Read / Write / Scan / Explore)</span> |
| <span style="font-size: 0.8rem; color: var(--neon-green);">β ONLINE</span> |
| </div> |
| <div class="chat-messages" id="chatMessages"> |
| <div class="msg bot"><div class="bubble">Hello! Click "Open Explorer" above to browse AI libraries, or chat with me to control the servers!</div></div> |
| </div> |
| <div class="typing-indicator" id="typingIndicator">AI is thinking...</div> |
| <div class="chat-input-group"> |
| <input type="text" id="chatInput" placeholder="Type a command..." onkeypress="handleChatEnter(event)"> |
| <button onclick="handleChatSend()">Send β‘</button> |
| </div> |
| </div> |
|
|
| |
| <div class="social-footer"> |
| <h3>CONNECT WITH THE DEVELOPER</h3> |
| <div class="social-links"> |
| <a href="https://www.facebook.com/" target="_blank" class="social-btn">π Facebook</a> |
| <a href="https://github.com/pathum25" target="_blank" class="social-btn">π GitHub</a> |
| <a href="https://huggingface.co/Pq234" target="_blank" class="social-btn">π€ Hugging Face</a> |
| <a href="https://wa.me/94767605853" target="_blank" class="social-btn">π¬ WhatsApp</a> |
| </div> |
| <div class="creator-credit">Created by <strong>A.P.PATHUm LAKMAL</strong> Β© 2026</div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const MODEL_LIBRARIES = [ |
| "acestep", "adapter-transformers", "allennlp", "anemoi", "araclip", |
| "aviation-ner", "asteroid", "audiocraft", "audioseal", "bagel-mot", |
| "bboxmaskpose", "ben2", "bertopic", "big_vision", "bionemo", |
| "birder", "birefnet", "bm25s", "boltzgen", "cancertathomev2", |
| "cartesia_pytorch", "cartesia_mlx", "ccpfn", "champ", "chatterbox", |
| "chaossim", "chat_tts", "chexmix", "chronos-forecasting", "clara", |
| "clipscope", "cloud-agents", "collectorvision", "colipri", "cosyvoice", |
| "cotracker", "colpali", "comet", "cosmos", "cxr-foundation", |
| "deepforest", "depth-anything-v2", "depth-pro", "derm-foundation", |
| "describe-anything", "dia-tts", "dia2", "diff-interpretation-tuning", |
| "diffree", "diffusers", "diffusionkit", "docking-at-home", "doctr", |
| "edsnlp", "elm", "encoderfile", "espnet", "eupe", "fairseq", |
| "fastai", "fastprint", "fasttext", "fixer", "flair", "flextab", |
| "fme", "gemma.cpp", "geometry-crafter", "gliner", "gliner2", |
| "glm-tts", "glyph-byt5", "granite-library", "grok", "habibi-tts", |
| "hallo", "hermes", "holomotion", "hezar", "htrflow", |
| "hunyuan-dit", "hunyuan3d-2", "hunyuanworld-voyager", "hy-worldplay", |
| "hy-world-2", "image-matching-models", "imstoucan", "index-tts", |
| "infinitetalk", "infinite-you", "intellifold", "ising-decoding", |
| "keras", "tf-keras", "keras-hub", "kerasformers", "kernels", |
| "kimi-audio", "kittentts", "kronos", "k2", "lyra-2.0", "lagernvs", |
| "ltx", "lightning-ir", "litert", "litert-lm", "lerobot", "lightglue", |
| "liveportrait", "longcat-video-avatar-1.5", "llama-cpp-python", |
| "mini-omni2", "mindspore", "magi-1", "magenta-realtime", "magenta-realtime-2", |
| "mamba-ssm", "manas-1", "mars5-tts", "matanyone", "mesh-anything", |
| "merlin", "medvae", "mflux", "mitie", "ml-agents", "ml-sharp", |
| "mlx", "mlx-image", "mlc-llm", "model2vec", "mobilint", "moshi", |
| "mtvcraft", "multimolecule", "nemo", "ninfer", "nobg", |
| "nv-medtech", "open-oasis", "open_clip", "openasr", "openpeerllm", |
| "open-sora", "outetts", "paddlenlp", "PaddleOCR", "peft", |
| "perception-encoder", "phantom-wan", "pocket-tts", "pruna-ai", |
| "pxia", "pyannote-audio", "py-feat", "pythae", "quantumpeer", |
| "qwen3_tts", "recurrentgemma", "relik", "refiners", "renderformer", |
| "reverb", "rkllm", "robo-orchard-lab", "rwkv", "saelens", |
| "scail-2", "sam2", "sam-3d-body", "sam-3d-objects", "same", |
| "sample-factory", "sap-rpt-1-oss", "sapiens", "sapiens2", |
| "seedvr", "self-forcing", "sentence-transformers", "setfit", |
| "sklearn", "spacy", "span-marker", "speechbrain", "ssr-speech", |
| "stable-audio-3", "stable-audio-tools", "monkeyocr", "diffusion-single-file", |
| "seed-story", "skala", "soloaudio", "songbloom", "stable-baselines3", |
| "stanza", "supertonic", "swarmformer", "synthefy-migas", "f5-tts", |
| "genmo", "tencent-song-generation", "tensorflowtts", "tensorrt", |
| "tabpfn", "terratorch", "tic-clip", "timesfm", "timee-ts", |
| "timm", "tirex", "tirex-2", "torchgeo", "transformers", |
| "transformers.js", "trellis", "trellis2", "tunejury", "ultralytics", |
| "univa", "uni-3dar", "unity-sentis", "sana", "videoprism", |
| "vfi-mamba", "vismatch", "lvface", "voicecraft", "voxcpm", |
| "vui", "vibevoice", "videox_fun", "wan2.2", "wham", |
| "whisperkit", "yolov10", "yolov26", "zonos", "3dtopia-xl" |
| ]; |
| |
| |
| let state = { |
| servers: { |
| 'Server1': { role: 'Primary', canWrite: true, cssClass: 'status-primary' }, |
| 'Server2': { role: 'Secondary', canWrite: false, cssClass: 'status-secondary' }, |
| 'Server3': { role: 'Secondary', canWrite: false, cssClass: 'status-excluded' } |
| } |
| }; |
| |
| |
| const logFeed = document.getElementById('logFeed'); |
| const uptimeDisplay = document.getElementById('robotUptime'); |
| const chatMessages = document.getElementById('chatMessages'); |
| const chatInput = document.getElementById('chatInput'); |
| const typingIndicator = document.getElementById('typingIndicator'); |
| const libGrid = document.getElementById('libGrid'); |
| const libExplorer = document.getElementById('libraryExplorer'); |
| |
| |
| let seconds = 0; |
| setInterval(() => { |
| seconds++; |
| const hrs = String(Math.floor(seconds / 3600)).padStart(2, '0'); |
| const mins = String(Math.floor((seconds % 3600) / 60)).padStart(2, '0'); |
| const secs = String(seconds % 60).padStart(2, '0'); |
| uptimeDisplay.textContent = `${hrs}:${mins}:${secs}`; |
| document.getElementById('cpuLoad').textContent = Math.floor(Math.random() * 30 + 5) + '%'; |
| }, 1000); |
| |
| |
| function addLog(message, type = 'info') { |
| const entry = document.createElement('div'); |
| entry.className = `log-line log-${type}`; |
| entry.innerHTML = `<span style="color:#555;">[${new Date().toLocaleTimeString()}]</span> ${message}`; |
| logFeed.appendChild(entry); |
| logFeed.scrollTop = logFeed.scrollHeight; |
| } |
| |
| function renderUI() { |
| const grid = document.getElementById('serverGrid'); |
| const primaryDisplay = document.getElementById('currentPrimaryDisplay'); |
| let html = ''; |
| let primaryName = ''; |
| |
| for (const [name, data] of Object.entries(state.servers)) { |
| if (data.role === 'Primary') primaryName = name; |
| let jobBtnHtml = (data.role === 'Primary') |
| ? `<button class="primary-act" style="padding:5px 15px; font-size:0.8rem; margin-top:10px;" onclick="simulateJobRun('${name}')">Run AutoUpsert</button>` |
| : `<button disabled style="padding:5px 15px; font-size:0.8rem; margin-top:10px;">[BLOCKED]</button>`; |
| |
| html += ` |
| <div class="server-card"> |
| <h3>${name}</h3> |
| <div class="status-badge ${data.cssClass}">${data.role}</div> |
| <div class="db-box ha"><strong>agDatabase:</strong> ${data.canWrite ? '<span style="color:var(--neon-green);">WRITABLE</span>' : '<span style="color:#ff3366;">READ-ONLY</span>'}</div> |
| ${jobBtnHtml} |
| </div> |
| `; |
| } |
| grid.innerHTML = html; |
| primaryDisplay.textContent = primaryName; |
| } |
| |
| function simulateFailover(targetServer) { |
| if (state.servers[targetServer].role === 'Primary') { |
| addLog(`[ABORT] Failover to ${targetServer} rejected. Already Active Primary.`, 'error'); |
| return `Failover to ${targetServer} rejected. Already Active Primary.`; |
| } |
| |
| for (const key in state.servers) { |
| state.servers[key].role = 'Secondary'; |
| state.servers[key].canWrite = false; |
| state.servers[key].cssClass = (key === 'Server3') ? 'status-excluded' : 'status-secondary'; |
| } |
| |
| state.servers[targetServer].role = 'Primary'; |
| state.servers[targetServer].canWrite = true; |
| state.servers[targetServer].cssClass = 'status-primary'; |
| |
| addLog(`β οΈ [FAILOVER] ${targetServer} is now ACTIVE PRIMARY.`, 'warn'); |
| renderUI(); |
| return `Successfully failed over to ${targetServer}. It is now the Primary node.`; |
| } |
| |
| function simulateJobRun(serverName) { |
| const server = state.servers[serverName]; |
| addLog(`π Attempting job execution on ${serverName}...`, 'info'); |
| |
| if (server.role === 'Primary') { |
| addLog(`β
[SUCCESS] AutoUpsert executed on ${serverName}.`, 'success'); |
| return `SUCCESS: Job executed on ${serverName} (Primary). Data written to agDatabase.`; |
| } |
| else if (server.role === 'Secondary' && serverName === 'Server2') { |
| addLog(`β οΈ [BLOCKED] Job triggered on ${serverName}. Replica is Secondary.`, 'error'); |
| return `WARNING: Job triggered on ${serverName}, but blocked! Secondary nodes cannot execute write commands.`; |
| } |
| else if (server.role === 'Secondary' && serverName === 'Server3') { |
| addLog(`β [FAILED] ${serverName} is excluded from this AG.`, 'error'); |
| return `ERROR: ${serverName} is excluded. No AutoUpsert job exists here.`; |
| } |
| } |
| |
| function resetSimulation() { |
| state.servers = { |
| 'Server1': { role: 'Primary', canWrite: true, cssClass: 'status-primary' }, |
| 'Server2': { role: 'Secondary', canWrite: false, cssClass: 'status-secondary' }, |
| 'Server3': { role: 'Secondary', canWrite: false, cssClass: 'status-excluded' } |
| }; |
| renderUI(); |
| addLog(`π [RESET] Orchestrator restored to default.`, 'warn'); |
| return "System reset to default. Server1 is Primary."; |
| } |
| |
| |
| function toggleExplorer() { |
| libExplorer.classList.toggle('open'); |
| if(libExplorer.classList.contains('open')) { |
| renderLibraries(MODEL_LIBRARIES); |
| addLog("[EXPLORER] π Library Explorer opened. Ready to browse.", 'info'); |
| } |
| } |
| |
| function renderLibraries(libraries) { |
| libGrid.innerHTML = ''; |
| libraries.forEach(lib => { |
| const div = document.createElement('div'); |
| div.className = 'lib-item'; |
| |
| div.onclick = () => window.open(`https://huggingface.co/docs/hub/${lib}`, '_blank'); |
| div.innerHTML = ` |
| <div class="lib-name">${lib}</div> |
| <div class="lib-desc">Click to open HF Docs</div> |
| `; |
| libGrid.appendChild(div); |
| }); |
| } |
| |
| function filterLibraries() { |
| const searchVal = document.getElementById('libSearch').value.toLowerCase(); |
| const filtered = MODEL_LIBRARIES.filter(lib => lib.toLowerCase().includes(searchVal)); |
| renderLibraries(filtered); |
| } |
| |
| |
| function addChatMessage(text, sender = 'bot') { |
| const msgDiv = document.createElement('div'); |
| msgDiv.className = `msg ${sender}`; |
| msgDiv.innerHTML = `<div class="bubble">${text}</div>`; |
| chatMessages.appendChild(msgDiv); |
| chatMessages.scrollTop = chatMessages.scrollHeight; |
| } |
| |
| async function processAICommand(input) { |
| const lowerInput = input.toLowerCase(); |
| typingIndicator.style.display = 'block'; |
| await new Promise(r => setTimeout(r, 1200)); |
| typingIndicator.style.display = 'none'; |
| |
| let response = ""; |
| |
| if (lowerInput.includes("hello")) { |
| response = "Greetings! I am A.P.PATHUm LAKMAL's AI Orchestrator."; |
| } |
| else if (lowerInput.includes("explorer") || lowerInput.includes("library") || lowerInput.includes("lib")) { |
| response = "π Opening Library Explorer..."; |
| if(!libExplorer.classList.contains('open')) toggleExplorer(); |
| } |
| else if (lowerInput.includes("primary")) { |
| for (const [name, data] of Object.entries(state.servers)) { |
| if(data.role === 'Primary') response = `The current Active Primary node is: ${name}`; |
| } |
| } |
| else if (lowerInput.includes("failover")) { |
| let target = "Server2"; |
| if(lowerInput.includes("server 3")) target = "Server3"; |
| response = simulateFailover(target); |
| } |
| else if (lowerInput.includes("run job")) { |
| let target = "Server1"; |
| if(lowerInput.includes("server 2")) target = "Server2"; |
| else if(lowerInput.includes("server 3")) target = "Server3"; |
| response = simulateJobRun(target); |
| } |
| else if (lowerInput.includes("reset")) { |
| response = resetSimulation(); |
| } |
| else { |
| response = "Command not recognized. Try: 'Open explorer', 'Failover to Server 2', 'Run job on Server 1'."; |
| } |
| |
| addChatMessage(response, 'bot'); |
| } |
| |
| function handleChatSend() { |
| const text = chatInput.value.trim(); |
| if (!text) return; |
| addChatMessage(text, 'user'); |
| chatInput.value = ''; |
| processAICommand(text); |
| } |
| |
| function handleChatEnter(event) { |
| if (event.key === 'Enter') handleChatSend(); |
| } |
| |
| |
| renderUI(); |
| addLog("[READY] AI System Bot and Library Explorer are online!", 'success'); |
| </script> |
| </body> |
| </html> |