Spaces:
Running
Running
Update index.html
Browse files- index.html +506 -8
index.html
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
-
|
|
|
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
|
@@ -179,7 +180,7 @@
|
|
| 179 |
|
| 180 |
.task-header {
|
| 181 |
display: flex;
|
| 182 |
-
justify-content: space-between;
|
| 183 |
align-items: center;
|
| 184 |
margin-bottom: 8px;
|
| 185 |
}
|
|
@@ -382,7 +383,6 @@
|
|
| 382 |
</style>
|
| 383 |
</head>
|
| 384 |
<body>
|
| 385 |
-
<!-- Your existing HTML body content stays the same -->
|
| 386 |
<div class="container">
|
| 387 |
<div class="header">
|
| 388 |
<h1>🤖 Advanced Agent System</h1>
|
|
@@ -628,8 +628,506 @@
|
|
| 628 |
}
|
| 629 |
|
| 630 |
class ScheduledProcessor extends BaseProcessor {
|
| 631 |
-
|
| 632 |
-
|
| 633 |
-
|
| 634 |
-
|
| 635 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
}
|
| 2 |
+
<!DOCTYPE html>
|
| 3 |
<html lang="en">
|
| 4 |
<head>
|
| 5 |
<meta charset="UTF-8">
|
|
|
|
| 180 |
|
| 181 |
.task-header {
|
| 182 |
display: flex;
|
| 183 |
+
justify-content: space-between;
|
| 184 |
align-items: center;
|
| 185 |
margin-bottom: 8px;
|
| 186 |
}
|
|
|
|
| 383 |
</style>
|
| 384 |
</head>
|
| 385 |
<body>
|
|
|
|
| 386 |
<div class="container">
|
| 387 |
<div class="header">
|
| 388 |
<h1>🤖 Advanced Agent System</h1>
|
|
|
|
| 628 |
}
|
| 629 |
|
| 630 |
class ScheduledProcessor extends BaseProcessor {
|
| 631 |
+
async execute(task, agentSystem) {
|
| 632 |
+
agentSystem.log(`Processing scheduled task: ${task.id}`, 'info');
|
| 633 |
+
const result = await super.execute(task, agentSystem);
|
| 634 |
+
result.type = 'scheduled_task';
|
| 635 |
+
result.scheduledFor = task.parameters?.scheduledTime || 'immediate';
|
| 636 |
+
return result;
|
| 637 |
+
}
|
| 638 |
+
}
|
| 639 |
+
|
| 640 |
+
class MonitoringProcessor extends BaseProcessor {
|
| 641 |
+
async execute(task, agentSystem) {
|
| 642 |
+
agentSystem.log(`Processing monitoring task: ${task.id}`, 'info');
|
| 643 |
+
|
| 644 |
+
// Simulate monitoring checks
|
| 645 |
+
const checks = ['System Health', 'Database Status', 'Agent Status', 'Task Queue'];
|
| 646 |
+
const results = {};
|
| 647 |
+
|
| 648 |
+
for (const check of checks) {
|
| 649 |
+
await new Promise(resolve => setTimeout(resolve, 300));
|
| 650 |
+
results[check] = Math.random() > 0.8 ? 'Warning' : 'OK';
|
| 651 |
+
}
|
| 652 |
+
|
| 653 |
+
return {
|
| 654 |
+
processed: true,
|
| 655 |
+
result: 'Monitoring completed',
|
| 656 |
+
checks: results,
|
| 657 |
+
timestamp: new Date().toISOString()
|
| 658 |
+
};
|
| 659 |
+
}
|
| 660 |
+
}
|
| 661 |
+
|
| 662 |
+
// Enhanced Agent System with proper queue management
|
| 663 |
+
class EnhancedAgentSystem {
|
| 664 |
+
constructor() {
|
| 665 |
+
this.db = new DatabaseManager();
|
| 666 |
+
this.taskEngine = null;
|
| 667 |
+
this.agents = new Map();
|
| 668 |
+
this.tasks = [];
|
| 669 |
+
this.logs = [];
|
| 670 |
+
this.isInitialized = false;
|
| 671 |
+
this.processingQueue = false; // FIXED: Added this flag
|
| 672 |
+
|
| 673 |
+
this.init();
|
| 674 |
+
}
|
| 675 |
+
|
| 676 |
+
async init() {
|
| 677 |
+
console.log('🚀 Initializing Enhanced Agent System...');
|
| 678 |
+
|
| 679 |
+
// Wait for database to be ready
|
| 680 |
+
await new Promise(resolve => {
|
| 681 |
+
const checkDb = () => {
|
| 682 |
+
if (this.db.connected) {
|
| 683 |
+
resolve();
|
| 684 |
+
} else {
|
| 685 |
+
setTimeout(checkDb, 100);
|
| 686 |
+
}
|
| 687 |
+
};
|
| 688 |
+
checkDb();
|
| 689 |
+
});
|
| 690 |
+
|
| 691 |
+
// FIXED: Initialize Task Processing Engine properly
|
| 692 |
+
this.taskEngine = new TaskProcessingEngine(this);
|
| 693 |
+
|
| 694 |
+
// Load existing data from database
|
| 695 |
+
await this.loadFromDatabase();
|
| 696 |
+
|
| 697 |
+
// Initialize default agents
|
| 698 |
+
this.createDefaultAgents();
|
| 699 |
+
|
| 700 |
+
// Start monitoring
|
| 701 |
+
this.startSystemMonitoring();
|
| 702 |
+
|
| 703 |
+
// Update UI
|
| 704 |
+
this.updateUI();
|
| 705 |
+
|
| 706 |
+
this.isInitialized = true;
|
| 707 |
+
this.log('System initialized successfully', 'success');
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
async loadFromDatabase() {
|
| 711 |
+
// Load tasks
|
| 712 |
+
const savedTasks = this.db.getAll(this.db.tables.tasks);
|
| 713 |
+
this.tasks = savedTasks.map(task => ({
|
| 714 |
+
...task,
|
| 715 |
+
createdAt: new Date(task.created_at),
|
| 716 |
+
updatedAt: new Date(task.updated_at)
|
| 717 |
+
}));
|
| 718 |
+
|
| 719 |
+
// Load agents
|
| 720 |
+
const savedAgents = this.db.getAll(this.db.tables.agents);
|
| 721 |
+
savedAgents.forEach(agent => {
|
| 722 |
+
this.agents.set(agent.id, {
|
| 723 |
+
...agent,
|
| 724 |
+
createdAt: new Date(agent.created_at),
|
| 725 |
+
status: 'idle' // Reset status on load
|
| 726 |
+
});
|
| 727 |
+
});
|
| 728 |
+
|
| 729 |
+
this.log(`Loaded ${this.tasks.length} tasks and ${this.agents.size} agents from database`, 'info');
|
| 730 |
+
}
|
| 731 |
+
|
| 732 |
+
createDefaultAgents() {
|
| 733 |
+
if (this.agents.size === 0) {
|
| 734 |
+
const defaultAgents = [
|
| 735 |
+
{ name: 'Task Manager', role: 'coordinator', capabilities: ['task_management', 'workflow'] },
|
| 736 |
+
{ name: 'Data Processor', role: 'worker', capabilities: ['data_processing', 'analysis'] },
|
| 737 |
+
{ name: 'Web Scraper', role: 'worker', capabilities: ['web_scraping', 'data_extraction'] },
|
| 738 |
+
{ name: 'Monitor Agent', role: 'observer', capabilities: ['monitoring', 'alerting'] }
|
| 739 |
+
];
|
| 740 |
+
|
| 741 |
+
defaultAgents.forEach(agentData => {
|
| 742 |
+
this.createAgent(agentData);
|
| 743 |
+
});
|
| 744 |
+
}
|
| 745 |
+
}
|
| 746 |
+
|
| 747 |
+
async createAgent(agentData) {
|
| 748 |
+
const agent = {
|
| 749 |
+
id: this.db.generateId(),
|
| 750 |
+
name: agentData.name,
|
| 751 |
+
role: agentData.role || 'worker',
|
| 752 |
+
capabilities: agentData.capabilities || [],
|
| 753 |
+
status: 'idle',
|
| 754 |
+
tasksCompleted: 0,
|
| 755 |
+
tasksInProgress: 0,
|
| 756 |
+
createdAt: new Date()
|
| 757 |
+
};
|
| 758 |
+
|
| 759 |
+
this.agents.set(agent.id, agent);
|
| 760 |
+
|
| 761 |
+
// Save to database
|
| 762 |
+
await this.db.insert(this.db.tables.agents, {
|
| 763 |
+
...agent,
|
| 764 |
+
createdAt: agent.createdAt.toISOString()
|
| 765 |
+
});
|
| 766 |
+
|
| 767 |
+
this.log(`Created agent: ${agent.name}`, 'success');
|
| 768 |
+
this.updateUI();
|
| 769 |
+
return agent;
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
async createTask(taskData) {
|
| 773 |
+
const task = {
|
| 774 |
+
id: this.db.generateId(),
|
| 775 |
+
type: taskData.type || 'single',
|
| 776 |
+
description: taskData.description,
|
| 777 |
+
priority: taskData.priority || 'normal',
|
| 778 |
+
assignedAgent: taskData.assignedAgent || null,
|
| 779 |
+
status: 'queued',
|
| 780 |
+
parameters: taskData.parameters || {},
|
| 781 |
+
dependencies: taskData.dependencies || [],
|
| 782 |
+
createdAt: new Date(),
|
| 783 |
+
retries: 0,
|
| 784 |
+
maxRetries: 3
|
| 785 |
+
};
|
| 786 |
+
|
| 787 |
+
this.tasks.push(task);
|
| 788 |
+
|
| 789 |
+
// Save to database
|
| 790 |
+
await this.db.insert(this.db.tables.tasks, {
|
| 791 |
+
...task,
|
| 792 |
+
createdAt: task.createdAt.toISOString()
|
| 793 |
+
});
|
| 794 |
+
|
| 795 |
+
this.log(`Created task: ${task.id} - ${task.description}`, 'info');
|
| 796 |
+
|
| 797 |
+
// FIXED: Process task if engine is ready and not already processing
|
| 798 |
+
if (this.taskEngine && !this.processingQueue) {
|
| 799 |
+
setTimeout(() => this.processNextTask(), 100);
|
| 800 |
+
}
|
| 801 |
+
|
| 802 |
+
this.updateUI();
|
| 803 |
+
return task;
|
| 804 |
+
}
|
| 805 |
+
|
| 806 |
+
async processNextTask() {
|
| 807 |
+
if (this.processingQueue) return;
|
| 808 |
+
|
| 809 |
+
const queuedTasks = this.tasks.filter(task => task.status === 'queued');
|
| 810 |
+
if (queuedTasks.length === 0) return;
|
| 811 |
+
|
| 812 |
+
this.processingQueue = true;
|
| 813 |
+
|
| 814 |
+
// Sort by priority
|
| 815 |
+
const priorityOrder = { urgent: 4, high: 3, normal: 2, low: 1 };
|
| 816 |
+
queuedTasks.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]);
|
| 817 |
+
|
| 818 |
+
const task = queuedTasks[0];
|
| 819 |
+
|
| 820 |
+
try {
|
| 821 |
+
// Update task status
|
| 822 |
+
task.status = 'processing';
|
| 823 |
+
await this.db.update(this.db.tables.tasks, task.id, { status: 'processing' });
|
| 824 |
+
|
| 825 |
+
// Process with task engine
|
| 826 |
+
const result = await this.taskEngine.processTask(task);
|
| 827 |
+
|
| 828 |
+
// Update task with results
|
| 829 |
+
task.status = 'completed';
|
| 830 |
+
task.result = result;
|
| 831 |
+
task.completedAt = new Date();
|
| 832 |
+
|
| 833 |
+
await this.db.update(this.db.tables.tasks, task.id, {
|
| 834 |
+
status: 'completed',
|
| 835 |
+
result: JSON.stringify(result),
|
| 836 |
+
completed_at: task.completedAt.toISOString()
|
| 837 |
+
});
|
| 838 |
+
|
| 839 |
+
this.log(`Task completed: ${task.id}`, 'success');
|
| 840 |
+
|
| 841 |
+
} catch (error) {
|
| 842 |
+
task.status = 'failed';
|
| 843 |
+
task.error = error.message;
|
| 844 |
+
|
| 845 |
+
await this.db.update(this.db.tables.tasks, task.id, {
|
| 846 |
+
status: 'failed',
|
| 847 |
+
error: error.message
|
| 848 |
+
});
|
| 849 |
+
|
| 850 |
+
this.log(`Task failed: ${task.id} - ${error.message}`, 'error');
|
| 851 |
+
}
|
| 852 |
+
|
| 853 |
+
this.processingQueue = false;
|
| 854 |
+
this.updateUI();
|
| 855 |
+
|
| 856 |
+
// Process next task
|
| 857 |
+
setTimeout(() => this.processNextTask(), 1000);
|
| 858 |
+
}
|
| 859 |
+
|
| 860 |
+
startSystemMonitoring() {
|
| 861 |
+
setInterval(() => {
|
| 862 |
+
this.updateSystemMetrics();
|
| 863 |
+
this.updateUI();
|
| 864 |
+
}, 5000);
|
| 865 |
+
}
|
| 866 |
+
|
| 867 |
+
updateSystemMetrics() {
|
| 868 |
+
const metrics = {
|
| 869 |
+
id: this.db.generateId(),
|
| 870 |
+
timestamp: new Date().toISOString(),
|
| 871 |
+
active_agents: Array.from(this.agents.values()).filter(a => a.status === 'active').length,
|
| 872 |
+
queued_tasks: this.tasks.filter(t => t.status === 'queued').length,
|
| 873 |
+
processing_tasks: this.tasks.filter(t => t.status === 'processing').length,
|
| 874 |
+
completed_tasks: this.tasks.filter(t => t.status === 'completed').length,
|
| 875 |
+
failed_tasks: this.tasks.filter(t => t.status === 'failed').length,
|
| 876 |
+
total_db_records: this.db.getTotalRecords()
|
| 877 |
+
};
|
| 878 |
+
|
| 879 |
+
// Save metrics to database (keep last 100 entries)
|
| 880 |
+
const savedMetrics = this.db.getAll(this.db.tables.metrics);
|
| 881 |
+
savedMetrics.push(metrics);
|
| 882 |
+
if (savedMetrics.length > 100) {
|
| 883 |
+
savedMetrics.splice(0, savedMetrics.length - 100);
|
| 884 |
+
}
|
| 885 |
+
localStorage.setItem(this.db.tables.metrics, JSON.stringify(savedMetrics));
|
| 886 |
+
}
|
| 887 |
+
|
| 888 |
+
log(message, level = 'info') {
|
| 889 |
+
const logEntry = {
|
| 890 |
+
id: this.db.generateId(),
|
| 891 |
+
timestamp: new Date(),
|
| 892 |
+
level: level,
|
| 893 |
+
message: message
|
| 894 |
+
};
|
| 895 |
+
|
| 896 |
+
this.logs.push(logEntry);
|
| 897 |
+
|
| 898 |
+
// Keep only last 100 logs in memory
|
| 899 |
+
if (this.logs.length > 100) {
|
| 900 |
+
this.logs.shift();
|
| 901 |
+
}
|
| 902 |
+
|
| 903 |
+
// Save to database
|
| 904 |
+
this.db.insert(this.db.tables.logs, {
|
| 905 |
+
...logEntry,
|
| 906 |
+
timestamp: logEntry.timestamp.toISOString()
|
| 907 |
+
});
|
| 908 |
+
|
| 909 |
+
console.log(`[${level.toUpperCase()}] ${message}`);
|
| 910 |
+
this.updateLogsUI();
|
| 911 |
+
}
|
| 912 |
+
|
| 913 |
+
updateUI() {
|
| 914 |
+
this.updateStatusCards();
|
| 915 |
+
this.updateAgentsDisplay();
|
| 916 |
+
this.updateTasksList();
|
| 917 |
+
this.updateDatabaseTable();
|
| 918 |
+
}
|
| 919 |
+
|
| 920 |
+
updateStatusCards() {
|
| 921 |
+
const activeAgents = Array.from(this.agents.values()).filter(a => a.status === 'active').length;
|
| 922 |
+
const queuedTasks = this.tasks.filter(t => t.status === 'queued').length;
|
| 923 |
+
const processingTasks = this.tasks.filter(t => t.status === 'processing').length;
|
| 924 |
+
const completedTasks = this.tasks.filter(t => t.status === 'completed').length;
|
| 925 |
+
const dbRecords = this.db.getTotalRecords();
|
| 926 |
+
|
| 927 |
+
document.getElementById('active-agents').textContent = activeAgents;
|
| 928 |
+
document.getElementById('queued-tasks').textContent = queuedTasks;
|
| 929 |
+
document.getElementById('processing-tasks').textContent = processingTasks;
|
| 930 |
+
document.getElementById('completed-tasks').textContent = completedTasks;
|
| 931 |
+
document.getElementById('db-records').textContent = dbRecords;
|
| 932 |
+
}
|
| 933 |
+
|
| 934 |
+
updateAgentsDisplay() {
|
| 935 |
+
const container = document.getElementById('agents-container');
|
| 936 |
+
container.innerHTML = '';
|
| 937 |
+
|
| 938 |
+
Array.from(this.agents.values()).forEach(agent => {
|
| 939 |
+
const agentCard = document.createElement('div');
|
| 940 |
+
agentCard.className = 'agent-card';
|
| 941 |
+
agentCard.innerHTML = `
|
| 942 |
+
<div class="agent-name">${agent.name}</div>
|
| 943 |
+
<div class="agent-status status-${agent.status}">${agent.status}</div>
|
| 944 |
+
<div style="font-size: 12px; color: #666;">
|
| 945 |
+
<div>Role: ${agent.role}</div>
|
| 946 |
+
<div>Tasks: ${agent.tasksCompleted || 0}</div>
|
| 947 |
+
</div>
|
| 948 |
+
<button class="btn btn-danger" onclick="agentSystem.deleteAgent('${agent.id}')" style="margin-top: 10px; padding: 5px 10px; font-size: 12px;">Remove</button>
|
| 949 |
+
`;
|
| 950 |
+
container.appendChild(agentCard);
|
| 951 |
+
});
|
| 952 |
+
|
| 953 |
+
// Update agent dropdown
|
| 954 |
+
const agentSelect = document.getElementById('task-agent');
|
| 955 |
+
agentSelect.innerHTML = '<option value="">Auto-assign</option>';
|
| 956 |
+
Array.from(this.agents.values()).forEach(agent => {
|
| 957 |
+
const option = document.createElement('option');
|
| 958 |
+
option.value = agent.id;
|
| 959 |
+
option.textContent = agent.name;
|
| 960 |
+
agentSelect.appendChild(option);
|
| 961 |
+
});
|
| 962 |
+
}
|
| 963 |
+
|
| 964 |
+
updateTasksList() {
|
| 965 |
+
const container = document.getElementById('task-list');
|
| 966 |
+
container.innerHTML = '';
|
| 967 |
+
|
| 968 |
+
// Sort tasks by creation date (newest first)
|
| 969 |
+
const sortedTasks = [...this.tasks].sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
| 970 |
+
|
| 971 |
+
sortedTasks.slice(0, 20).forEach(task => { // Show only last 20 tasks
|
| 972 |
+
const taskItem = document.createElement('div');
|
| 973 |
+
taskItem.className = 'task-item';
|
| 974 |
+
|
| 975 |
+
const assignedAgent = task.assignedAgent ?
|
| 976 |
+
this.agents.get(task.assignedAgent)?.name || 'Unknown Agent' :
|
| 977 |
+
'Auto-assigned';
|
| 978 |
+
|
| 979 |
+
taskItem.innerHTML = `
|
| 980 |
+
<div class="task-header">
|
| 981 |
+
<span class="task-id">${task.id}</span>
|
| 982 |
+
<span class="task-status status-${task.status}">${task.status}</span>
|
| 983 |
+
</div>
|
| 984 |
+
<div style="margin-bottom: 8px;">
|
| 985 |
+
<strong>Type:</strong> ${task.type} |
|
| 986 |
+
<strong>Priority:</strong> ${task.priority} |
|
| 987 |
+
<strong>Agent:</strong> ${assignedAgent}
|
| 988 |
+
</div>
|
| 989 |
+
<div style="margin-bottom: 8px;">
|
| 990 |
+
<strong>Description:</strong> ${task.description}
|
| 991 |
+
</div>
|
| 992 |
+
<div style="font-size: 12px; color: #666;">
|
| 993 |
+
<div>Created: ${task.createdAt.toLocaleString()}</div>
|
| 994 |
+
${task.completedAt ? `<div>Completed: ${task.completedAt.toLocaleString()}</div>` : ''}
|
| 995 |
+
${task.error ? `<div style="color: #c53030;">Error: ${task.error}</div>` : ''}
|
| 996 |
+
</div>
|
| 997 |
+
<div style="margin-top: 10px;">
|
| 998 |
+
<button class="btn btn-danger" onclick="agentSystem.deleteTask('${task.id}')" style="padding: 5px 10px; font-size: 12px;">Delete</button>
|
| 999 |
+
${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>` : ''}
|
| 1000 |
+
</div>
|
| 1001 |
+
`;
|
| 1002 |
+
container.appendChild(taskItem);
|
| 1003 |
+
});
|
| 1004 |
+
}
|
| 1005 |
+
|
| 1006 |
+
updateDatabaseTable() {
|
| 1007 |
+
const tbody = document.getElementById('data-table-body');
|
| 1008 |
+
tbody.innerHTML = '';
|
| 1009 |
+
|
| 1010 |
+
// Get recent records from all tables
|
| 1011 |
+
const allRecords = [];
|
| 1012 |
+
Object.entries(this.db.tables).forEach(([tableName, table]) => {
|
| 1013 |
+
const records = this.db.getAll(table);
|
| 1014 |
+
records.forEach(record => {
|
| 1015 |
+
allRecords.push({
|
| 1016 |
+
...record,
|
| 1017 |
+
table: tableName
|
| 1018 |
+
});
|
| 1019 |
+
});
|
| 1020 |
+
});
|
| 1021 |
+
|
| 1022 |
+
// Sort by creation date and take last 50
|
| 1023 |
+
allRecords.sort((a, b) => new Date(b.created_at || b.timestamp) - new Date(a.created_at || a.timestamp));
|
| 1024 |
+
allRecords.slice(0, 50).forEach(record => {
|
| 1025 |
+
const row = document.createElement('tr');
|
| 1026 |
+
row.innerHTML = `
|
| 1027 |
+
<td>${record.id}</td>
|
| 1028 |
+
<td>${record.table}</td>
|
| 1029 |
+
<td>${record.status || record.level || 'N/A'}</td>
|
| 1030 |
+
<td>${new Date(record.created_at || record.timestamp).toLocaleString()}</td>
|
| 1031 |
+
<td>${record.updated_at ? new Date(record.updated_at).toLocaleString() : 'N/A'}</td>
|
| 1032 |
+
<td>
|
| 1033 |
+
<button class="btn-danger" onclick="agentSystem.deleteRecord('${record.table}', '${record.id}')" style="padding: 3px 6px; font-size: 11px;">Delete</button>
|
| 1034 |
+
</td>
|
| 1035 |
+
`;
|
| 1036 |
+
tbody.appendChild(row);
|
| 1037 |
+
});
|
| 1038 |
+
}
|
| 1039 |
+
|
| 1040 |
+
updateLogsUI() {
|
| 1041 |
+
const container = document.getElementById('logs-container');
|
| 1042 |
+
container.innerHTML = '';
|
| 1043 |
+
|
| 1044 |
+
this.logs.slice(-20).forEach(log => {
|
| 1045 |
+
const logEntry = document.createElement('div');
|
| 1046 |
+
logEntry.className = 'log-entry';
|
| 1047 |
+
logEntry.innerHTML = `
|
| 1048 |
+
<span class="log-timestamp">[${log.timestamp.toLocaleTimeString()}]</span>
|
| 1049 |
+
<span class="log-level-${log.level}">[${log.level.toUpperCase()}]</span>
|
| 1050 |
+
<span>${log.message}</span>
|
| 1051 |
+
`;
|
| 1052 |
+
container.appendChild(logEntry);
|
| 1053 |
+
});
|
| 1054 |
+
|
| 1055 |
+
// Auto-scroll to bottom
|
| 1056 |
+
container.scrollTop = container.scrollHeight;
|
| 1057 |
+
}
|
| 1058 |
+
|
| 1059 |
+
async deleteAgent(agentId) {
|
| 1060 |
+
if (confirm('Are you sure you want to delete this agent?')) {
|
| 1061 |
+
this.agents.delete(agentId);
|
| 1062 |
+
await this.db.delete(this.db.tables.agents, agentId);
|
| 1063 |
+
this.log(`Deleted agent: ${agentId}`, 'warning');
|
| 1064 |
+
this.updateUI();
|
| 1065 |
+
}
|
| 1066 |
+
}
|
| 1067 |
+
|
| 1068 |
+
async deleteTask(taskId) {
|
| 1069 |
+
if (confirm('Are you sure you want to delete this task?')) {
|
| 1070 |
+
this.tasks = this.tasks.filter(t => t.id !== taskId);
|
| 1071 |
+
await this.db.delete(this.db.tables.tasks, taskId);
|
| 1072 |
+
this.log(`Deleted task: ${taskId}`, 'warning');
|
| 1073 |
+
this.updateUI();
|
| 1074 |
+
}
|
| 1075 |
+
}
|
| 1076 |
+
|
| 1077 |
+
async retryTask(taskId) {
|
| 1078 |
+
const task = this.tasks.find(t => t.id === taskId);
|
| 1079 |
+
if (task) {
|
| 1080 |
+
task.status = 'queued';
|
| 1081 |
+
task.retries = 0;
|
| 1082 |
+
task.error = null;
|
| 1083 |
+
await this.db.update(this.db.tables.tasks, taskId, {
|
| 1084 |
+
status: 'queued',
|
| 1085 |
+
error: null
|
| 1086 |
+
});
|
| 1087 |
+
this.log(`Retrying task: ${taskId}`, 'info');
|
| 1088 |
+
this.updateUI();
|
| 1089 |
+
setTimeout(() => this.processNextTask(), 100);
|
| 1090 |
+
}
|
| 1091 |
+
}
|
| 1092 |
+
|
| 1093 |
+
async deleteRecord(table, id) {
|
| 1094 |
+
if (confirm('Are you sure you want to delete this record?')) {
|
| 1095 |
+
await this.db.delete(table, id);
|
| 1096 |
+
this.log(`Deleted record from ${table}: ${id}`, 'warning');
|
| 1097 |
+
this.updateUI();
|
| 1098 |
+
}
|
| 1099 |
+
}
|
| 1100 |
+
}
|
| 1101 |
+
|
| 1102 |
+
// Global system instance
|
| 1103 |
+
let agentSystem;
|
| 1104 |
+
|
| 1105 |
+
// UI Event Handlers - FIXED: Prevent form submission redirect
|
| 1106 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1107 |
+
// Initialize the system
|
| 1108 |
+
agentSystem = new EnhancedAgentSystem();
|
| 1109 |
+
|
| 1110 |
+
// Task form submission
|
| 1111 |
+
document.getElementById('task-form').addEventListener('submit', function(e) {
|
| 1112 |
+
e.preventDefault(); // FIXED: This prevents the page redirect
|
| 1113 |
+
|
| 1114 |
+
const taskData = {
|
| 1115 |
+
type: document.getElementById('task-type').value,
|
| 1116 |
+
description: document.getElementById('task-description').value,
|
| 1117 |
+
priority: document.getElementById('task-priority').value,
|
| 1118 |
+
assignedAgent: document.getElementById('task-agent').value || null,
|
| 1119 |
+
parameters: {}
|
| 1120 |
+
};
|
| 1121 |
+
|
| 1122 |
+
if (taskData.description.trim()) {
|
| 1123 |
+
agentSystem.createTask(taskData);
|
| 1124 |
+
|
| 1125 |
+
// Reset form
|
| 1126 |
+
document.getElementById('task-form').reset();
|
| 1127 |
+
} else {
|
| 1128 |
+
alert('Please enter a task description');
|
| 1129 |
+
}
|
| 1130 |
+
});
|
| 1131 |
+
});
|
| 1132 |
+
|
| 1133 |
+
|