Robotics
English
Pq234 commited on
Commit
d4e2fad
·
verified ·
1 Parent(s): 881ee31

Create README.md

Browse files
Files changed (1) hide show
  1. README.md +438 -0
README.md ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: h-research
3
+ datasets:
4
+ - nvidia/PhysicalAI-Robotics-Locomanipulation-GRAIL
5
+ language:
6
+ - en
7
+ metrics:
8
+ - ronaldahmed/nwentfaithfulness
9
+ base_model:
10
+ - deepseek-ai/DeepSeek-V4-Flash-0731
11
+ new_version: openbmb/MiniCPM-RobotManip
12
+ pipeline_tag: robotics
13
+ ---
14
+ <!DOCTYPE html>
15
+ <html lang="en">
16
+ <head>
17
+ <meta charset="UTF-8">
18
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
19
+ <title>🤖 AI-Robotic Orchestrator v3.0</title>
20
+ <style>
21
+ /* --- Cyber/Robotic Theme Variables --- */
22
+ :root {
23
+ --bg-dark: #0a0f14;
24
+ --bg-panel: #141a20;
25
+ --neon-green: #00ffaa;
26
+ --neon-blue: #00d4ff;
27
+ --neon-red: #ff3366;
28
+ --text-main: #e0e6ed;
29
+ --text-muted: #7a8b9e;
30
+ --border-glow: rgba(0, 255, 170, 0.2);
31
+ }
32
+
33
+ * { box-sizing: border-box; margin: 0; padding: 0; }
34
+
35
+ body {
36
+ font-family: 'Segoe UI', 'Courier New', monospace, sans-serif;
37
+ background-color: var(--bg-dark);
38
+ color: var(--text-main);
39
+ padding: 20px;
40
+ display: flex;
41
+ justify-content: center;
42
+ min-height: 100vh;
43
+ background-image:
44
+ linear-gradient(rgba(0, 255, 170, 0.03) 1px, transparent 1px),
45
+ linear-gradient(90deg, rgba(0, 255, 170, 0.03) 1px, transparent 1px);
46
+ background-size: 40px 40px;
47
+ }
48
+
49
+ .container {
50
+ max-width: 1100px;
51
+ width: 100%;
52
+ background: var(--bg-panel);
53
+ border: 1px solid var(--border-glow);
54
+ border-radius: 16px;
55
+ padding: 30px;
56
+ box-shadow: 0 0 30px rgba(0, 255, 170, 0.05);
57
+ position: relative;
58
+ }
59
+
60
+ /* --- Header --- */
61
+ 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; }
62
+ .subtitle { text-align: center; color: var(--text-muted); margin-bottom: 25px; border-bottom: 1px solid #2a3540; padding-bottom: 15px; }
63
+
64
+ /* --- Robot Status Panel --- */
65
+ .robot-status-panel {
66
+ display: flex; justify-content: space-between; background: #0d1219;
67
+ border: 1px solid #2a3540; border-radius: 8px; padding: 15px 20px;
68
+ margin-bottom: 25px; flex-wrap: wrap; gap: 10px;
69
+ }
70
+ .stat-item { display: flex; flex-direction: column; }
71
+ .stat-label { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px;}
72
+ .stat-value { font-weight: bold; font-size: 1.1rem; font-family: 'Courier New', monospace; }
73
+ .blink { animation: blinker 1.5s linear infinite; }
74
+ @keyframes blinker { 50% { opacity: 0.3; } }
75
+
76
+ /* --- Server Grid --- */
77
+ .server-grid { display: flex; justify-content: space-between; gap: 15px; flex-wrap: wrap; margin-bottom: 25px; }
78
+ .server-card {
79
+ flex: 1; min-width: 180px; background: #11181f; border: 1px solid #2a3540;
80
+ border-radius: 10px; padding: 20px 15px; text-align: center; transition: 0.3s;
81
+ }
82
+ .server-card h3 { margin: 0 0 15px 0; color: var(--neon-blue); }
83
+
84
+ .status-badge {
85
+ display: inline-block; padding: 6px 16px; border-radius: 20px; font-size: 0.8rem;
86
+ font-weight: bold; text-transform: uppercase; background: #2a3540; color: var(--text-muted);
87
+ }
88
+ .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); }
89
+ .status-secondary { background: rgba(0, 212, 255, 0.1); color: var(--neon-blue); border: 1px solid var(--neon-blue); }
90
+ .status-excluded { background: rgba(255, 51, 102, 0.1); color: var(--neon-red); border: 1px solid var(--neon-red); }
91
+
92
+ .db-box { margin-top: 12px; font-size: 0.8rem; background: #0d1219; padding: 6px; border-radius: 4px; border-left: 2px solid #2a3540; }
93
+ .db-box.ha { border-left-color: var(--neon-green); }
94
+
95
+ /* --- Control Panel --- */
96
+ .ai-control-panel { background: rgba(0, 0, 0, 0.4); border: 1px solid #2a3540; border-radius: 10px; padding: 20px; margin-bottom: 25px; }
97
+ .ai-control-panel h2 { margin-top: 0; color: var(--neon-blue); font-size: 1.1rem; border-bottom: 1px solid #2a3540; padding-bottom: 10px; }
98
+ .control-group { display: flex; gap: 10px; flex-wrap: wrap; margin: 15px 0; }
99
+
100
+ button {
101
+ background: transparent; color: var(--text-main); border: 1px solid #2a3540;
102
+ padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: 600; transition: 0.2s;
103
+ }
104
+ button:hover { background: #2a3540; }
105
+ button.primary-act { border-color: var(--neon-green); color: var(--neon-green); }
106
+ button.primary-act:hover { box-shadow: 0 0 15px rgba(0,255,170,0.2); background: rgba(0,255,170,0.1); }
107
+ button.danger { border-color: var(--neon-red); color: var(--neon-red); }
108
+ button.danger:hover { background: rgba(255,51,102,0.1); box-shadow: 0 0 15px rgba(255,51,102,0.2); }
109
+ button:disabled { opacity: 0.5; cursor: not-allowed; }
110
+
111
+ /* --- Terminal --- */
112
+ .ai-terminal { background: #0a0b0d; border: 1px solid #2a3540; border-radius: 8px; padding: 5px; margin-bottom: 20px; }
113
+ .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; }
114
+ .terminal-window { padding: 15px; height: 120px; overflow-y: auto; font-family: 'Courier New', monospace; font-size: 0.9rem; color: #bbb; }
115
+ .terminal-window::-webkit-scrollbar { width: 5px; }
116
+ .terminal-window::-webkit-scrollbar-track { background: #0a0b0d; }
117
+ .terminal-window::-webkit-scrollbar-thumb { background: #2a3540; border-radius: 10px; }
118
+ .log-line { margin-bottom: 3px; }
119
+ .log-error { color: var(--neon-red); }
120
+ .log-success { color: var(--neon-green); }
121
+ .log-info { color: var(--neon-blue); }
122
+ .log-warn { color: #ffaa00; }
123
+
124
+ /* --- NEW: CHAT INTERFACE --- */
125
+ .chat-container {
126
+ margin-top: 10px;
127
+ background: #0d1219;
128
+ border: 1px solid var(--neon-blue);
129
+ border-radius: 10px;
130
+ padding: 15px;
131
+ box-shadow: 0 0 20px rgba(0, 212, 255, 0.1);
132
+ }
133
+ .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; }
134
+ .chat-messages { height: 150px; overflow-y: auto; margin-bottom: 15px; padding-right: 5px;}
135
+ .chat-messages::-webkit-scrollbar { width: 5px; }
136
+ .chat-messages::-webkit-scrollbar-track { background: #0d1219; }
137
+ .chat-messages::-webkit-scrollbar-thumb { background: var(--neon-blue); border-radius: 10px; }
138
+
139
+ .msg { display: flex; margin-bottom: 10px; }
140
+ .msg.user { justify-content: flex-end; }
141
+ .msg.bot { justify-content: flex-start; }
142
+ .bubble { max-width: 80%; padding: 8px 15px; border-radius: 15px; font-size: 0.9rem; }
143
+ .user .bubble { background: #005c99; color: white; border-bottom-right-radius: 2px; }
144
+ .bot .bubble { background: #2a3540; color: #e0e6ed; border-bottom-left-radius: 2px; }
145
+ .typing-indicator { color: var(--neon-blue); font-size: 0.8rem; font-style: italic; margin-left: 10px; display: none; }
146
+
147
+ .chat-input-group { display: flex; gap: 10px; }
148
+ .chat-input-group input { flex: 1; background: #141a20; border: 1px solid #2a3540; color: white; padding: 10px; border-radius: 6px; outline: none; }
149
+ .chat-input-group input:focus { border-color: var(--neon-blue); }
150
+ .chat-input-group button { border-color: var(--neon-blue); color: var(--neon-blue); padding: 10px 20px; border-radius: 6px;}
151
+
152
+ /* --- Footer --- */
153
+ .social-footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #2a3540; text-align: center; }
154
+ .social-links { display: flex; justify-content: center; gap: 15px; flex-wrap: wrap; margin-top: 10px; }
155
+ .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; }
156
+ .social-btn:hover { background: #2a3540; border-color: var(--neon-blue); color: white; }
157
+ .creator-credit { margin-top: 20px; font-size: 0.9rem; color: #555; border-top: 1px solid #1a232c; padding-top: 15px; }
158
+ .creator-credit strong { color: var(--neon-blue); }
159
+ </style>
160
+ </head>
161
+ <body>
162
+
163
+ <div class="container">
164
+ <h1>🤖 AI-Robotic Orchestrator v3.0</h1>
165
+ <div class="subtitle">AG1-Sample :: Autonomous Scheduler Unit :: Read, Write, Scan, Execute</div>
166
+
167
+ <!-- Live Robot Status Panel -->
168
+ <div class="robot-status-panel">
169
+ <div class="stat-item"><span class="stat-label">System Status</span><span class="stat-value blink" style="color: var(--neon-green);">● ACTIVE</span></div>
170
+ <div class="stat-item"><span class="stat-label">Uptime</span><span class="stat-value" id="robotUptime">00:00:00</span></div>
171
+ <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>
172
+ <div class="stat-item"><span class="stat-label">CPU Load</span><span class="stat-value" id="cpuLoad">12%</span></div>
173
+ </div>
174
+
175
+ <!-- Server Grid -->
176
+ <div class="server-grid" id="serverGrid"></div>
177
+
178
+ <!-- AI Command Center -->
179
+ <div class="ai-control-panel">
180
+ <h2>⚡ Manual Command Center</h2>
181
+ <div style="background: #0d1219; padding: 8px 15px; border-radius: 4px; margin-bottom: 15px; border-left: 3px solid #ffaa00;">
182
+ <strong style="color:#ffaa00;">⚙️ Active Policy:</strong> <span id="customRuleDisplay" style="color: var(--text-main);">Only Primary nodes can write to agDatabase.</span>
183
+ </div>
184
+ <div class="control-group">
185
+ <button class="danger" onclick="simulateFailover('Server2')">⚡ Failover to S2</button>
186
+ <button class="danger" onclick="simulateFailover('Server3')">⚡ Failover to S3</button>
187
+ <button class="primary-act" onclick="resetSimulation()">⟳ Reset System</button>
188
+ <button onclick="simulateJobRun('Server1')">Run Job S1</button>
189
+ <button onclick="simulateJobRun('Server2')">Run Job S2</button>
190
+ <button onclick="simulateJobRun('Server3')">Run Job S3</button>
191
+ </div>
192
+ </div>
193
+
194
+ <!-- AI Terminal Log -->
195
+ <div class="ai-terminal">
196
+ <div class="terminal-header">
197
+ <span>📟 TERMINAL LOG</span>
198
+ <span>Operator: A.P.PATHUm LAKMAL</span>
199
+ </div>
200
+ <div class="terminal-window" id="logFeed">
201
+ <div class="log-line log-success">[INIT] System initialized. A.P.PATHUm LAKMAL ready.</div>
202
+ </div>
203
+ </div>
204
+
205
+ <!-- NEW: AI CHATBOT INTERFACE -->
206
+ <div class="chat-container">
207
+ <div class="chat-header">
208
+ <span>🧠 AI System Bot (Read / Write / Scan / Execute)</span>
209
+ <span style="font-size: 0.8rem; color: var(--neon-green);">● ONLINE</span>
210
+ </div>
211
+ <div class="chat-messages" id="chatMessages">
212
+ <div class="msg bot"><div class="bubble">Hello! I am your AI Orchestrator. You can ask me to check server status, run jobs, or failover nodes! Try: "Scan Server 2"</div></div>
213
+ </div>
214
+ <div class="typing-indicator" id="typingIndicator">AI is thinking...</div>
215
+ <div class="chat-input-group">
216
+ <input type="text" id="chatInput" placeholder="Type a command... (e.g., 'Failover to Server 3')" onkeypress="handleChatEnter(event)">
217
+ <button onclick="handleChatSend()">Send ⚡</button>
218
+ </div>
219
+ </div>
220
+
221
+ <!-- Social Footer -->
222
+ <div class="social-footer">
223
+ <h3>CONNECT WITH THE DEVELOPER</h3>
224
+ <div class="social-links">
225
+ <a href="https://www.facebook.com/" target="_blank" class="social-btn">📘 Facebook</a>
226
+ <a href="https://github.com/pathum25" target="_blank" class="social-btn">🐙 GitHub</a>
227
+ <a href="https://huggingface.co/Pq234" target="_blank" class="social-btn">🤗 Hugging Face</a>
228
+ <a href="https://wa.me/94767605853" target="_blank" class="social-btn">💬 WhatsApp</a>
229
+ </div>
230
+ <div class="creator-credit">Created by <strong>A.P.PATHUm LAKMAL</strong> © 2026</div>
231
+ </div>
232
+ </div>
233
+
234
+ <script>
235
+ // --- ROBOT STATE ---
236
+ let state = {
237
+ servers: {
238
+ 'Server1': { role: 'Primary', canWrite: true, cssClass: 'status-primary' },
239
+ 'Server2': { role: 'Secondary', canWrite: false, cssClass: 'status-secondary' },
240
+ 'Server3': { role: 'Secondary', canWrite: false, cssClass: 'status-excluded' }
241
+ }
242
+ };
243
+
244
+ // --- DOM ELEMENTS ---
245
+ const logFeed = document.getElementById('logFeed');
246
+ const uptimeDisplay = document.getElementById('robotUptime');
247
+ const chatMessages = document.getElementById('chatMessages');
248
+ const chatInput = document.getElementById('chatInput');
249
+ const typingIndicator = document.getElementById('typingIndicator');
250
+
251
+ // --- UPTIME TIMER ---
252
+ let seconds = 0;
253
+ setInterval(() => {
254
+ seconds++;
255
+ const hrs = String(Math.floor(seconds / 3600)).padStart(2, '0');
256
+ const mins = String(Math.floor((seconds % 3600) / 60)).padStart(2, '0');
257
+ const secs = String(seconds % 60).padStart(2, '0');
258
+ uptimeDisplay.textContent = `${hrs}:${mins}:${secs}`;
259
+ document.getElementById('cpuLoad').textContent = Math.floor(Math.random() * 30 + 5) + '%';
260
+ }, 1000);
261
+
262
+ // --- CORE FUNCTIONS ---
263
+ function addLog(message, type = 'info') {
264
+ const entry = document.createElement('div');
265
+ entry.className = `log-line log-${type}`;
266
+ entry.innerHTML = `<span style="color:#555;">[${new Date().toLocaleTimeString()}]</span> ${message}`;
267
+ logFeed.appendChild(entry);
268
+ logFeed.scrollTop = logFeed.scrollHeight;
269
+ }
270
+
271
+ function renderUI() {
272
+ const grid = document.getElementById('serverGrid');
273
+ const primaryDisplay = document.getElementById('currentPrimaryDisplay');
274
+ let html = '';
275
+ let primaryName = '';
276
+
277
+ for (const [name, data] of Object.entries(state.servers)) {
278
+ if (data.role === 'Primary') primaryName = name;
279
+
280
+ let jobBtnHtml = (data.role === 'Primary')
281
+ ? `<button class="primary-act" style="padding:5px 15px; font-size:0.8rem; margin-top:10px;" onclick="simulateJobRun('${name}')">Run AutoUpsert</button>`
282
+ : `<button disabled style="padding:5px 15px; font-size:0.8rem; margin-top:10px;">[BLOCKED]</button>`;
283
+
284
+ html += `
285
+ <div class="server-card">
286
+ <h3>${name}</h3>
287
+ <div class="status-badge ${data.cssClass}">${data.role}</div>
288
+ <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>
289
+ ${jobBtnHtml}
290
+ </div>
291
+ `;
292
+ }
293
+ grid.innerHTML = html;
294
+ primaryDisplay.textContent = primaryName;
295
+ }
296
+
297
+ function simulateFailover(targetServer) {
298
+ if (state.servers[targetServer].role === 'Primary') {
299
+ addLog(`[ABORT] Failover to ${targetServer} rejected. Already Active Primary.`, 'error');
300
+ return;
301
+ }
302
+
303
+ for (const key in state.servers) {
304
+ state.servers[key].role = 'Secondary';
305
+ state.servers[key].canWrite = false;
306
+ state.servers[key].cssClass = (key === 'Server3') ? 'status-excluded' : 'status-secondary';
307
+ }
308
+
309
+ state.servers[targetServer].role = 'Primary';
310
+ state.servers[targetServer].canWrite = true;
311
+ state.servers[targetServer].cssClass = 'status-primary';
312
+
313
+ addLog(`⚠️ [FAILOVER] ${targetServer} is now ACTIVE PRIMARY.`, 'warn');
314
+ renderUI();
315
+ return `Successfully failed over to ${targetServer}. It is now the Primary node.`;
316
+ }
317
+
318
+ function simulateJobRun(serverName) {
319
+ const server = state.servers[serverName];
320
+ addLog(`📝 Attempting job execution on ${serverName}...`, 'info');
321
+
322
+ if (server.role === 'Primary') {
323
+ addLog(`✅ [SUCCESS] AutoUpsert executed on ${serverName}.`, 'success');
324
+ return `SUCCESS: Job executed on ${serverName} (Primary). Data written to agDatabase.`;
325
+ }
326
+ else if (server.role === 'Secondary' && serverName === 'Server2') {
327
+ addLog(`⚠️ [BLOCKED] Job triggered on ${serverName}. Replica is Secondary.`, 'error');
328
+ return `WARNING: Job triggered on ${serverName}, but blocked! Secondary nodes cannot execute write commands.`;
329
+ }
330
+ else if (server.role === 'Secondary' && serverName === 'Server3') {
331
+ addLog(`⛔ [FAILED] ${serverName} is excluded from this AG.`, 'error');
332
+ return `ERROR: ${serverName} is excluded. No AutoUpsert job exists here.`;
333
+ }
334
+ }
335
+
336
+ function resetSimulation() {
337
+ state.servers = {
338
+ 'Server1': { role: 'Primary', canWrite: true, cssClass: 'status-primary' },
339
+ 'Server2': { role: 'Secondary', canWrite: false, cssClass: 'status-secondary' },
340
+ 'Server3': { role: 'Secondary', canWrite: false, cssClass: 'status-excluded' }
341
+ };
342
+ renderUI();
343
+ addLog(`🔄 [RESET] Orchestrator restored to default.`, 'warn');
344
+ return "System reset to default. Server1 is Primary.";
345
+ }
346
+
347
+ // --- AI CHATBOT LOGIC (Read, Write, Scan, Execute) ---
348
+ function addChatMessage(text, sender = 'bot') {
349
+ const msgDiv = document.createElement('div');
350
+ msgDiv.className = `msg ${sender}`;
351
+ msgDiv.innerHTML = `<div class="bubble">${text}</div>`;
352
+ chatMessages.appendChild(msgDiv);
353
+ chatMessages.scrollTop = chatMessages.scrollHeight;
354
+ }
355
+
356
+ async function processAICommand(input) {
357
+ const lowerInput = input.toLowerCase();
358
+ typingIndicator.style.display = 'block';
359
+
360
+ // Simulate AI Processing Delay
361
+ await new Promise(r => setTimeout(r, 1500));
362
+ typingIndicator.style.display = 'none';
363
+
364
+ let response = "";
365
+
366
+ // --- AI Logic Interpreters ---
367
+ if (lowerInput.includes("hello") || lowerInput.includes("hi") || lowerInput.includes("hey")) {
368
+ response = "Greetings! I am A.P.PATHUm LAKMAL's AI Orchestrator. Type 'help' to see what I can do.";
369
+ }
370
+ else if (lowerInput.includes("help")) {
371
+ response = "I can read, write, scan, and execute! Try: \n- 'Scan Server 2'\n- 'What is the primary server?'\n- 'Run job on Server 1'\n- 'Failover to Server 3'";
372
+ }
373
+ else if (lowerInput.includes("scan") || lowerInput.includes("status")) {
374
+ let target = "all";
375
+ if(lowerInput.includes("server 1")) target = "Server1";
376
+ else if(lowerInput.includes("server 2")) target = "Server2";
377
+ else if(lowerInput.includes("server 3")) target = "Server3";
378
+
379
+ if(target === "all") {
380
+ let s1 = state.servers['Server1'];
381
+ let s2 = state.servers['Server2'];
382
+ let s3 = state.servers['Server3'];
383
+ response = `System Scan Complete:\n[Server1] Role: ${s1.role}, Write Access: ${s1.canWrite ? 'Yes' : 'No'}\n[Server2] Role: ${s2.role}, Write Access: ${s2.canWrite ? 'Yes' : 'No'}\n[Server3] Role: ${s3.role}, Write Access: ${s3.canWrite ? 'Yes' : 'No'} (Excluded)`;
384
+ } else {
385
+ let data = state.servers[target];
386
+ response = `Scanning ${target}...\nRole: ${data.role}\nWriteable: ${data.canWrite ? 'Yes' : 'No'}`;
387
+ }
388
+ }
389
+ else if (lowerInput.includes("primary") || lowerInput.includes("active node")) {
390
+ for (const [name, data] of Object.entries(state.servers)) {
391
+ if(data.role === 'Primary') response = `The current Active Primary node is: ${name}`;
392
+ }
393
+ }
394
+ else if (lowerInput.includes("failover") || lowerInput.includes("switch")) {
395
+ let target = "Server2";
396
+ if(lowerInput.includes("server 3")) target = "Server3";
397
+ else if(lowerInput.includes("server 2")) target = "Server2";
398
+
399
+ response = simulateFailover(target);
400
+ }
401
+ else if (lowerInput.includes("run job") || lowerInput.includes("execute job")) {
402
+ let target = "Server1";
403
+ if(lowerInput.includes("server 2")) target = "Server2";
404
+ else if(lowerInput.includes("server 3")) target = "Server3";
405
+ else if(lowerInput.includes("s1")) target = "Server1";
406
+ else if(lowerInput.includes("s2")) target = "Server2";
407
+ else if(lowerInput.includes("s3")) target = "Server3";
408
+
409
+ response = simulateJobRun(target);
410
+ }
411
+ else if (lowerInput.includes("reset") || lowerInput.includes("restart")) {
412
+ response = resetSimulation();
413
+ }
414
+ else {
415
+ response = "Command not recognized. Try: 'Scan Server 2', 'What is primary?', 'Run job on Server 1', 'Failover to Server 3', or 'Reset'.";
416
+ }
417
+
418
+ addChatMessage(response, 'bot');
419
+ }
420
+
421
+ function handleChatSend() {
422
+ const text = chatInput.value.trim();
423
+ if (!text) return;
424
+ addChatMessage(text, 'user');
425
+ chatInput.value = '';
426
+ processAICommand(text);
427
+ }
428
+
429
+ function handleChatEnter(event) {
430
+ if (event.key === 'Enter') handleChatSend();
431
+ }
432
+
433
+ // --- INIT ---
434
+ renderUI();
435
+ addLog("[READY] AI System Bot is online. Type commands in the chat!", 'success');
436
+ </script>
437
+ </body>
438
+ </html>