Ai25 / Html
Pq234's picture
Create Html
59a6e53 verified
Raw
History Blame Contribute Delete
27.2 kB
<!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;
}
/* --- Header --- */
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 --- */
.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 --- */
.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); }
/* --- Control Panel --- */
.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; }
/* --- Library Explorer --- */
.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; }
/* --- Terminal --- */
.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 Interface --- */
.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;}
/* --- Footer --- */
.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>
<!-- Live Robot Status Panel -->
<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>
<!-- Server Grid -->
<div class="server-grid" id="serverGrid"></div>
<!-- AI Command Center -->
<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>
<!-- AI Library Explorer -->
<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">
<!-- Libraries rendered by JS -->
</div>
</div>
<!-- AI Terminal Log -->
<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>
<!-- AI CHATBOT INTERFACE -->
<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>
<!-- Social Footer -->
<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>
// --- YOUR HUGGING FACE LIBRARY LIST ---
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"
];
// --- ROBOT STATE ---
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' }
}
};
// --- DOM ELEMENTS ---
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');
// --- UPTIME TIMER ---
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);
// --- CORE SYSTEM FUNCTIONS ---
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.";
}
// --- NEW: LIBRARY EXPLORER FUNCTIONS ---
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';
// Direct link to Hugging Face Documentation
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);
}
// --- AI CHATBOT ---
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();
}
// --- INIT ---
renderUI();
addLog("[READY] AI System Bot and Library Explorer are online!", 'success');
</script>
</body>
</html>