← back to Designer Wallcoverings

DW-Agents/dw-agents/agent-ui-manager/ui-manager-agent.ts.backup-auth-1762615744

982 lines

/**
 * DW-Agents: UI Manager Agent
 *
 * Central UI/UX management system:
 * - Unified design system and branding
 * - Agent directory with live links
 * - Theme customization and distribution
 * - Style consistency across all agents
 * - Central navigation hub
 *
 * Port: 7240
 */

import express, { Request, Response } from 'express';
import session from 'express-session';
import * as fs from 'fs';
import * as path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';
import { requireAuth as ssoAuth, handleLogin, SSO_TOKEN_NAME, SSO_TOKEN_VALUE } from '../shared-auth';
import cookieParser from 'cookie-parser';

const execAsync = promisify(exec);

import Anthropic from '@anthropic-ai/sdk';

// Import universal UI components
const { getUniversalHeader } = require('../shared-ui-components.js');

const app = express();
const PORT = 7240;

// Anthropic Claude
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '';
const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });

// Design system
const DESIGN_SYSTEM = {
  colors: {
    primary: '#667eea',
    secondary: '#764ba2',
    accent: '#f093fb',
    success: '#27ae60',
    warning: '#f39c12',
    error: '#e74c3c',
    dark: '#2c3e50',
    light: '#ecf0f1',
  },
  fonts: {
    primary: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
    mono: "'Monaco', 'Courier New', monospace",
  },
  spacing: {
    base: '20px',
    small: '10px',
    large: '40px',
  },
  borderRadius: {
    small: '5px',
    medium: '8px',
    large: '10px',
  },
  shadows: {
    small: '0 2px 5px rgba(0,0,0,0.05)',
    medium: '0 2px 10px rgba(0,0,0,0.1)',
    large: '0 10px 40px rgba(0,0,0,0.3)',
  },
};

// Agent registry
const AGENTS = [
  { name: 'Task Orchestrator', port: 9900, path: '/', icon: '🎯', category: 'Core', description: 'Master task coordination' },
  { name: 'Shopify Store', port: 7238, path: '/', icon: '🛍️', category: 'E-Commerce', description: 'Store management' },
  { name: 'Log Monitor', port: 7239, path: '/', icon: '📋', category: 'Monitoring', description: 'Log analysis & error detection' },
  { name: 'Purchasing Office', port: 9880, path: '/', icon: '📦', category: 'Operations', description: 'Office supplies ordering' },
  { name: 'Accounting', port: 9882, path: '/', icon: '💰', category: 'Finance', description: 'Financial management' },
  { name: 'Marketing', port: 9881, path: '/', icon: '📢', category: 'Marketing', description: 'Campaign management' },
  { name: 'Zendesk Chat', port: 9884, path: '/', icon: '💬', category: 'Customer', description: 'Customer support' },
  { name: 'Digital Samples', port: 9879, path: '/', icon: '🎨', category: 'Customer', description: 'Sample management' },
  { name: 'Trend Research', port: 9883, path: '/', icon: '📊', category: 'Analytics', description: 'Market analysis' },
  { name: 'Legal Team', port: 9878, path: '/', icon: '⚖️', category: 'Legal', description: 'Legal & compliance' },
  { name: 'Master Hub', port: 9712, path: '/', icon: '🏠', category: 'Core', description: 'Central dashboard' },
  { name: 'UI Manager', port: 7240, path: '/', icon: '🎨', category: 'System', description: 'UI/UX management' },
];

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());

declare module 'express-session' {
  interface SessionData {
    authenticated: boolean;
    currentTheme: any;
    chatHistory: Array<{ role: 'user' | 'assistant', content: string }>;
  }
}

app.use(
  session({
    secret: 'dw-agents-ui-manager-2025',
    resave: false,
    saveUninitialized: true,
    rolling: true,
    cookie: {
      secure: false,
      httpOnly: true,
      maxAge: 7 * 24 * 60 * 60 * 1000,
    },
  })
);

// Authentication
app.post('/login', handleLogin);

const requireAuth = (req: Request, res: Response, next: any) => {
  // TEMPORARY: Disable auth for 4 hours (until 4 hours from server restart)
  const serverStartTime = Date.now();
  const fourHoursInMs = 4 * 60 * 60 * 1000;
  if (Date.now() - serverStartTime < fourHoursInMs) {
    return next();
  }

  if (req.cookies[SSO_TOKEN_NAME] === SSO_TOKEN_VALUE || req.session.authenticated) {
    next();
  } else {
    res.redirect('/login');
  }
};

