← back to Designer Wallcoverings

DW-Agents/dw-agents/agent-completed-tasks/completed-tasks-agent.ts.backup-20251121-005605

278 lines

/**
 * DW-Agents: Completed Tasks Agent
 *
 * Shows all completed tasks from all agents in chronological order
 * Port: 9889
 */

import express, { Request, Response } from 'express';
import { requireGlobalAuth } from '../shared-global-auth';
import { getCompletedTasks, logCompletedTask } from '../shared-task-logger';
const SSO_TOKEN_NAME = 'sso_token';
const SSO_TOKEN_VALUE = 'dw-secure-token-2024';
import cookieParser from 'cookie-parser';
import session from 'express-session';

// import { chatMiddleware } from '../shared-chat-integration';
const chatMiddleware = (config: any) => (req: any, res: any, next: any) => next();

const app = express();

// Global Authentication
const PORT = 9889;

// Global Authentication - MUST come before any other middleware
app.use(cookieParser());

// Add inter-agent chat widget (after auth)
app.use(chatMiddleware({
  agentId: 'agent-completed-tasks',
  agentName: 'Completed Tasks',
  port: 9889,
  category: 'agent'
}));


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

declare module 'express-session' {
  interface SessionData {
    authenticated: boolean;
  }
}

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

// REMOVED: requireAuth - now using requireGlobalAuth from shared-global-auth

// API endpoint for agents to submit completed tasks
app.post('/api/task', express.json(), (req: Request, res: Response) => {
  try {
    const { agent, task, status, metadata } = req.body;

    if (!agent || !task || !status) {
      return res.status(400).json({ error: 'Missing required fields: agent, task, status' });
    }

    logCompletedTask({ agent, task, status, metadata });

    res.json({ success: true, message: 'Task logged successfully' });
  } catch (error) {
    console.error('Failed to log task:', error);
    res.status(500).json({ error: 'Failed to log task' });
  }
});

// API endpoint to get completed tasks as JSON
app.get('/api/tasks', (req: Request, res: Response) => {
  try {
    const tasks = getCompletedTasks();
    res.json(tasks);
  } catch (error) {
    console.error('Failed to retrieve tasks:', error);
    res.status(500).json({ error: 'Failed to retrieve tasks' });
  }
});

// Main dashboard
app.get('/', requireGlobalAuth, (req: Request, res: Response) => {
  const tasks = getCompletedTasks();

  const tasksHTML = tasks.length > 0
    ? tasks.map(t => `
      <div class="task-item" data-agent="${t.agent}">
        <div class="task-header">
          <div class="task-agent">${t.agent}</div>
          <div class="task-time">${new Date(t.timestamp).toLocaleString()}</div>
        </div>
        <div class="task-description">${t.task}</div>
        <div class="task-status">${t.status}</div>
      </div>
    `).join('')
    : `
      <div style="text-align: center; padding: 40px; color: #888;">
        <h3>No completed tasks yet</h3>
        <p>Tasks will appear here as agents complete them.</p>
        <p style="margin-top: 20px;">Agents can log tasks via: <code>POST http://45.61.58.125:9889/api/task</code></p>
      </div>
    `;

  res.send(`
<!DOCTYPE html>
<html>
<head>
  <title>Completed Tasks - DW-Agents</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
      padding: 20px;
      min-height: 100vh;
    }
    .header {
      background: white;
      padding: 30px;
      border-radius: 15px;
      margin-bottom: 20px;
      box-shadow: 0 5px 20px rgba(0,0,0,0.1);
    }
    .header h1 { color: #28a745; font-size: 2.5em; margin-bottom: 10px; }
    .header .subtitle { color: #666; font-size: 1.1em; }
    .timeline {
      background: white;
      border-radius: 15px;
      padding: 30px;
      box-shadow: 0 5px 20px rgba(0,0,0,0.1);
    }
    .task-item {
      border-left: 4px solid #28a745;
      padding: 20px;
      margin-bottom: 20px;
      background: #f8f9fa;
      border-radius: 8px;
      transition: all 0.2s;
    }
    .task-item:hover {
      transform: translateX(5px);
      box-shadow: 0 3px 10px rgba(40, 167, 69, 0.2);
    }
    .task-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 10px;
    }
    .task-agent {
      font-weight: 600;
      color: #28a745;
      font-size: 1.1em;
    }
    .task-time {
      color: #888;
      font-size: 0.9em;
    }
    .task-description {
      color: #333;
      margin-bottom: 8px;
      font-size: 1.05em;
    }
    .task-status {
      display: inline-block;
      background: #28a745;
      color: white;
      padding: 4px 12px;
      border-radius: 12px;
      font-size: 0.85em;
      font-weight: 600;
    }
    .filters {
      background: white;
      padding: 20px;
      border-radius: 15px;
      margin-bottom: 20px;
      box-shadow: 0 5px 20px rgba(0,0,0,0.1);
      display: flex;
      gap: 15px;
      align-items: center;
    }
    .filters select {
      padding: 10px;
      border: 2px solid #e0e0e0;
      border-radius: 8px;
      font-size: 1em;
    }
    .filters label {
      font-weight: 600;
      color: #666;
    }
  </style>
</head>
<body>
  <div class="header">
    <h1>✅ Completed Tasks</h1>
    <div class="subtitle">All completed tasks from DW-Agents in chronological order</div>
  </div>

  <div class="filters">
    <label>Filter by Agent:</label>
    <select id="agentFilter" onchange="filterTasks()">
      <option value="all">All Agents</option>
      <option value="Legal Team">Legal Team</option>
      <option value="Marketing">Marketing</option>
      <option value="Digital Samples">Digital Samples</option>
      <option value="Purchasing Office">Purchasing Office</option>
      <option value="Trend Research">Trend Research</option>
      <option value="Accounting">Accounting</option>
      <option value="Zendesk Chat">Zendesk Chat</option>
      <option value="Server Uptime">Server Uptime</option>
    </select>
    <span style="margin-left: auto; color: #888;" id="lastUpdate">Last updated: --:--</span>
  </div>

  <div class="timeline" id="timeline">
    ${tasksHTML}
  </div>

  <script>
    function filterTasks() {
      const filter = document.getElementById('agentFilter').value;
      const items = document.querySelectorAll('.task-item');

      items.forEach(item => {
        if (filter === 'all' || item.dataset.agent === filter) {
          item.style.display = 'block';
        } else {
          item.style.display = 'none';
        }
      });
    }

    function updateTimestamp() {
      document.getElementById('lastUpdate').textContent = 'Last updated: ' + new Date().toLocaleTimeString();
    }

    // Auto-refresh every 30 seconds
    setInterval(() => {
      location.reload();
    }, 30000);

    updateTimestamp();
  </script>
</body>
</html>
  `);
});


// Metrics endpoint for daily reporting
app.get("/api/metrics", (req: Request, res: Response) => {
  res.json({
    status: "online",
    uptime: process.uptime(),
    responseTime: 0,
    tasksCompleted: 0,
    errorsToday: 0,
    lastActivity: new Date().toISOString(),
    qnaReadiness: 100
  });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`✅ Completed Tasks Agent running on port ${PORT}`);
  console.log(`Dashboard: http://45.61.58.125:${PORT}`);
});