Spaces:
Running
Running
| } | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Advanced Agent System - Task Processing & Database Integration</title> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| color: #333; | |
| } | |
| .container { | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| } | |
| .header { | |
| text-align: center; | |
| margin-bottom: 30px; | |
| color: white; | |
| } | |
| .header h1 { | |
| font-size: 2.5rem; | |
| margin-bottom: 10px; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.3); | |
| } | |
| .system-status { | |
| background: rgba(255,255,255,0.95); | |
| border-radius: 15px; | |
| padding: 20px; | |
| margin-bottom: 20px; | |
| box-shadow: 0 8px 32px rgba(0,0,0,0.1); | |
| backdrop-filter: blur(10px); | |
| } | |
| .status-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
| gap: 15px; | |
| margin-bottom: 20px; | |
| } | |
| .status-card { | |
| background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); | |
| color: white; | |
| padding: 15px; | |
| border-radius: 10px; | |
| text-align: center; | |
| } | |
| .status-card h3 { | |
| font-size: 1.1rem; | |
| margin-bottom: 5px; | |
| } | |
| .status-card .value { | |
| font-size: 1.5rem; | |
| font-weight: bold; | |
| } | |
| .main-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| margin-bottom: 20px; | |
| } | |
| .panel { | |
| background: rgba(255,255,255,0.95); | |
| border-radius: 15px; | |
| padding: 20px; | |
| box-shadow: 0 8px 32px rgba(0,0,0,0.1); | |
| backdrop-filter: blur(10px); | |
| } | |
| .panel h2 { | |
| color: #4a5568; | |
| margin-bottom: 15px; | |
| font-size: 1.3rem; | |
| border-bottom: 2px solid #e2e8f0; | |
| padding-bottom: 8px; | |
| } | |
| .task-form { | |
| display: grid; | |
| gap: 15px; | |
| } | |
| .form-group { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .form-group label { | |
| font-weight: 600; | |
| margin-bottom: 5px; | |
| color: #4a5568; | |
| } | |
| .form-group input, | |
| .form-group select, | |
| .form-group textarea { | |
| padding: 10px; | |
| border: 2px solid #e2e8f0; | |
| border-radius: 8px; | |
| font-size: 14px; | |
| transition: border-color 0.3s; | |
| } | |
| .form-group input:focus, | |
| .form-group select:focus, | |
| .form-group textarea:focus { | |
| outline: none; | |
| border-color: #4299e1; | |
| } | |
| .btn { | |
| padding: 12px 24px; | |
| border: none; | |
| border-radius: 8px; | |
| font-size: 14px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| } | |
| .btn-success { | |
| background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%); | |
| color: #2d5a27; | |
| } | |
| .btn-danger { | |
| background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%); | |
| color: #c53030; | |
| } | |
| .btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 15px rgba(0,0,0,0.2); | |
| } | |
| .task-list { | |
| max-height: 400px; | |
| overflow-y: auto; | |
| } | |
| .task-item { | |
| background: #f7fafc; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 8px; | |
| padding: 15px; | |
| margin-bottom: 10px; | |
| transition: all 0.3s; | |
| } | |
| .task-item:hover { | |
| background: #edf2f7; | |
| transform: translateX(5px); | |
| } | |
| .task-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 8px; | |
| } | |
| .task-id { | |
| font-weight: 600; | |
| color: #2d3748; | |
| } | |
| .task-status { | |
| padding: 4px 8px; | |
| border-radius: 4px; | |
| font-size: 12px; | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| } | |
| .status-queued { background: #fef5e7; color: #c05621; } | |
| .status-processing { background: #e6fffa; color: #234e52; } | |
| .status-completed { background: #f0fff4; color: #22543d; } | |
| .status-failed { background: #fed7d7; color: #c53030; } | |
| .agents-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | |
| gap: 15px; | |
| } | |
| .agent-card { | |
| background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%); | |
| border-radius: 10px; | |
| padding: 15px; | |
| text-align: center; | |
| transition: transform 0.3s; | |
| } | |
| .agent-card:hover { | |
| transform: scale(1.05); | |
| } | |
| .agent-name { | |
| font-weight: 600; | |
| margin-bottom: 5px; | |
| color: #2d3748; | |
| } | |
| .agent-status { | |
| font-size: 12px; | |
| padding: 4px 8px; | |
| border-radius: 4px; | |
| display: inline-block; | |
| margin-bottom: 10px; | |
| } | |
| .status-active { background: #c6f6d5; color: #22543d; } | |
| .status-idle { background: #fed7e2; color: #97266d; } | |
| .logs-container { | |
| background: #1a202c; | |
| color: #e2e8f0; | |
| border-radius: 8px; | |
| padding: 15px; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| font-family: 'Courier New', monospace; | |
| font-size: 12px; | |
| line-height: 1.4; | |
| } | |
| .log-entry { | |
| margin-bottom: 5px; | |
| padding: 2px 0; | |
| } | |
| .log-timestamp { | |
| color: #718096; | |
| margin-right: 10px; | |
| } | |
| .log-level-info { color: #63b3ed; } | |
| .log-level-success { color: #68d391; } | |
| .log-level-warning { color: #f6ad55; } | |
| .log-level-error { color: #fc8181; } | |
| .database-panel { | |
| grid-column: 1 / -1; | |
| margin-top: 20px; | |
| } | |
| .db-actions { | |
| display: flex; | |
| gap: 10px; | |
| margin-bottom: 15px; | |
| flex-wrap: wrap; | |
| } | |
| .connection-status { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 15px; | |
| } | |
| .status-indicator { | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| background: #68d391; | |
| animation: pulse 2s infinite; | |
| } | |
| .status-disconnected { | |
| background: #fc8181; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 1; } | |
| } | |
| .data-table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| margin-top: 15px; | |
| } | |
| .data-table th, | |
| .data-table td { | |
| border: 1px solid #e2e8f0; | |
| padding: 8px 12px; | |
| text-align: left; | |
| } | |
| .data-table th { | |
| background: #f7fafc; | |
| font-weight: 600; | |
| color: #4a5568; | |
| } | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: rgba(0,0,0,0.5); | |
| z-index: 1000; | |
| } | |
| .modal-content { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| background: white; | |
| border-radius: 15px; | |
| padding: 30px; | |
| max-width: 600px; | |
| width: 90%; | |
| max-height: 80vh; | |
| overflow-y: auto; | |
| } | |
| .modal-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| border-bottom: 2px solid #e2e8f0; | |
| padding-bottom: 10px; | |
| } | |
| .close-btn { | |
| background: none; | |
| border: none; | |
| font-size: 24px; | |
| cursor: pointer; | |
| color: #a0aec0; | |
| } | |
| .close-btn:hover { | |
| color: #4a5568; | |
| } | |
| @media (max-width: 768px) { | |
| .main-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .status-grid { | |
| grid-template-columns: repeat(2, 1fr); | |
| } | |
| .header h1 { | |
| font-size: 2rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <h1>🤖 Advanced Agent System</h1> | |
| <p>Task Processing Engine with Database Integration</p> | |
| </div> | |
| <!-- System Status --> | |
| <div class="system-status"> | |
| <div class="status-grid"> | |
| <div class="status-card"> | |
| <h3>Active Agents</h3> | |
| <div class="value" id="active-agents">0</div> | |
| </div> | |
| <div class="status-card"> | |
| <h3>Tasks Queued</h3> | |
| <div class="value" id="queued-tasks">0</div> | |
| </div> | |
| <div class="status-card"> | |
| <h3>Processing</h3> | |
| <div class="value" id="processing-tasks">0</div> | |
| </div> | |
| <div class="status-card"> | |
| <h3>Completed</h3> | |
| <div class="value" id="completed-tasks">0</div> | |
| </div> | |
| <div class="status-card"> | |
| <h3>DB Records</h3> | |
| <div class="value" id="db-records">0</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main Grid --> | |
| <div class="main-grid"> | |
| <!-- Task Creation Panel --> | |
| <div class="panel"> | |
| <h2>📝 Create Task</h2> | |
| <form class="task-form" id="task-form"> | |
| <div class="form-group"> | |
| <label for="task-type">Task Type</label> | |
| <select id="task-type"> | |
| <option value="single">Single Task</option> | |
| <option value="workflow">Workflow</option> | |
| <option value="batch">Batch Processing</option> | |
| <option value="scheduled">Scheduled Task</option> | |
| <option value="monitoring">Monitoring</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label for="task-description">Description</label> | |
| <textarea id="task-description" rows="3" placeholder="Describe what this task should do..."></textarea> | |
| </div> | |
| <div class="form-group"> | |
| <label for="task-priority">Priority</label> | |
| <select id="task-priority"> | |
| <option value="low">Low</option> | |
| <option value="normal" selected>Normal</option> | |
| <option value="high">High</option> | |
| <option value="urgent">Urgent</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label for="task-agent">Assign to Agent</label> | |
| <select id="task-agent"> | |
| <option value="">Auto-assign</option> | |
| </select> | |
| </div> | |
| <button type="submit" class="btn btn-primary">Create Task</button> | |
| </form> | |
| </div> | |
| <!-- Active Agents Panel --> | |
| <div class="panel"> | |
| <h2>🤖 Active Agents</h2> | |
| <div class="agents-grid" id="agents-container"> | |
| <!-- Agents will be populated here --> | |
| </div> | |
| <button class="btn btn-success" onclick="createAgent()">+ Add Agent</button> | |
| </div> | |
| </div> | |
| <!-- Task Queue Panel --> | |
| <div class="panel"> | |
| <h2>📋 Task Queue & Processing</h2> | |
| <div class="task-list" id="task-list"> | |
| <!-- Tasks will be populated here --> | |
| </div> | |
| </div> | |
| <!-- Database Integration Panel --> | |
| <div class="panel database-panel"> | |
| <h2>🗄️ Database Integration</h2> | |
| <div class="connection-status"> | |
| <div class="status-indicator" id="db-status"></div> | |
| <span id="db-status-text">Connected to Local Storage</span> | |
| </div> | |
| <div class="db-actions"> | |
| <button class="btn btn-primary" onclick="initializeDatabase()">Initialize DB</button> | |
| <button class="btn btn-success" onclick="exportData()">Export Data</button> | |
| <button class="btn btn-danger" onclick="clearDatabase()">Clear Database</button> | |
| <button class="btn btn-primary" onclick="showQueryInterface()">Query Interface</button> | |
| </div> | |
| <div id="db-content"> | |
| <table class="data-table" id="data-table"> | |
| <thead> | |
| <tr> | |
| <th>ID</th> | |
| <th>Type</th> | |
| <th>Status</th> | |
| <th>Created</th> | |
| <th>Updated</th> | |
| <th>Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody id="data-table-body"> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <!-- System Logs --> | |
| <div class="panel"> | |
| <h2>📊 System Logs</h2> | |
| <div class="logs-container" id="logs-container"> | |
| <!-- Logs will be populated here --> | |
| </div> | |
| <button class="btn btn-danger" onclick="clearLogs()">Clear Logs</button> | |
| </div> | |
| </div> | |
| <!-- Modal for Query Interface --> | |
| <div class="modal" id="query-modal"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h2>Database Query Interface</h2> | |
| <button class="close-btn" onclick="closeModal()">×</button> | |
| </div> | |
| <div class="form-group"> | |
| <label for="query-input">SQL-like Query</label> | |
| <textarea id="query-input" rows="4" placeholder="SELECT * FROM tasks WHERE status = 'completed'"></textarea> | |
| </div> | |
| <button class="btn btn-primary" onclick="executeQuery()">Execute Query</button> | |
| <div id="query-results"></div> | |
| </div> | |
| </div> | |
| <script> | |
| // Database Manager Class | |
| // Complete DatabaseManager Class for the Agent System | |
| // Add this class BEFORE the TaskProcessingEngine class in your HTML file | |
| class DatabaseManager { | |
| constructor() { | |
| this.connected = false; | |
| this.tables = { | |
| tasks: 'agent_tasks', | |
| agents: 'agent_agents', | |
| logs: 'agent_logs', | |
| metrics: 'agent_metrics', | |
| workflows: 'agent_workflows', | |
| schedules: 'agent_schedules' | |
| }; | |
| this.init(); | |
| } | |
| init() { | |
| try { | |
| // Check if localStorage is available | |
| if (typeof Storage !== "undefined") { | |
| this.connected = true; | |
| this.initializeTables(); | |
| console.log('✅ Database Manager initialized with localStorage'); | |
| } else { | |
| console.error('❌ localStorage not supported'); | |
| this.connected = false; | |
| } | |
| } catch (error) { | |
| console.error('❌ Database initialization failed:', error); | |
| this.connected = false; | |
| } | |
| } | |
| initializeTables() { | |
| // Initialize empty arrays for each table if they don't exist | |
| Object.values(this.tables).forEach(tableName => { | |
| if (!localStorage.getItem(tableName)) { | |
| localStorage.setItem(tableName, JSON.stringify([])); | |
| } | |
| }); | |
| } | |
| generateId() { | |
| // Generate unique ID using timestamp and random number | |
| return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; | |
| } | |
| // CREATE operations | |
| async insert(tableName, data) { | |
| try { | |
| const records = this.getAll(tableName); | |
| const newRecord = { | |
| ...data, | |
| id: data.id || this.generateId(), | |
| created_at: data.created_at || new Date().toISOString(), | |
| updated_at: new Date().toISOString() | |
| }; | |
| records.push(newRecord); | |
| localStorage.setItem(tableName, JSON.stringify(records)); | |
| return newRecord; | |
| } catch (error) { | |
| console.error(`Insert failed for table ${tableName}:`, error); | |
| throw error; | |
| } | |
| } | |
| async insertMany(tableName, dataArray) { | |
| try { | |
| const records = this.getAll(tableName); | |
| const newRecords = dataArray.map(data => ({ | |
| ...data, | |
| id: data.id || this.generateId(), | |
| created_at: data.created_at || new Date().toISOString(), | |
| updated_at: new Date().toISOString() | |
| })); | |
| records.push(...newRecords); | |
| localStorage.setItem(tableName, JSON.stringify(records)); | |
| return newRecords; | |
| } catch (error) { | |
| console.error(`Batch insert failed for table ${tableName}:`, error); | |
| throw error; | |
| } | |
| } | |
| // READ operations | |
| getAll(tableName) { | |
| try { | |
| const data = localStorage.getItem(tableName); | |
| return data ? JSON.parse(data) : []; | |
| } catch (error) { | |
| console.error(`Get all failed for table ${tableName}:`, error); | |
| return []; | |
| } | |
| } | |
| getById(tableName, id) { | |
| try { | |
| const records = this.getAll(tableName); | |
| return records.find(record => record.id === id); | |
| } catch (error) { | |
| console.error(`Get by ID failed for table ${tableName}:`, error); | |
| return null; | |
| } | |
| } | |
| query(tableName, filterFn) { | |
| try { | |
| const records = this.getAll(tableName); | |
| return records.filter(filterFn); | |
| } catch (error) { | |
| console.error(`Query failed for table ${tableName}:`, error); | |
| return []; | |
| } | |
| } | |
| // Advanced query methods | |
| where(tableName, conditions) { | |
| try { | |
| const records = this.getAll(tableName); | |
| return records.filter(record => { | |
| return Object.entries(conditions).every(([key, value]) => { | |
| if (typeof value === 'object' && value !== null) { | |
| // Handle operators like { $gt: 10 }, { $in: ['a', 'b'] } | |
| if (value.$gt !== undefined) return record[key] > value.$gt; | |
| if (value.$lt !== undefined) return record[key] < value.$lt; | |
| if (value.$gte !== undefined) return record[key] >= value.$gte; | |
| if (value.$lte !== undefined) return record[key] <= value.$lte; | |
| if (value.$in !== undefined) return value.$in.includes(record[key]); | |
| if (value.$nin !== undefined) return !value.$nin.includes(record[key]); | |
| if (value.$ne !== undefined) return record[key] !== value.$ne; | |
| } | |
| return record[key] === value; | |
| }); | |
| }); | |
| } catch (error) { | |
| console.error(`Where query failed for table ${tableName}:`, error); | |
| return []; | |
| } | |
| } | |
| // UPDATE operations | |
| async update(tableName, id, updateData) { | |
| try { | |
| const records = this.getAll(tableName); | |
| const index = records.findIndex(record => record.id === id); | |
| if (index !== -1) { | |
| records[index] = { | |
| ...records[index], | |
| ...updateData, | |
| updated_at: new Date().toISOString() | |
| }; | |
| localStorage.setItem(tableName, JSON.stringify(records)); | |
| return records[index]; | |
| } | |
| return null; | |
| } catch (error) { | |
| console.error(`Update failed for table ${tableName}:`, error); | |
| throw error; | |
| } | |
| } | |
| async updateWhere(tableName, conditions, updateData) { | |
| try { | |
| const records = this.getAll(tableName); | |
| let updatedCount = 0; | |
| const updatedRecords = records.map(record => { | |
| const matches = Object.entries(conditions).every(([key, value]) => record[key] === value); | |
| if (matches) { | |
| updatedCount++; | |
| return { | |
| ...record, | |
| ...updateData, | |
| updated_at: new Date().toISOString() | |
| }; | |
| } | |
| return record; | |
| }); | |
| localStorage.setItem(tableName, JSON.stringify(updatedRecords)); | |
| return updatedCount; | |
| } catch (error) { | |
| console.error(`Update where failed for table ${tableName}:`, error); | |
| throw error; | |
| } | |
| } | |
| // DELETE operations | |
| async delete(tableName, id) { | |
| try { | |
| const records = this.getAll(tableName); | |
| const filteredRecords = records.filter(record => record.id !== id); | |
| if (filteredRecords.length !== records.length) { | |
| localStorage.setItem(tableName, JSON.stringify(filteredRecords)); | |
| return true; | |
| } | |
| return false; | |
| } catch (error) { | |
| console.error(`Delete failed for table ${tableName}:`, error); | |
| throw error; | |
| } | |
| } | |
| async deleteWhere(tableName, conditions) { | |
| try { | |
| const records = this.getAll(tableName); | |
| const filteredRecords = records.filter(record => { | |
| return !Object.entries(conditions).every(([key, value]) => record[key] === value); | |
| }); | |
| const deletedCount = records.length - filteredRecords.length; | |
| localStorage.setItem(tableName, JSON.stringify(filteredRecords)); | |
| return deletedCount; | |
| } catch (error) { | |
| console.error(`Delete where failed for table ${tableName}:`, error); | |
| throw error; | |
| } | |
| } | |
| // UTILITY operations | |
| async clearTable(tableName) { | |
| try { | |
| localStorage.setItem(tableName, JSON.stringify([])); | |
| return true; | |
| } catch (error) { | |
| console.error(`Clear table failed for ${tableName}:`, error); | |
| throw error; | |
| } | |
| } | |
| async clearAllTables() { | |
| try { | |
| Object.values(this.tables).forEach(tableName => { | |
| localStorage.setItem(tableName, JSON.stringify([])); | |
| }); | |
| return true; | |
| } catch (error) { | |
| console.error('Clear all tables failed:', error); | |
| throw error; | |
| } | |
| } | |
| getTotalRecords() { | |
| try { | |
| let total = 0; | |
| Object.values(this.tables).forEach(tableName => { | |
| total += this.getAll(tableName).length; | |
| }); | |
| return total; | |
| } catch (error) { | |
| console.error('Get total records failed:', error); | |
| return 0; | |
| } | |
| } | |
| getTableStats() { | |
| try { | |
| const stats = {}; | |
| Object.entries(this.tables).forEach(([key, tableName]) => { | |
| stats[key] = { | |
| tableName, | |
| count: this.getAll(tableName).length | |
| }; | |
| }); | |
| return stats; | |
| } catch (error) { | |
| console.error('Get table stats failed:', error); | |
| return {}; | |
| } | |
| } | |
| // BACKUP and RESTORE operations | |
| exportData() { | |
| try { | |
| const data = {}; | |
| Object.entries(this.tables).forEach(([key, tableName]) => { | |
| data[key] = this.getAll(tableName); | |
| }); | |
| const exportData = { | |
| timestamp: new Date().toISOString(), | |
| version: '1.0', | |
| data: data | |
| }; | |
| return JSON.stringify(exportData, null, 2); | |
| } catch (error) { | |
| console.error('Export data failed:', error); | |
| throw error; | |
| } | |
| } | |
| async importData(jsonData) { | |
| try { | |
| const importData = JSON.parse(jsonData); | |
| if (!importData.data) { | |
| throw new Error('Invalid import data format'); | |
| } | |
| Object.entries(importData.data).forEach(([key, records]) => { | |
| if (this.tables[key]) { | |
| localStorage.setItem(this.tables[key], JSON.stringify(records)); | |
| } | |
| }); | |
| return true; | |
| } catch (error) { | |
| console.error('Import data failed:', error); | |
| throw error; | |
| } | |
| } | |
| // SEARCH operations | |
| search(tableName, searchTerm, fields = []) { | |
| try { | |
| const records = this.getAll(tableName); | |
| const searchLower = searchTerm.toString().toLowerCase(); | |
| return records.filter(record => { | |
| if (fields.length === 0) { | |
| // Search all fields | |
| return Object.values(record).some(value => | |
| value && value.toString().toLowerCase().includes(searchLower) | |
| ); | |
| } else { | |
| // Search specific fields | |
| return fields.some(field => | |
| record[field] && record[field].toString().toLowerCase().includes(searchLower) | |
| ); | |
| } | |
| }); | |
| } catch (error) { | |
| console.error(`Search failed for table ${tableName}:`, error); | |
| return []; | |
| } | |
| } | |
| // PAGINATION | |
| paginate(tableName, page = 1, limit = 10, orderBy = 'created_at', order = 'desc') { | |
| try { | |
| const records = this.getAll(tableName); | |
| // Sort records | |
| const sortedRecords = records.sort((a, b) => { | |
| const aVal = a[orderBy]; | |
| const bVal = b[orderBy]; | |
| if (order === 'desc') { | |
| return aVal > bVal ? -1 : aVal < bVal ? 1 : 0; | |
| } else { | |
| return aVal < bVal ? -1 : aVal > bVal ? 1 : 0; | |
| } | |
| }); | |
| // Paginate | |
| const startIndex = (page - 1) * limit; | |
| const endIndex = startIndex + limit; | |
| const paginatedRecords = sortedRecords.slice(startIndex, endIndex); | |
| return { | |
| data: paginatedRecords, | |
| pagination: { | |
| currentPage: page, | |
| totalPages: Math.ceil(records.length / limit), | |
| totalRecords: records.length, | |
| hasNext: endIndex < records.length, | |
| hasPrev: page > 1 | |
| } | |
| }; | |
| } catch (error) { | |
| console.error(`Pagination failed for table ${tableName}:`, error); | |
| return { data: [], pagination: {} }; | |
| } | |
| } | |
| // VALIDATION | |
| validateRecord(tableName, record, schema = null) { | |
| // Basic validation - can be extended with more complex schemas | |
| if (!record.id) { | |
| record.id = this.generateId(); | |
| } | |
| if (!record.created_at) { | |
| record.created_at = new Date().toISOString(); | |
| } | |
| record.updated_at = new Date().toISOString(); | |
| return record; | |
| } | |
| // CONNECTION status | |
| isConnected() { | |
| return this.connected; | |
| } | |
| getConnectionInfo() { | |
| return { | |
| connected: this.connected, | |
| type: 'localStorage', | |
| tables: Object.keys(this.tables).length, | |
| totalRecords: this.getTotalRecords() | |
| }; | |
| } | |
| } | |
| async processTask(task) { | |
| const processor = this.processors.get(task.type) || this.processors.get('single'); | |
| return await processor.execute(task, this.agentSystem); | |
| } | |
| } | |
| // Base Processor Class | |
| class BaseProcessor { | |
| async execute(task, agentSystem) { | |
| // Simulate processing time | |
| await new Promise(resolve => setTimeout(resolve, Math.random() * 2000 + 1000)); | |
| return { | |
| processed: true, | |
| result: `Task "${task.description}" completed successfully`, | |
| timestamp: new Date().toISOString() | |
| }; | |
| } | |
| } | |
| // Specific Processor Implementations | |
| class SingleTaskProcessor extends BaseProcessor { | |
| async execute(task, agentSystem) { | |
| agentSystem.log(`Processing single task: ${task.id}`, 'info'); | |
| const result = await super.execute(task, agentSystem); | |
| result.type = 'single_task'; | |
| return result; | |
| } | |
| } | |
| class WorkflowProcessor extends BaseProcessor { | |
| async execute(task, agentSystem) { | |
| agentSystem.log(`Processing workflow: ${task.id}`, 'info'); | |
| const steps = ['Step 1: Initialize', 'Step 2: Process', 'Step 3: Finalize']; | |
| const stepResults = []; | |
| for (let i = 0; i < steps.length; i++) { | |
| agentSystem.log(`Executing ${steps[i]}`, 'info'); | |
| await new Promise(resolve => setTimeout(resolve, 800)); | |
| stepResults.push(`${steps[i]} completed`); | |
| } | |
| return { | |
| processed: true, | |
| result: 'Workflow completed successfully', | |
| steps: stepResults, | |
| timestamp: new Date().toISOString() | |
| }; | |
| } | |
| } | |
| class BatchProcessor extends BaseProcessor { | |
| async execute(task, agentSystem) { | |
| agentSystem.log(`Processing batch task: ${task.id}`, 'info'); | |
| const batchSize = 5; | |
| const processed = []; | |
| for (let i = 0; i < batchSize; i++) { | |
| agentSystem.log(`Processing batch item ${i + 1}/${batchSize}`, 'info'); | |
| await new Promise(resolve => setTimeout(resolve, 500)); | |
| processed.push(`Item ${i + 1} processed`); | |
| } | |
| return { | |
| processed: true, | |
| result: `Batch processing completed - ${batchSize} items processed`, | |
| items: processed, | |
| timestamp: new Date().toISOString() | |
| }; | |
| } | |
| } | |
| class ScheduledProcessor extends BaseProcessor { | |
| async execute(task, agentSystem) { | |
| agentSystem.log(`Processing scheduled task: ${task.id}`, 'info'); | |
| const result = await super.execute(task, agentSystem); | |
| result.type = 'scheduled_task'; | |
| result.scheduledFor = task.parameters?.scheduledTime || 'immediate'; | |
| return result; | |
| } | |
| } | |
| class MonitoringProcessor extends BaseProcessor { | |
| async execute(task, agentSystem) { | |
| agentSystem.log(`Processing monitoring task: ${task.id}`, 'info'); | |
| // Simulate monitoring checks | |
| const checks = ['System Health', 'Database Status', 'Agent Status', 'Task Queue']; | |
| const results = {}; | |
| for (const check of checks) { | |
| await new Promise(resolve => setTimeout(resolve, 300)); | |
| results[check] = Math.random() > 0.8 ? 'Warning' : 'OK'; | |
| } | |
| return { | |
| processed: true, | |
| result: 'Monitoring completed', | |
| checks: results, | |
| timestamp: new Date().toISOString() | |
| }; | |
| } | |
| } | |
| // Enhanced Agent System with proper queue management | |
| class EnhancedAgentSystem { | |
| constructor() { | |
| this.db = new DatabaseManager(); | |
| this.taskEngine = null; | |
| this.agents = new Map(); | |
| this.tasks = []; | |
| this.logs = []; | |
| this.isInitialized = false; | |
| this.processingQueue = false; | |
| this.init(); | |
| } | |
| async init() { | |
| console.log('🚀 Initializing Enhanced Agent System...'); | |
| // Wait for database to be ready | |
| await new Promise(resolve => { | |
| const checkDb = () => { | |
| if (this.db.connected) { | |
| resolve(); | |
| } else { | |
| setTimeout(checkDb, 100); | |
| } | |
| }; | |
| checkDb(); | |
| }); | |
| // FIXED: Initialize Task Processing Engine properly | |
| this.taskEngine = new TaskProcessingEngine(this); | |
| // Load existing data from database | |
| await this.loadFromDatabase(); | |
| // Initialize default agents | |
| this.createDefaultAgents(); | |
| // Start monitoring | |
| this.startSystemMonitoring(); | |
| // Update UI | |
| this.updateUI(); | |
| this.isInitialized = true; | |
| this.log('System initialized successfully', 'success'); | |
| } | |
| async loadFromDatabase() { | |
| // Load tasks | |
| const savedTasks = this.db.getAll(this.db.tables.tasks); | |
| this.tasks = savedTasks.map(task => ({ | |
| ...task, | |
| createdAt: new Date(task.created_at), | |
| updatedAt: new Date(task.updated_at) | |
| })); | |
| // Load agents | |
| const savedAgents = this.db.getAll(this.db.tables.agents); | |
| savedAgents.forEach(agent => { | |
| this.agents.set(agent.id, { | |
| ...agent, | |
| createdAt: new Date(agent.created_at), | |
| status: 'idle' // Reset status on load | |
| }); | |
| }); | |
| this.log(`Loaded ${this.tasks.length} tasks and ${this.agents.size} agents from database`, 'info'); | |
| } | |
| createDefaultAgents() { | |
| if (this.agents.size === 0) { | |
| const defaultAgents = [ | |
| { name: 'Task Manager', role: 'coordinator', capabilities: ['task_management', 'workflow'] }, | |
| { name: 'Data Processor', role: 'worker', capabilities: ['data_processing', 'analysis'] }, | |
| { name: 'Web Scraper', role: 'worker', capabilities: ['web_scraping', 'data_extraction'] }, | |
| { name: 'Monitor Agent', role: 'observer', capabilities: ['monitoring', 'alerting'] } | |
| ]; | |
| defaultAgents.forEach(agentData => { | |
| this.createAgent(agentData); | |
| }); | |
| } | |
| } | |
| async createAgent(agentData) { | |
| const agent = { | |
| id: this.db.generateId(), | |
| name: agentData.name, | |
| role: agentData.role || 'worker', | |
| capabilities: agentData.capabilities || [], | |
| status: 'idle', | |
| tasksCompleted: 0, | |
| tasksInProgress: 0, | |
| createdAt: new Date() | |
| }; | |
| this.agents.set(agent.id, agent); | |
| // Save to database | |
| await this.db.insert(this.db.tables.agents, { | |
| ...agent, | |
| createdAt: agent.createdAt.toISOString() | |
| }); | |
| this.log(`Created agent: ${agent.name}`, 'success'); | |
| this.updateUI(); | |
| return agent; | |
| } | |
| async createTask(taskData) { | |
| const task = { | |
| id: this.db.generateId(), | |
| type: taskData.type || 'single', | |
| description: taskData.description, | |
| priority: taskData.priority || 'normal', | |
| assignedAgent: taskData.assignedAgent || null, | |
| status: 'queued', | |
| parameters: taskData.parameters || {}, | |
| dependencies: taskData.dependencies || [], | |
| createdAt: new Date(), | |
| retries: 0, | |
| maxRetries: 3 | |
| }; | |
| this.tasks.push(task); | |
| // Save to database | |
| await this.db.insert(this.db.tables.tasks, { | |
| ...task, | |
| createdAt: task.createdAt.toISOString() | |
| }); | |
| this.log(`Created task: ${task.id} - ${task.description}`, 'info'); | |
| // FIXED: Process task if engine is ready and not already processing | |
| if (this.taskEngine && !this.processingQueue) { | |
| setTimeout(() => this.processNextTask(), 100); | |
| } | |
| this.updateUI(); | |
| return task; | |
| // FIXED VERSION - Replace the processNextTask method with this corrected version | |
| async processNextTask() { | |
| if (this.processingQueue) return; // Prevent multiple simultaneous processing | |
| const queuedTasks = this.tasks.filter(task => task.status === 'queued'); | |
| if (queuedTasks.length === 0) return; | |
| this.processingQueue = true; // Set processing flag | |
| // Sort by priority | |
| const priorityOrder = { urgent: 4, high: 3, normal: 2, low: 1 }; | |
| queuedTasks.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]); | |
| const task = queuedTasks[0]; | |
| try { | |
| // Update task status to processing | |
| task.status = 'processing'; | |
| await this.db.update(this.db.tables.tasks, task.id, { status: 'processing' }); | |
| this.updateUI(); // Update UI immediately | |
| // Process with task engine | |
| const result = await this.taskEngine.processTask(task); | |
| // Update task with results | |
| task.status = 'completed'; | |
| task.result = result; | |
| task.completedAt = new Date(); | |
| await this.db.update(this.db.tables.tasks, task.id, { | |
| status: 'completed', | |
| result: JSON.stringify(result), | |
| completed_at: task.completedAt.toISOString() | |
| }); | |
| this.log(`Task completed: ${task.id}`, 'success'); | |
| } catch (error) { | |
| task.status = 'failed'; | |
| task.error = error.message; | |
| await this.db.update(this.db.tables.tasks, task.id, { | |
| status: 'failed', | |
| error: error.message | |
| }); | |
| this.log(`Task failed: ${task.id} - ${error.message}`, 'error'); | |
| } | |
| this.processingQueue = false; // Reset processing flag | |
| this.updateUI(); | |
| startSystemMonitoring() { | |
| setInterval(() => { | |
| this.updateSystemMetrics(); | |
| this.updateUI(); | |
| }, 5000); | |
| } | |
| updateSystemMetrics() { | |
| const metrics = { | |
| id: this.db.generateId(), | |
| timestamp: new Date().toISOString(), | |
| active_agents: Array.from(this.agents.values()).filter(a => a.status === 'active').length, | |
| queued_tasks: this.tasks.filter(t => t.status === 'queued').length, | |
| processing_tasks: this.tasks.filter(t => t.status === 'processing').length, | |
| completed_tasks: this.tasks.filter(t => t.status === 'completed').length, | |
| failed_tasks: this.tasks.filter(t => t.status === 'failed').length, | |
| total_db_records: this.db.getTotalRecords() | |
| }; | |
| // Save metrics to database (keep last 100 entries) | |
| const savedMetrics = this.db.getAll(this.db.tables.metrics); | |
| savedMetrics.push(metrics); | |
| if (savedMetrics.length > 100) { | |
| savedMetrics.splice(0, savedMetrics.length - 100); | |
| } | |
| localStorage.setItem(this.db.tables.metrics, JSON.stringify(savedMetrics)); | |
| } | |
| log(message, level = 'info') { | |
| const logEntry = { | |
| id: this.db.generateId(), | |
| timestamp: new Date(), | |
| level: level, | |
| message: message | |
| }; | |
| this.logs.push(logEntry); | |
| // Keep only last 100 logs in memory | |
| if (this.logs.length > 100) { | |
| this.logs.shift(); | |
| } | |
| // Save to database | |
| this.db.insert(this.db.tables.logs, { | |
| ...logEntry, | |
| timestamp: logEntry.timestamp.toISOString() | |
| }); | |
| console.log(`[${level.toUpperCase()}] ${message}`); | |
| this.updateLogsUI(); | |
| } | |
| updateUI() { | |
| this.updateStatusCards(); | |
| this.updateAgentsDisplay(); | |
| this.updateTasksList(); | |
| this.updateDatabaseTable(); | |
| } | |
| updateStatusCards() { | |
| const activeAgents = Array.from(this.agents.values()).filter(a => a.status === 'active').length; | |
| const queuedTasks = this.tasks.filter(t => t.status === 'queued').length; | |
| const processingTasks = this.tasks.filter(t => t.status === 'processing').length; | |
| const completedTasks = this.tasks.filter(t => t.status === 'completed').length; | |
| const dbRecords = this.db.getTotalRecords(); | |
| document.getElementById('active-agents').textContent = activeAgents; | |
| document.getElementById('queued-tasks').textContent = queuedTasks; | |
| document.getElementById('processing-tasks').textContent = processingTasks; | |
| document.getElementById('completed-tasks').textContent = completedTasks; | |
| document.getElementById('db-records').textContent = dbRecords; | |
| } | |
| updateAgentsDisplay() { | |
| const container = document.getElementById('agents-container'); | |
| container.innerHTML = ''; | |
| Array.from(this.agents.values()).forEach(agent => { | |
| const agentCard = document.createElement('div'); | |
| agentCard.className = 'agent-card'; | |
| agentCard.innerHTML = ` | |
| <div class="agent-name">${agent.name}</div> | |
| <div class="agent-status status-${agent.status}">${agent.status}</div> | |
| <div style="font-size: 12px; color: #666;"> | |
| <div>Role: ${agent.role}</div> | |
| <div>Tasks: ${agent.tasksCompleted || 0}</div> | |
| </div> | |
| <button class="btn btn-danger" onclick="agentSystem.deleteAgent('${agent.id}')" style="margin-top: 10px; padding: 5px 10px; font-size: 12px;">Remove</button> | |
| `; | |
| container.appendChild(agentCard); | |
| }); | |
| // Update agent dropdown | |
| const agentSelect = document.getElementById('task-agent'); | |
| agentSelect.innerHTML = '<option value="">Auto-assign</option>'; | |
| Array.from(this.agents.values()).forEach(agent => { | |
| const option = document.createElement('option'); | |
| option.value = agent.id; | |
| option.textContent = agent.name; | |
| agentSelect.appendChild(option); | |
| }); | |
| } | |
| updateTasksList() { | |
| const container = document.getElementById('task-list'); | |
| container.innerHTML = ''; | |
| // Sort tasks by creation date (newest first) | |
| const sortedTasks = [...this.tasks].sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); | |
| sortedTasks.slice(0, 20).forEach(task => { // Show only last 20 tasks | |
| const taskItem = document.createElement('div'); | |
| taskItem.className = 'task-item'; | |
| const assignedAgent = task.assignedAgent ? | |
| this.agents.get(task.assignedAgent)?.name || 'Unknown Agent' : | |
| 'Auto-assigned'; | |
| taskItem.innerHTML = ` | |
| <div class="task-header"> | |
| <span class="task-id">${task.id}</span> | |
| <span class="task-status status-${task.status}">${task.status}</span> | |
| </div> | |
| <div style="margin-bottom: 8px;"> | |
| <strong>Type:</strong> ${task.type} | | |
| <strong>Priority:</strong> ${task.priority} | | |
| <strong>Agent:</strong> ${assignedAgent} | |
| </div> | |
| <div style="margin-bottom: 8px;"> | |
| <strong>Description:</strong> ${task.description} | |
| </div> | |
| <div style="font-size: 12px; color: #666;"> | |
| <div>Created: ${task.createdAt.toLocaleString()}</div> | |
| ${task.completedAt ? `<div>Completed: ${task.completedAt.toLocaleString()}</div>` : ''} | |
| ${task.error ? `<div style="color: #c53030;">Error: ${task.error}</div>` : ''} | |
| </div> | |
| <div style="margin-top: 10px;"> | |
| <button class="btn btn-danger" onclick="agentSystem.deleteTask('${task.id}')" style="padding: 5px 10px; font-size: 12px;">Delete</button> | |
| ${task.status === 'failed' ? `<button class="btn btn-primary" onclick="agentSystem.retryTask('${task.id}')" style="padding: 5px 10px; font-size: 12px; margin-left: 5px;">Retry</button>` : ''} | |
| </div> | |
| `; | |
| container.appendChild(taskItem); | |
| }); | |
| } | |
| updateDatabaseTable() { | |
| const tbody = document.getElementById('data-table-body'); | |
| tbody.innerHTML = ''; | |
| // Get recent records from all tables | |
| const allRecords = []; | |
| Object.entries(this.db.tables).forEach(([tableName, table]) => { | |
| const records = this.db.getAll(table); | |
| records.forEach(record => { | |
| allRecords.push({ | |
| ...record, | |
| table: tableName | |
| }); | |
| }); | |
| }); | |
| // Sort by creation date and take last 50 | |
| allRecords.sort((a, b) => new Date(b.created_at || b.timestamp) - new Date(a.created_at || a.timestamp)); | |
| allRecords.slice(0, 50).forEach(record => { | |
| const row = document.createElement('tr'); | |
| row.innerHTML = ` | |
| <td>${record.id}</td> | |
| <td>${record.table}</td> | |
| <td>${record.status || record.level || 'N/A'}</td> | |
| <td>${new Date(record.created_at || record.timestamp).toLocaleString()}</td> | |
| <td>${record.updated_at ? new Date(record.updated_at).toLocaleString() : 'N/A'}</td> | |
| <td> | |
| <button class="btn-danger" onclick="agentSystem.deleteRecord('${record.table}', '${record.id}')" style="padding: 3px 6px; font-size: 11px;">Delete</button> | |
| </td> | |
| `; | |
| tbody.appendChild(row); | |
| }); | |
| } | |
| updateLogsUI() { | |
| const container = document.getElementById('logs-container'); | |
| container.innerHTML = ''; | |
| this.logs.slice(-20).forEach(log => { | |
| const logEntry = document.createElement('div'); | |
| logEntry.className = 'log-entry'; | |
| logEntry.innerHTML = ` | |
| <span class="log-timestamp">[${log.timestamp.toLocaleTimeString()}]</span> | |
| <span class="log-level-${log.level}">[${log.level.toUpperCase()}]</span> | |
| <span>${log.message}</span> | |
| `; | |
| container.appendChild(logEntry); | |
| }); | |
| // Auto-scroll to bottom | |
| container.scrollTop = container.scrollHeight; | |
| } | |
| async deleteAgent(agentId) { | |
| if (confirm('Are you sure you want to delete this agent?')) { | |
| this.agents.delete(agentId); | |
| await this.db.delete(this.db.tables.agents, agentId); | |
| this.log(`Deleted agent: ${agentId}`, 'warning'); | |
| this.updateUI(); | |
| } | |
| } | |
| async deleteTask(taskId) { | |
| if (confirm('Are you sure you want to delete this task?')) { | |
| this.tasks = this.tasks.filter(t => t.id !== taskId); | |
| await this.db.delete(this.db.tables.tasks, taskId); | |
| this.log(`Deleted task: ${taskId}`, 'warning'); | |
| this.updateUI(); | |
| } | |
| } | |
| async retryTask(taskId) { | |
| const task = this.tasks.find(t => t.id === taskId); | |
| if (task) { | |
| task.status = 'queued'; | |
| task.retries = 0; | |
| task.error = null; | |
| await this.db.update(this.db.tables.tasks, taskId, { | |
| status: 'queued', | |
| error: null | |
| }); | |
| this.log(`Retrying task: ${taskId}`, 'info'); | |
| this.updateUI(); | |
| setTimeout(() => this.processNextTask(), 100); | |
| } | |
| } | |
| async deleteRecord(table, id) { | |
| if (confirm('Are you sure you want to delete this record?')) { | |
| await this.db.delete(table, id); | |
| this.log(`Deleted record from ${table}: ${id}`, 'warning'); | |
| this.updateUI(); | |
| } | |
| } | |
| } | |
| // Global system instance | |
| let agentSystem; | |
| // UI Event Handlers - FIXED: Prevent form submission redirect | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize the system | |
| agentSystem = new EnhancedAgentSystem(); | |
| // Task form submission | |
| document.getElementById('task-form').addEventListener('submit', function(e) { | |
| e.preventDefault(); // FIXED: This prevents the page redirect | |
| const taskData = { | |
| type: document.getElementById('task-type').value, | |
| description: document.getElementById('task-description').value, | |
| priority: document.getElementById('task-priority').value, | |
| assignedAgent: document.getElementById('task-agent').value || null, | |
| parameters: {} | |
| }; | |
| if (taskData.description.trim()) { | |
| agentSystem.createTask(taskData); | |
| // Reset form | |
| document.getElementById('task-form').reset(); | |
| } else { | |
| alert('Please enter a task description'); | |
| // Global utility functions | |
| function createAgent() { | |
| const name = prompt('Enter agent name:'); | |
| if (name) { | |
| const role = prompt('Enter agent role (worker/coordinator/observer):', 'worker'); | |
| const capabilities = prompt('Enter capabilities (comma-separated):', 'general').split(',').map(s => s.trim()); | |
| agentSystem.createAgent({ | |
| name: name, | |
| role: role || 'worker', | |
| capabilities: capabilities | |
| }); | |
| } | |
| } | |
| function initializeDatabase() { | |
| agentSystem.db.clearAll(); | |
| agentSystem.log('Database initialized', 'success'); | |
| agentSystem.updateUI(); | |
| } | |
| function exportData() { | |
| const data = { | |
| tasks: agentSystem.tasks, | |
| agents: Array.from(agentSystem.agents.values()), | |
| logs: agentSystem.logs, | |
| timestamp: new Date().toISOString() | |
| }; | |
| const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = `agent_system_export_${Date.now()}.json`; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| URL.revokeObjectURL(url); | |
| agentSystem.log('Data exported successfully', 'success'); | |
| } | |
| function clearDatabase() { | |
| if (confirm('This will delete all data. Are you sure?')) { | |
| agentSystem.db.clearAll(); | |
| agentSystem.tasks = []; | |
| agentSystem.agents.clear(); | |
| agentSystem.logs = []; | |
| agentSystem.log('Database cleared', 'warning'); | |
| agentSystem.updateUI(); | |
| } | |
| } | |
| function showQueryInterface() { | |
| document.getElementById('query-modal').style.display = 'block'; | |
| } | |
| function closeModal() { | |
| document.getElementById('query-modal').style.display = 'none'; | |
| } | |
| function executeQuery() { | |
| const query = document.getElementById('query-input').value.trim(); | |
| const resultsDiv = document.getElementById('query-results'); | |
| if (!query) { | |
| resultsDiv.innerHTML = '<p style="color: red;">Please enter a query</p>'; | |
| return; | |
| } | |
| // Simple query parser (basic SELECT functionality) | |
| try { | |
| let results = []; | |
| const lowerQuery = query.toLowerCase(); | |
| if (lowerQuery.includes('from tasks')) { | |
| results = agentSystem.tasks; | |
| } else if (lowerQuery.includes('from agents')) { | |
| results = Array.from(agentSystem.agents.values()); | |
| } else if (lowerQuery.includes('from logs')) { | |
| results = agentSystem.logs; | |
| } else { | |
| throw new Error('Unsupported query. Use: SELECT * FROM tasks/agents/logs'); | |
| } | |
| // Basic WHERE filtering | |
| if (lowerQuery.includes('where')) { | |
| const whereMatch = query.match(/where\s+(\w+)\s*=\s*'([^']+)'/i); | |
| if (whereMatch) { | |
| const [, field, value] = whereMatch; | |
| results = results.filter(item => item[field] === value); | |
| } | |
| } | |
| // Display results | |
| if (results.length === 0) { | |
| resultsDiv.innerHTML = '<p>No results found</p>'; | |
| } else { | |
| const table = document.createElement('table'); | |
| table.className = 'data-table'; | |
| table.style.marginTop = '15px'; | |
| // Headers | |
| const headers = Object.keys(results[0]); | |
| const headerRow = table.insertRow(); | |
| headers.forEach(header => { | |
| const th = document.createElement('th'); | |
| th.textContent = header; | |
| headerRow.appendChild(th); | |
| }); | |
| // Data rows | |
| results.slice(0, 20).forEach(item => { | |
| const row = table.insertRow(); | |
| headers.forEach(header => { | |
| const cell = row.insertCell(); | |
| let value = item[header]; | |
| if (typeof value === 'object' && value !== null) { | |
| value = JSON.stringify(value); | |
| } | |
| cell.textContent = value || 'N/A'; | |
| }); | |
| }); | |
| resultsDiv.innerHTML = ''; | |
| resultsDiv.appendChild(table); | |
| } | |
| agentSystem.log(`Query executed: ${query}`, 'info'); | |
| } catch (error) { | |
| resultsDiv.innerHTML = `<p style="color: red;">Query Error: ${error.message}</p>`; | |
| agentSystem.log(`Query failed: ${error.message}`, 'error'); | |
| } | |
| } | |
| function clearLogs() { | |
| agentSystem.logs = []; | |
| agentSystem.db.clear(agentSystem.db.tables.logs); | |
| agentSystem.updateLogsUI(); | |
| agentSystem.log('Logs cleared', 'info'); | |
| } | |
| } | |
| }); | |
| }); | |
| </script> | |