app.get('/login', (req: Request, res: Response) => {
  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>UI Manager - Login</title>
      <style>
        body {
          font-family: ${DESIGN_SYSTEM.fonts.primary};
          background: linear-gradient(135deg, ${DESIGN_SYSTEM.colors.primary} 0%, ${DESIGN_SYSTEM.colors.secondary} 100%);
          display: flex;
          justify-content: center;
          align-items: center;
          height: 100vh;
          margin: 0;
        }
        .login-box {
          background: white;
          padding: 40px;
          border-radius: ${DESIGN_SYSTEM.borderRadius.large};
          box-shadow: ${DESIGN_SYSTEM.shadows.large};
          width: 300px;
        }
        h2 { margin-top: 0; color: ${DESIGN_SYSTEM.colors.dark}; }
        input {
          width: 100%;
          padding: 12px;
          margin: 10px 0;
          border: 1px solid #ddd;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          box-sizing: border-box;
        }
        button {
          width: 100%;
          padding: 12px;
          background: ${DESIGN_SYSTEM.colors.primary};
          color: white;
          border: none;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          cursor: pointer;
          font-size: 16px;
        }
        button:hover { background: ${DESIGN_SYSTEM.colors.secondary}; }
      </style>
    </head>
    <body>
      <div class="login-box">
        <h2>🎨 UI Manager</h2>
        <form method="POST" action="/login">
          <input type="password" name="password" placeholder="Password" required autofocus />
          <button type="submit">Login</button>
        </form>
      </div>
    </body>
    </html>
  `);
});

// Check agent status
async function checkAgentStatus(port: number): Promise<boolean> {
  try {
    // Try /health first, then fallback to root / if health doesn't exist
    const { stdout } = await execAsync(`curl -s -o /dev/null -w "%{http_code}" --max-time 2 http://localhost:${port}/health 2>/dev/null || curl -s -o /dev/null -w "%{http_code}" --max-time 2 http://localhost:${port}/ 2>/dev/null || echo "000"`);
    const statusCode = stdout.trim();
    return statusCode === '200' || statusCode.startsWith('2') || statusCode === '404' || statusCode === '302';
  } catch (error) {
    return false;
  }
}

