← back to Designer Wallcoverings
DW-Agents/dw-agents/master-hub-chat.js
651 lines
const express = require('express');
const cors = require('cors');
const path = require('path');
const fs = require('fs');
const app = express();
const PORT = 9893;
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.static('public'));
// Read agent configurations
const getAgentConfigs = () => {
const agents = [
{ name: 'Purchasing Office', port: 9880, icon: '🛒', description: 'Manages purchase orders and vendor relations' },
{ name: 'Marketing Agent', port: 9881, icon: '📢', description: 'Handles marketing campaigns and social media' },
{ name: 'Accounting Agent', port: 9882, icon: '💰', description: 'Financial tracking and reporting' },
{ name: 'Trend Research', port: 9883, icon: '📊', description: 'Analyzes market trends and patterns' },
{ name: 'Zendesk Chat', port: 9884, icon: '💬', description: 'Customer support integration' },
{ name: 'Digital Samples', port: 9879, icon: '🎨', description: 'Digital sample management' },
{ name: 'Legal Team', port: 9878, icon: '⚖️', description: 'Legal document processing' },
{ name: 'Needs Attention', port: 9886, icon: '⚠️', description: 'Priority items requiring attention' },
{ name: 'Parallel Processes', port: 9887, icon: '🔄', description: 'Concurrent task management' },
{ name: 'Server Uptime', port: 9888, icon: '🖥️', description: 'Monitor server health' },
{ name: 'Task Orchestrator', port: 9900, icon: '🎯', description: 'Coordinate agent tasks' },
{ name: 'Completed Tasks', port: 9889, icon: '✅', description: 'Track finished work' },
{ name: "Today's Highlights", port: 9885, icon: '⭐', description: 'Daily summary and highlights' },
{ name: 'New Client Signup', port: 9890, icon: '👤', description: 'Onboard new clients' },
{ name: 'In Parallel', port: 9891, icon: '⚡', description: 'Simultaneous operations' },
{ name: 'Skills Manager', port: 9894, icon: '🧠', description: 'AI capabilities registry' }
];
return agents;
};
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
service: 'Master Hub Chat',
port: PORT,
uptime: process.uptime(),
timestamp: new Date().toISOString()
});
});
// Get all agents
app.get('/api/agents', (req, res) => {
const agents = getAgentConfigs();
res.json(agents);
});
// Main dashboard HTML
app.get('/', (req, res) => {
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Master Hub - DW Agents</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
.header {
text-align: center;
color: white;
margin-bottom: 40px;
padding: 30px;
background: rgba(255,255,255,0.1);
border-radius: 20px;
backdrop-filter: blur(10px);
}
h1 {
font-size: 3em;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.subtitle {
font-size: 1.2em;
opacity: 0.95;
}
.agents-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 25px;
margin-bottom: 40px;
}
.agent-card {
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.agent-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0,0,0,0.3);
}
.agent-header {
display: flex;
align-items: center;
gap: 15px;
margin-bottom: 15px;
}
.agent-icon {
font-size: 2.5em;
min-width: 60px;
text-align: center;
}
.agent-info {
flex: 1;
}
.agent-name {
font-size: 1.3em;
font-weight: 700;
color: #333;
margin-bottom: 5px;
}
.agent-port {
color: #666;
font-size: 0.9em;
font-family: monospace;
background: #f0f0f0;
padding: 2px 8px;
border-radius: 4px;
display: inline-block;
}
.agent-description {
color: #555;
line-height: 1.5;
margin-bottom: 20px;
min-height: 40px;
}
.agent-actions {
display: flex;
gap: 10px;
}
.btn {
flex: 1;
padding: 12px 20px;
border: none;
border-radius: 8px;
font-size: 1em;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
text-decoration: none;
text-align: center;
display: inline-block;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: scale(1.05);
box-shadow: 0 5px 15px rgba(102,126,234,0.4);
}
.btn-secondary {
background: #f0f0f0;
color: #333;
}
.btn-secondary:hover {
background: #e0e0e0;
}
.status-indicator {
position: absolute;
top: 15px;
right: 15px;
width: 12px;
height: 12px;
border-radius: 50%;
background: #4CAF50;
box-shadow: 0 0 10px #4CAF50;
animation: pulse 2s infinite;
}
.status-indicator.offline {
background: #f44336;
box-shadow: 0 0 10px #f44336;
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
100% { transform: scale(1); opacity: 1; }
}
.footer {
text-align: center;
color: white;
padding: 20px;
background: rgba(255,255,255,0.1);
border-radius: 15px;
backdrop-filter: blur(10px);
}
/* Chat Modal */
.chat-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
z-index: 10000;
justify-content: center;
align-items: center;
}
.chat-container {
width: 500px;
height: 700px;
background: white;
border-radius: 20px;
display: flex;
flex-direction: column;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.chat-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.chat-title {
font-size: 1.3em;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.chat-close {
background: rgba(255,255,255,0.2);
border: none;
color: white;
width: 36px;
height: 36px;
border-radius: 50%;
cursor: pointer;
font-size: 1.5em;
display: flex;
align-items: center;
justify-content: center;
}
.chat-close:hover {
background: rgba(255,255,255,0.3);
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 20px;
background: #f8f9fa;
}
.chat-input-container {
padding: 20px;
border-top: 1px solid #e0e0e0;
background: white;
}
.chat-input-wrapper {
display: flex;
gap: 10px;
}
.chat-input {
flex: 1;
padding: 12px;
border: 2px solid #e0e0e0;
border-radius: 25px;
font-size: 1em;
outline: none;
}
.chat-input:focus {
border-color: #667eea;
}
.chat-send {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 25px;
cursor: pointer;
font-weight: 600;
}
.chat-send:hover {
transform: scale(1.05);
}
.message {
margin-bottom: 15px;
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.message.user {
text-align: right;
}
.message-content {
display: inline-block;
padding: 12px 16px;
border-radius: 12px;
max-width: 80%;
word-wrap: break-word;
}
.message.user .message-content {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.message.assistant .message-content {
background: white;
color: #333;
border: 1px solid #e0e0e0;
}
.typing-indicator {
display: none;
padding: 12px 16px;
background: white;
border: 1px solid #e0e0e0;
border-radius: 12px;
display: inline-block;
margin-bottom: 15px;
}
.typing-indicator span {
display: inline-block;
width: 8px;
height: 8px;
background: #666;
border-radius: 50%;
margin: 0 2px;
animation: typing 1.4s infinite;
}
.typing-indicator span:nth-child(2) {
animation-delay: 0.2s;
}
.typing-indicator span:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes typing {
0%, 60%, 100% {
transform: translateY(0);
}
30% {
transform: translateY(-10px);
}
}
@media (max-width: 768px) {
.agents-grid {
grid-template-columns: 1fr;
}
.chat-container {
width: 90%;
height: 80%;
margin: 20px;
}
h1 {
font-size: 2em;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🚀 Master Hub</h1>
<div class="subtitle">DW Agents Central Command</div>
</div>
<div class="agents-grid" id="agentsGrid">
<!-- Agent cards will be loaded here -->
</div>
<div class="footer">
<p>© 2024 Designer Wallcoverings - AI Agent Network</p>
<p style="margin-top: 10px; opacity: 0.8;">Powered by Claude AI</p>
</div>
</div>
<!-- Chat Modal -->
<div class="chat-modal" id="chatModal">
<div class="chat-container">
<div class="chat-header">
<div class="chat-title">
<span id="chatAgentIcon">💬</span>
<span id="chatAgentName">Agent Assistant</span>
</div>
<button class="chat-close" onclick="closeChat()">×</button>
</div>
<div class="chat-messages" id="chatMessages">
<div style="text-align: center; color: #888; padding: 20px;">
👋 Hi! How can I help you today?
</div>
</div>
<div class="chat-input-container">
<div class="chat-input-wrapper">
<input
type="text"
class="chat-input"
id="chatInput"
placeholder="Type your message..."
onkeypress="if(event.key==='Enter') sendMessage()"
/>
<button class="chat-send" onclick="sendMessage()">Send</button>
</div>
</div>
</div>
</div>
<script>
let currentAgent = null;
let chatHistory = [];
// Load agents on page load
async function loadAgents() {
try {
const response = await fetch('/api/agents');
const agents = await response.json();
const grid = document.getElementById('agentsGrid');
grid.innerHTML = agents.map(agent => \`
<div class="agent-card">
<div class="status-indicator" id="status-\${agent.port}"></div>
<div class="agent-header">
<div class="agent-icon">\${agent.icon}</div>
<div class="agent-info">
<div class="agent-name">\${agent.name}</div>
<div class="agent-port">Port: \${agent.port}</div>
</div>
</div>
<div class="agent-description">\${agent.description}</div>
<div class="agent-actions">
<a href="http://45.61.58.125:\${agent.port}" target="_blank" class="btn btn-secondary">
🔗 Open
</a>
<button class="btn btn-primary" onclick='openChat(\${JSON.stringify(agent)})'>
💬 Chat
</button>
</div>
</div>
\`).join('');
// Check agent status
agents.forEach(agent => {
checkAgentStatus(agent.port);
});
} catch (error) {
console.error('Failed to load agents:', error);
}
}
// Check if agent is online
async function checkAgentStatus(port) {
try {
const response = await fetch(\`http://45.61.58.125:\${port}/health\`, {
mode: 'no-cors',
timeout: 2000
});
document.getElementById(\`status-\${port}\`).classList.remove('offline');
} catch (error) {
document.getElementById(\`status-\${port}\`).classList.add('offline');
}
}
// Open chat modal
function openChat(agent) {
currentAgent = agent;
chatHistory = [];
document.getElementById('chatAgentIcon').textContent = agent.icon;
document.getElementById('chatAgentName').textContent = agent.name;
document.getElementById('chatModal').style.display = 'flex';
document.getElementById('chatMessages').innerHTML = \`
<div style="text-align: center; color: #888; padding: 20px;">
👋 Hi! I'm the AI assistant for \${agent.name}. How can I help you?
</div>
\`;
document.getElementById('chatInput').focus();
}
// Close chat modal
function closeChat() {
document.getElementById('chatModal').style.display = 'none';
currentAgent = null;
chatHistory = [];
}
// Send message
async function sendMessage() {
const input = document.getElementById('chatInput');
const message = input.value.trim();
if (!message || !currentAgent) return;
// Add user message
addMessage('user', message);
input.value = '';
// Show typing indicator
showTyping();
// Simulate AI response (in production, this would call the agent's API)
setTimeout(() => {
hideTyping();
const response = generateAgentResponse(currentAgent, message);
addMessage('assistant', response);
}, 1000);
}
// Add message to chat
function addMessage(role, content) {
const messagesDiv = document.getElementById('chatMessages');
const messageDiv = document.createElement('div');
messageDiv.className = \`message \${role}\`;
messageDiv.innerHTML = \`<div class="message-content">\${content}</div>\`;
messagesDiv.appendChild(messageDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
chatHistory.push({ role, content });
}
// Show typing indicator
function showTyping() {
const messagesDiv = document.getElementById('chatMessages');
const typingDiv = document.createElement('div');
typingDiv.className = 'typing-indicator';
typingDiv.id = 'typingIndicator';
typingDiv.style.display = 'inline-block';
typingDiv.innerHTML = '<span></span><span></span><span></span>';
messagesDiv.appendChild(typingDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
// Hide typing indicator
function hideTyping() {
const indicator = document.getElementById('typingIndicator');
if (indicator) indicator.remove();
}
// Generate agent-specific response
function generateAgentResponse(agent, message) {
const responses = {
'Purchasing Office': 'I can help you with purchase orders, vendor management, and procurement processes.',
'Marketing Agent': 'I handle marketing campaigns, social media strategies, and brand management.',
'Accounting Agent': 'I manage financial reports, invoices, and budget tracking.',
'Trend Research': 'I analyze market trends, consumer behavior, and industry patterns.',
'Skills Manager': 'I manage the AI capabilities registry and track skill usage across all agents.',
'Needs Attention': 'I track priority items and urgent tasks that require immediate attention.',
'Task Orchestrator': 'I coordinate tasks between agents and manage workflow automation.'
};
return responses[agent.name] || \`I'm the \${agent.name} assistant. I can help you with tasks related to \${agent.description.toLowerCase()}.\`;
}
// Initialize on load
loadAgents();
// Refresh status every 30 seconds
setInterval(loadAgents, 30000);
// Close modal on outside click
document.getElementById('chatModal').addEventListener('click', (e) => {
if (e.target.id === 'chatModal') {
closeChat();
}
});
</script>
</body>
</html>
`;
res.send(html);
});
// Start server
app.listen(PORT, () => {
console.log(`✅ Master Hub Chat running on http://45.61.58.125:${PORT}`);
console.log(`📊 Dashboard: http://45.61.58.125:${PORT}/`);
console.log(`❤️ Health check: http://45.61.58.125:${PORT}/health`);
});