/** * Agent Status Widget - shows running agents */ import { useState, useEffect } from "react"; import { Bot, Activity, AlertCircle, CheckCircle, Clock } from "lucide-react"; import type { WidgetProps } from "@mosaic/shared"; interface Agent { id: string; name: string; status: "IDLE" | "WORKING" | "WAITING" | "ERROR" | "TERMINATED"; currentTask?: string; lastHeartbeat: string; taskCount: number; } export function AgentStatusWidget({ id: _id, config: _config }: WidgetProps) { const [agents, setAgents] = useState([]); const [isLoading, setIsLoading] = useState(true); // Mock data for now - will fetch from API later useEffect(() => { setIsLoading(true); setTimeout(() => { setAgents([ { id: "1", name: "Code Review Agent", status: "WORKING", currentTask: "Reviewing PR #123", lastHeartbeat: new Date().toISOString(), taskCount: 42, }, { id: "2", name: "Documentation Agent", status: "IDLE", lastHeartbeat: new Date().toISOString(), taskCount: 15, }, { id: "3", name: "Test Runner Agent", status: "ERROR", currentTask: "Failed to run tests", lastHeartbeat: new Date(Date.now() - 300000).toISOString(), taskCount: 28, }, ]); setIsLoading(false); }, 500); }, []); const getStatusIcon = (status: Agent["status"]) => { switch (status) { case "WORKING": return ; case "IDLE": return ; case "WAITING": return ; case "ERROR": return ; case "TERMINATED": return ; default: return ; } }; const getStatusText = (status: Agent["status"]) => { return status.charAt(0).toUpperCase() + status.slice(1).toLowerCase(); }; const getTimeSinceLastHeartbeat = (timestamp: string) => { const now = new Date(); const last = new Date(timestamp); const diffMs = now.getTime() - last.getTime(); if (diffMs < 60000) return "Just now"; if (diffMs < 3600000) return `${Math.floor(diffMs / 60000)}m ago`; if (diffMs < 86400000) return `${Math.floor(diffMs / 3600000)}h ago`; return `${Math.floor(diffMs / 86400000)}d ago`; }; const stats = { total: agents.length, working: agents.filter((a) => a.status === "WORKING").length, idle: agents.filter((a) => a.status === "IDLE").length, error: agents.filter((a) => a.status === "ERROR").length, }; if (isLoading) { return (
Loading agents...
); } return (
{/* Summary stats */}
{stats.total}
Total
{stats.working}
Working
{stats.idle}
Idle
{stats.error}
Error
{/* Agent list */}
{agents.length === 0 ? (
No agents configured
) : ( agents.map((agent) => (
{agent.name}
{getStatusIcon(agent.status)} {getStatusText(agent.status)}
{agent.currentTask && (
{agent.currentTask}
)}
{agent.taskCount} tasks completed {getTimeSinceLastHeartbeat(agent.lastHeartbeat)}
)) )}
); }