// Main dashboard
app.get('/', requireAuth, async (req: Request, res: Response) => {
  // Check status of all agents
  const agentStatuses = await Promise.all(
    AGENTS.map(async (agent) => ({
      ...agent,
      online: await checkAgentStatus(agent.port),
    }))
  );

  const categories = [...new Set(AGENTS.map(a => a.category))];

  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>UI Manager - Agent Directory</title>
      <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
          font-family: ${DESIGN_SYSTEM.fonts.primary};
          background: ${DESIGN_SYSTEM.colors.light};
          padding: 10px;
        }
        .header {
          background: linear-gradient(135deg, ${DESIGN_SYSTEM.colors.primary} 0%, ${DESIGN_SYSTEM.colors.secondary} 100%);
          color: white;
          padding: ${DESIGN_SYSTEM.spacing.base};
          box-shadow: ${DESIGN_SYSTEM.shadows.medium};
          border-radius: 10px;
          margin-bottom: 20px;
        }
        .header h1 { font-size: 28px; margin-bottom: 10px; }
        .header p { font-size: 14px; opacity: 0.9; }
        .nav {
          background: white;
          padding: 15px ${DESIGN_SYSTEM.spacing.base};
          box-shadow: ${DESIGN_SYSTEM.shadows.small};
          display: flex;
          gap: 20px;
          overflow-x: auto;
        }
        .nav-item {
          padding: 10px 20px;
          background: ${DESIGN_SYSTEM.colors.light};
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          cursor: pointer;
          white-space: nowrap;
          transition: all 0.3s;
        }
        .nav-item:hover { background: ${DESIGN_SYSTEM.colors.primary}; color: white; }
        .nav-item.active { background: ${DESIGN_SYSTEM.colors.primary}; color: white; }
        .content {
          padding: 15px;
          max-width: 1600px;
          margin: 0 auto;
        }
        .stats {
          display: grid;
          grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
          gap: ${DESIGN_SYSTEM.spacing.base};
          margin-bottom: ${DESIGN_SYSTEM.spacing.base};
        }
        .stat-card {
          background: white;
          padding: ${DESIGN_SYSTEM.spacing.base};
          border-radius: ${DESIGN_SYSTEM.borderRadius.medium};
          box-shadow: ${DESIGN_SYSTEM.shadows.medium};
          text-align: center;
        }
        .stat-card h3 { font-size: 14px; color: #666; margin-bottom: 10px; }
        .stat-card p { font-size: 32px; font-weight: bold; color: ${DESIGN_SYSTEM.colors.primary}; }
        .agent-grid {
          display: grid;
          grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
          gap: 12px;
        }
        .agent-card {
          background: white;
          border-radius: ${DESIGN_SYSTEM.borderRadius.medium};
          box-shadow: ${DESIGN_SYSTEM.shadows.medium};
          overflow: hidden;
          transition: transform 0.3s, box-shadow 0.3s;
          cursor: pointer;
        }
        .agent-card:hover {
          transform: translateY(-5px);
          box-shadow: 0 10px 30px rgba(0,0,0,0.2);
        }
        .agent-header {
          background: linear-gradient(135deg, ${DESIGN_SYSTEM.colors.primary} 0%, ${DESIGN_SYSTEM.colors.secondary} 100%);
          color: white;
          padding: 12px 15px;
          display: flex;
          align-items: center;
          gap: 10px;
        }
        .agent-icon {
          font-size: 32px;
        }
        .agent-info h3 { font-size: 18px; margin-bottom: 5px; }
        .agent-info p { font-size: 12px; opacity: 0.9; }
        .agent-body {
          padding: 12px 15px;
        }
        .agent-body p {
          color: #666;
          margin-bottom: 15px;
          font-size: 14px;
        }
        .agent-footer {
          display: flex;
          gap: 8px;
          padding: 0 15px 12px 15px;
        }
        .btn {
          flex: 1;
          padding: 8px;
          border: none;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          cursor: pointer;
          font-size: 12px;
          transition: all 0.3s;
          text-align: center;
          text-decoration: none;
          display: inline-block;
          font-weight: 600;
        }
        .btn-primary {
          background: ${DESIGN_SYSTEM.colors.primary};
          color: white;
        }
        .btn-primary:hover { background: ${DESIGN_SYSTEM.colors.secondary}; }
        .btn-secondary {
          background: ${DESIGN_SYSTEM.colors.light};
          color: ${DESIGN_SYSTEM.colors.dark};
        }
        .btn-secondary:hover { background: #ddd; }
        .status-badge {
          display: inline-block;
          padding: 4px 12px;
          border-radius: 12px;
          font-size: 11px;
          font-weight: bold;
          margin-left: auto;
        }
        .status-online {
          background: ${DESIGN_SYSTEM.colors.success};
          color: white;
        }
        .status-offline {
          background: ${DESIGN_SYSTEM.colors.error};
          color: white;
        }
        .category-section {
          margin-bottom: 30px;
        }
        .category-title {
          font-size: 20px;
          font-weight: 600;
          color: ${DESIGN_SYSTEM.colors.dark};
          margin-bottom: 15px;
          padding-bottom: 10px;
          border-bottom: 2px solid ${DESIGN_SYSTEM.colors.primary};
        }
        .design-system {
          background: white;
          padding: ${DESIGN_SYSTEM.spacing.base};
          border-radius: ${DESIGN_SYSTEM.borderRadius.medium};
          box-shadow: ${DESIGN_SYSTEM.shadows.medium};
          margin-bottom: ${DESIGN_SYSTEM.spacing.base};
        }
        .color-palette {
          display: flex;
          gap: 10px;
          flex-wrap: wrap;
        }
        .color-swatch {
          width: 80px;
          height: 80px;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          display: flex;
          align-items: flex-end;
          padding: 8px;
          color: white;
          font-size: 11px;
          font-weight: bold;
          text-shadow: 0 1px 2px rgba(0,0,0,0.3);
        }
        .chat-container {
          background: white;
          padding: ${DESIGN_SYSTEM.spacing.base};
          border-radius: ${DESIGN_SYSTEM.borderRadius.medium};
          box-shadow: ${DESIGN_SYSTEM.shadows.medium};
          height: calc(100vh - 250px);
          display: flex;
          flex-direction: column;
        }
        .chat-messages {
          flex: 1;
          overflow-y: auto;
          padding: ${DESIGN_SYSTEM.spacing.base};
          background: #fafafa;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          margin-bottom: ${DESIGN_SYSTEM.spacing.base};
        }
        .chat-message {
          margin-bottom: 15px;
          padding: 12px;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          max-width: 80%;
        }
        .chat-message.user {
          background: ${DESIGN_SYSTEM.colors.primary};
          color: white;
          margin-left: auto;
          text-align: right;
        }
        .chat-message.assistant {
          background: white;
          box-shadow: ${DESIGN_SYSTEM.shadows.small};
        }
        .chat-input-area {
          display: flex;
          gap: 10px;
        }
        .chat-input {
          flex: 1;
          padding: 12px;
          border: 2px solid ${DESIGN_SYSTEM.colors.primary};
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          font-size: 14px;
        }
        .chat-send {
          padding: 12px 30px;
          background: ${DESIGN_SYSTEM.colors.primary};
          color: white;
          border: none;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          cursor: pointer;
          font-weight: 600;
        }
        .chat-send:hover {
          background: ${DESIGN_SYSTEM.colors.secondary};
        }
        .chat-info {
          background: ${DESIGN_SYSTEM.colors.light};
          padding: 15px;
          border-radius: ${DESIGN_SYSTEM.borderRadius.small};
          margin-bottom: 15px;
          font-size: 14px;
        }
      </style>
    </head>
    <body>
      ${getUniversalHeader('UI Manager', PORT, 5)}

      <div class="header" style="margin-top: 20px;">
        <h1>🎨 UI Manager - Agent Directory</h1>
        <p>Central hub for all DW-Agents with unified design system</p>
      </div>

      <div class="nav">
        <div class="nav-item active" onclick="showView('agents')">Agent Directory</div>
        <div class="nav-item" onclick="showView('preview')">🎬 Live Preview</div>
        <div class="nav-item" onclick="showView('design')">Design System</div>
        <div class="nav-item" onclick="showView('functions')">Functions</div>
        <div class="nav-item" onclick="showView('chat')">Universal Chat</div>
      </div>

      <div class="content">
        <div id="agents-view">
          <div class="stats">
            <div class="stat-card">
              <h3>Total Agents</h3>
              <p>${AGENTS.length}</p>
            </div>
            <div class="stat-card">
              <h3>Online</h3>
              <p>${agentStatuses.filter(a => a.online).length}</p>
            </div>
            <div class="stat-card">
              <h3>Offline</h3>
              <p>${agentStatuses.filter(a => !a.online).length}</p>
            </div>
            <div class="stat-card">
              <h3>Categories</h3>
              <p>${categories.length}</p>
            </div>
          </div>

          ${categories.map(category => `
            <div class="category-section">
              <h2 class="category-title">${category}</h2>
              <div class="agent-grid">
                ${agentStatuses.filter(a => a.category === category).map(agent => `
                  <div class="agent-card">
                    <div class="agent-header">
                      <div class="agent-icon">${agent.icon}</div>
                      <div class="agent-info">
                        <h3>${agent.name}</h3>
                        <p>Port ${agent.port}</p>
                      </div>
                      <span class="status-badge ${agent.online ? 'status-online' : 'status-offline'}">
                        ${agent.online ? 'Online' : 'Offline'}
                      </span>
                    </div>
                    <div class="agent-body">
                      <p>${agent.description}</p>
                    </div>
                    <div class="agent-footer">
                      <a href="http://45.61.58.125:${agent.port}${agent.path}" target="_blank" class="btn btn-primary">
                        Open Dashboard
                      </a>
                      <button class="btn btn-secondary" onclick="checkHealth(${agent.port})">
                        Check Status
                      </button>
                    </div>
                  </div>
                `).join('')}
              </div>
            </div>
          `).join('')}
        </div>

        <div id="design-view" style="display: none;">
          <div class="design-system">
            <h2 style="margin-bottom: 20px;">Design System</h2>

            <h3 style="margin: 20px 0 10px 0;">Color Palette</h3>
            <div class="color-palette">
              <div class="color-swatch" style="background: ${DESIGN_SYSTEM.colors.primary};">Primary</div>
              <div class="color-swatch" style="background: ${DESIGN_SYSTEM.colors.secondary};">Secondary</div>
              <div class="color-swatch" style="background: ${DESIGN_SYSTEM.colors.accent};">Accent</div>
              <div class="color-swatch" style="background: ${DESIGN_SYSTEM.colors.success};">Success</div>
              <div class="color-swatch" style="background: ${DESIGN_SYSTEM.colors.warning};">Warning</div>
              <div class="color-swatch" style="background: ${DESIGN_SYSTEM.colors.error};">Error</div>
            </div>

            <h3 style="margin: 30px 0 10px 0;">Typography</h3>
            <p><strong>Primary Font:</strong> ${DESIGN_SYSTEM.fonts.primary}</p>
            <p><strong>Monospace Font:</strong> ${DESIGN_SYSTEM.fonts.mono}</p>

            <h3 style="margin: 30px 0 10px 0;">Spacing</h3>
            <p><strong>Base:</strong> ${DESIGN_SYSTEM.spacing.base}</p>
            <p><strong>Small:</strong> ${DESIGN_SYSTEM.spacing.small}</p>
            <p><strong>Large:</strong> ${DESIGN_SYSTEM.spacing.large}</p>

            <h3 style="margin: 30px 0 10px 0;">Border Radius</h3>
            <p><strong>Small:</strong> ${DESIGN_SYSTEM.borderRadius.small}</p>
            <p><strong>Medium:</strong> ${DESIGN_SYSTEM.borderRadius.medium}</p>
            <p><strong>Large:</strong> ${DESIGN_SYSTEM.borderRadius.large}</p>
          </div>
        </div>

        <div id="functions-view" style="display: none;">
          <div class="design-system">
            <h2 style="margin-bottom: 20px;">UI Manager Functions</h2>

            <h3>Available Functions:</h3>
            <ul style="line-height: 2; margin: 20px 0;">
              <li><strong>Agent Directory</strong> - Central hub linking to all agent dashboards</li>
              <li><strong>Status Monitoring</strong> - Real-time health checks for all agents</li>
              <li><strong>Design System</strong> - Unified color palette and styling guidelines</li>
              <li><strong>Universal Chat</strong> - AI assistant that works across all agents</li>
              <li><strong>Style Distribution</strong> - Generate CSS for consistent branding</li>
              <li><strong>Theme Customization</strong> - Customize colors and styles</li>
              <li><strong>Quick Navigation</strong> - One-click access to any agent</li>
              <li><strong>Visual Organization</strong> - Agents grouped by category</li>
              <li><strong>Responsive Design</strong> - Mobile-friendly layouts</li>
            </ul>

            <h3 style="margin-top: 30px;">API Endpoints:</h3>
            <ul style="line-height: 2; margin: 20px 0; font-family: ${DESIGN_SYSTEM.fonts.mono}; font-size: 13px;">
              <li>GET /api/agents - List all agents</li>
              <li>GET /api/status - Check all agent statuses</li>
              <li>GET /api/design-system - Get design tokens</li>
              <li>POST /api/chat - Universal AI chat</li>
              <li>POST /api/theme - Update theme</li>
              <li>GET /api/css - Generate unified CSS</li>
            </ul>
          </div>
        </div>

        <div id="preview-view" style="display: none;">
          <!-- Chat at top -->
          <div style="background: white; padding: 20px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;">
            <h3 style="margin-bottom: 15px;">💬 UI Feedback Chat - Make Suggestions!</h3>
            <div style="background: #fafafa; padding: 15px; border-radius: 5px; height: 150px; overflow-y: auto; margin-bottom: 15px;" id="previewChatMessages">
              <div style="padding: 10px; background: white; border-radius: 5px; margin-bottom: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
                <strong>UI Manager:</strong> Tell me what you think about the agent UIs below! I can help improve colors, layouts, consistency, etc.
              </div>
            </div>
            <div style="display: flex; gap: 10px;">
              <input type="text" id="previewChatInput" placeholder="e.g., 'Make all buttons the same color' or 'Add more spacing'" style="flex: 1; padding: 12px; border: 2px solid ${DESIGN_SYSTEM.colors.primary}; border-radius: 5px;" />
              <button onclick="sendPreviewMessage()" style="padding: 12px 30px; background: ${DESIGN_SYSTEM.colors.primary}; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: 600;">Send Feedback</button>
            </div>
          </div>

          <!-- Agent Preview Grid -->
          <div class="design-system" style="padding: 20px;">
            <h2 style="margin-bottom: 20px;">🎬 Live Agent UI Preview - All Running Agents</h2>
            <p style="margin-bottom: 20px; color: #666;">View all agent interfaces side-by-side. Click any preview to open in full screen.</p>

            <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 20px;">
              ${agentStatuses.filter(a => a.online).map(agent => `
                <div style="background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
                  <div style="background: linear-gradient(135deg, ${DESIGN_SYSTEM.colors.primary} 0%, ${DESIGN_SYSTEM.colors.secondary} 100%); color: white; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
                    <div>
                      <strong style="font-size: 16px;">${agent.icon} ${agent.name}</strong>
                      <div style="font-size: 12px; opacity: 0.9;">Port ${agent.port}</div>
                    </div>
                    <a href="http://45.61.58.125:${agent.port}${agent.path}" target="_blank" style="background: rgba(255,255,255,0.2); color: white; padding: 8px 16px; border-radius: 5px; text-decoration: none; font-size: 12px;">Open Full</a>
                  </div>
                  <div style="position: relative; padding-bottom: 75%; background: #f5f5f5;">
                    <iframe
                      src="http://45.61.58.125:${agent.port}${agent.path}"
                      style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;"
                      sandbox="allow-same-origin allow-scripts allow-forms"
                      loading="lazy"
                    ></iframe>
                  </div>
                  <div style="padding: 15px; background: #fafafa; border-top: 1px solid #eee;">
                    <p style="margin: 0; font-size: 13px; color: #666;">${agent.description}</p>
                  </div>
                </div>
              `).join('')}
            </div>
          </div>
        </div>

        <div id="chat-view" style="display: none;">
          <div class="chat-container">
            <div class="chat-info">
              <strong>🤖 Universal Chat - Your AI Assistant</strong><br>
              Ask me anything about your agents, tasks, store data, logs, or system operations.
              I can help you manage, monitor, and control all DW-Agents from one place!
            </div>
            <div class="chat-messages" id="chatMessages">
              <div class="chat-message assistant">
                👋 Hello! I'm your universal AI assistant for all DW-Agents. I can help you with:
                <ul style="margin: 10px 0 0 20px;">
                  <li>Check agent status and health</li>
                  <li>Query Shopify store data</li>
                  <li>Review log issues</li>
                  <li>Create and assign tasks</li>
                  <li>Navigate to specific agents</li>
                  <li>Manage UI and styling</li>
                </ul>
                What would you like to know?
              </div>
            </div>
            <div class="chat-input-area">
              <input type="text" class="chat-input" id="chatInput" placeholder="Ask about agents, tasks, orders, logs, or anything else..." />
              <button class="chat-send" onclick="sendMessage()">Send</button>
            </div>
          </div>
        </div>
      </div>

      <script>
        function showView(view) {
          document.querySelectorAll('.nav-item').forEach(item => item.classList.remove('active'));
          event.target.classList.add('active');

          document.getElementById('agents-view').style.display = 'none';
          document.getElementById('preview-view').style.display = 'none';
          document.getElementById('design-view').style.display = 'none';
          document.getElementById('functions-view').style.display = 'none';
          document.getElementById('chat-view').style.display = 'none';

          document.getElementById(view + '-view').style.display = 'block';
        }

        async function checkHealth(port) {
          try {
            const res = await fetch(\`http://45.61.58.125:\${port}/health\`);
            const data = await res.json();
            alert(\`Agent Status:\\n\\n\` + JSON.stringify(data, null, 2));
          } catch (error) {
            alert('Agent is offline or unreachable');
          }
        }

        async function sendMessage() {
          const input = document.getElementById('chatInput');
          const message = input.value.trim();
          if (!message) return;

          // Add user message
          const messagesDiv = document.getElementById('chatMessages');
          const userMsg = document.createElement('div');
          userMsg.className = 'chat-message user';
          userMsg.textContent = message;
          messagesDiv.appendChild(userMsg);

          input.value = '';
          messagesDiv.scrollTop = messagesDiv.scrollHeight;

          // Show thinking indicator
          const thinkingMsg = document.createElement('div');
          thinkingMsg.className = 'chat-message assistant';
          thinkingMsg.innerHTML = '💭 Thinking...';
          thinkingMsg.id = 'thinking';
          messagesDiv.appendChild(thinkingMsg);
          messagesDiv.scrollTop = messagesDiv.scrollHeight;

          try {
            const res = await fetch('/api/chat', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ message })
            });
            const data = await res.json();

            // Remove thinking indicator
            document.getElementById('thinking').remove();

            // Add assistant response
            const assistantMsg = document.createElement('div');
            assistantMsg.className = 'chat-message assistant';
            assistantMsg.textContent = data.response;
            messagesDiv.appendChild(assistantMsg);
            messagesDiv.scrollTop = messagesDiv.scrollHeight;
          } catch (error) {
            document.getElementById('thinking').remove();
            const errorMsg = document.createElement('div');
            errorMsg.className = 'chat-message assistant';
            errorMsg.textContent = 'Error: ' + error.message;
            messagesDiv.appendChild(errorMsg);
          }
        }

        // Preview chat for UI feedback
        async function sendPreviewMessage() {
          const input = document.getElementById('previewChatInput');
          const message = input.value.trim();
          if (!message) return;

          const messagesDiv = document.getElementById('previewChatMessages');

          // Add user message
          const userMsg = document.createElement('div');
          userMsg.style.cssText = 'padding: 10px; background: ${DESIGN_SYSTEM.colors.primary}; color: white; border-radius: 5px; margin-bottom: 10px; text-align: right;';
          userMsg.innerHTML = '<strong>You:</strong> ' + message;
          messagesDiv.appendChild(userMsg);

          input.value = '';
          messagesDiv.scrollTop = messagesDiv.scrollHeight;

          // Show thinking
          const thinkingMsg = document.createElement('div');
          thinkingMsg.style.cssText = 'padding: 10px; background: white; border-radius: 5px; margin-bottom: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);';
          thinkingMsg.innerHTML = '<strong>UI Manager:</strong> 💭 Analyzing UI feedback...';
          thinkingMsg.id = 'preview-thinking';
          messagesDiv.appendChild(thinkingMsg);
          messagesDiv.scrollTop = messagesDiv.scrollHeight;

          try {
            const res = await fetch('/api/ui-feedback', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ message })
            });
            const data = await res.json();

            document.getElementById('preview-thinking').remove();

            const assistantMsg = document.createElement('div');
            assistantMsg.style.cssText = 'padding: 10px; background: white; border-radius: 5px; margin-bottom: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);';
            assistantMsg.innerHTML = '<strong>UI Manager:</strong> ' + data.response;
            messagesDiv.appendChild(assistantMsg);
            messagesDiv.scrollTop = messagesDiv.scrollHeight;
          } catch (error) {
            document.getElementById('preview-thinking').remove();
          }
        }

        // Allow Enter key to send
        document.addEventListener('DOMContentLoaded', function() {
          const input = document.getElementById('chatInput');
          if (input) {
            input.addEventListener('keypress', function(e) {
              if (e.key === 'Enter') sendMessage();
            });
          }

          const previewInput = document.getElementById('previewChatInput');
          if (previewInput) {
            previewInput.addEventListener('keypress', function(e) {
              if (e.key === 'Enter') sendPreviewMessage();
            });
          }
        });
      </script>
    </body>
    </html>
  `);
});

// API: Get all agents
app.get('/api/agents', requireAuth, (req: Request, res: Response) => {
  res.json({ agents: AGENTS });
});

// API: Check status of all agents
app.get('/api/status', requireAuth, async (req: Request, res: Response) => {
  const statuses = await Promise.all(
    AGENTS.map(async (agent) => ({
      name: agent.name,
      port: agent.port,
      online: await checkAgentStatus(agent.port),
    }))
  );
  res.json({ statuses });
});

// API: UI Feedback chat
app.post('/api/ui-feedback', requireAuth, async (req: Request, res: Response) => {
  try {
    const { message } = req.body;

    const systemPrompt = `You are the UI Manager AI for DW-Agents. Users are giving you feedback about the UI/UX of various agent dashboards.

Your role:
- Analyze UI feedback and suggestions
- Provide actionable recommendations
- Suggest specific color codes, spacing values, or layout changes
- Be encouraging and helpful
- Reference the design system: Primary ${DESIGN_SYSTEM.colors.primary}, Secondary ${DESIGN_SYSTEM.colors.secondary}

Available agents to improve:
${AGENTS.map(a => `- ${a.name} (Port ${a.port})`).join('\n')}

Respond with specific, actionable suggestions. Use technical terms when appropriate (CSS, color codes, etc.).`;

    const response = await anthropic.messages.create({
      model: 'claude-3-5-sonnet-20241022',
      max_tokens: 512,
      system: systemPrompt,
      messages: [{ role: 'user', content: message }],
    });

    const assistantMessage = response.content[0].type === 'text' ? response.content[0].text : '';
    res.json({ response: assistantMessage });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

// API: Universal chat
app.post('/api/chat', requireAuth, async (req: Request, res: Response) => {
  try {
    const { message } = req.body;

    if (!req.session.chatHistory) {
      req.session.chatHistory = [];
    }

    req.session.chatHistory.push({ role: 'user', content: message });

    const systemPrompt = `You are the Universal AI Assistant for DW-Agents system. You have access to all agent information and can help users:

Available Agents:
${AGENTS.map(a => `- ${a.name} (Port ${a.port}): ${a.description}`).join('\n')}

You can help with:
- Checking agent status and health
- Navigating to specific agents
- Explaining agent functions
- Providing UI/UX guidance
- Helping with design system
- Creating tasks (coordinate with task-orchestrator)
- Querying Shopify store data (coordinate with shopify-store agent)
- Reviewing log issues (coordinate with log-monitor agent)
- Managing the overall system

Be helpful, concise, and actionable. Provide direct links to agents when relevant (http://45.61.58.125:[PORT]).`;

    const response = await anthropic.messages.create({
      model: 'claude-3-5-sonnet-20241022',
      max_tokens: 1024,
      system: systemPrompt,
      messages: req.session.chatHistory.slice(-10),
    });

    const assistantMessage = response.content[0].type === 'text' ? response.content[0].text : '';
    req.session.chatHistory.push({ role: 'assistant', content: assistantMessage });

    res.json({ response: assistantMessage });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

// API: Get design system
app.get('/api/design-system', requireAuth, (req: Request, res: Response) => {
  res.json({ designSystem: DESIGN_SYSTEM });
});

// API: Generate unified CSS
app.get('/api/css', requireAuth, (req: Request, res: Response) => {
  const css = `
/* DW-Agents Unified Design System */
:root {
  --color-primary: ${DESIGN_SYSTEM.colors.primary};
  --color-secondary: ${DESIGN_SYSTEM.colors.secondary};
  --color-accent: ${DESIGN_SYSTEM.colors.accent};
  --color-success: ${DESIGN_SYSTEM.colors.success};
  --color-warning: ${DESIGN_SYSTEM.colors.warning};
  --color-error: ${DESIGN_SYSTEM.colors.error};
  --color-dark: ${DESIGN_SYSTEM.colors.dark};
  --color-light: ${DESIGN_SYSTEM.colors.light};

  --font-primary: ${DESIGN_SYSTEM.fonts.primary};
  --font-mono: ${DESIGN_SYSTEM.fonts.mono};

  --spacing-base: ${DESIGN_SYSTEM.spacing.base};
  --spacing-small: ${DESIGN_SYSTEM.spacing.small};
  --spacing-large: ${DESIGN_SYSTEM.spacing.large};

  --radius-small: ${DESIGN_SYSTEM.borderRadius.small};
  --radius-medium: ${DESIGN_SYSTEM.borderRadius.medium};
  --radius-large: ${DESIGN_SYSTEM.borderRadius.large};

  --shadow-small: ${DESIGN_SYSTEM.shadows.small};
  --shadow-medium: ${DESIGN_SYSTEM.shadows.medium};
  --shadow-large: ${DESIGN_SYSTEM.shadows.large};
}

body {
  font-family: var(--font-primary);
  background: var(--color-light);
}

.btn-primary {
  background: var(--color-primary);
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: var(--radius-small);
  cursor: pointer;
}

.btn-primary:hover {
  background: var(--color-secondary);
}
  `;

  res.setHeader('Content-Type', 'text/css');
  res.send(css);
});

// Health check
app.get('/health', (req: Request, res: Response) => {
  res.json({
    status: 'healthy',
    agent: 'ui-manager',
    port: PORT,
    managedAgents: AGENTS.length,
    timestamp: new Date().toISOString()
  });
});

// Start server
app.listen(PORT, () => {
  console.log(`🎨 UI Manager Agent running on port ${PORT}`);
  console.log(`📊 Dashboard: http://localhost:${PORT}`);
  console.log(`🔗 Managing ${AGENTS.length} agents`);
});

// Graceful shutdown
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully...');
  process.exit(0);
});

process.on('SIGINT', () => {
  console.log('SIGINT received, shutting down gracefully...');
  process.exit(0);
});