"use client"; import { useState, useEffect, useMemo } from "react"; import { useSession } from "next-auth/react"; import { agentsApi, type AgentTask, type TaskLog, type Agent } from "@/lib/api/agents"; import { MetricCard } from "@/components/business/metric-card"; import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, } from "@/components/ui/table"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { cn } from "@/lib/utils"; import { Bot, CheckCircle2, XCircle, Clock, Loader2, AlertCircle, Settings2, Save } from "lucide-react"; type TaskStatus = "pending" | "running" | "completed" | "failed" | "cancelled"; type FilterStatus = "all" | TaskStatus; const STATUS_CONFIG: Record = { pending: { label: "等待中", icon: , color: "bg-gray-100 text-gray-600" }, running: { label: "运行中", icon: , color: "bg-blue-100 text-blue-600" }, completed: { label: "已完成", icon: , color: "bg-emerald-100 text-emerald-600" }, failed: { label: "失败", icon: , color: "bg-red-100 text-red-600" }, cancelled: { label: "已取消", icon: , color: "bg-yellow-100 text-yellow-600" }, }; function formatDuration(startedAt?: string, completedAt?: string): string { if (!startedAt) return "-"; const start = new Date(startedAt).getTime(); const end = completedAt ? new Date(completedAt).getTime() : Date.now(); const seconds = Math.round((end - start) / 1000); if (seconds < 60) return `${seconds}s`; const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; return `${minutes}m ${remainingSeconds}s`; } function formatDate(dateStr: string): string { const date = new Date(dateStr); return date.toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", }); } interface ExecutionStats { total: number; successCount: number; failedCount: number; runningCount: number; successRate: number; avgDurationSeconds: number; } export default function AgentsPage() { const { data: session } = useSession(); const token = (session as { accessToken?: string })?.accessToken; const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [filterStatus, setFilterStatus] = useState("all"); const [selectedTask, setSelectedTask] = useState(null); const [taskLogs, setTaskLogs] = useState([]); const [loadingLogs, setLoadingLogs] = useState(false); const [agents, setAgents] = useState([]); const [configAgent, setConfigAgent] = useState(null); const [configJson, setConfigJson] = useState(""); const [savingConfig, setSavingConfig] = useState(false); // 获取执行记录 useEffect(() => { if (!token) return; async function fetchTasks() { setLoading(true); setError(null); try { const params = filterStatus !== "all" ? { status: filterStatus, limit: 50 } : { limit: 50 }; const result = await agentsApi.listTasks(token!, params); setTasks(result.items); } catch (err) { setError(err instanceof Error ? err.message : "获取执行记录失败"); } finally { setLoading(false); } } fetchTasks(); }, [token, filterStatus]); useEffect(() => { if (!token) return; agentsApi.list(token).then(setAgents).catch(() => {}); }, [token]); // 获取任务日志 const fetchTaskLogs = async (taskId: string) => { if (!token) return; setLoadingLogs(true); try { const result = await agentsApi.getTaskLogs(token, taskId); setTaskLogs(result.items); } catch (err) { console.error("获取日志失败:", err); } finally { setLoadingLogs(false); } }; // 计算统计摘要 const stats = useMemo(() => { const allTasks = tasks; const successCount = allTasks.filter(t => t.status === "completed").length; const failedCount = allTasks.filter(t => t.status === "failed").length; const runningCount = allTasks.filter(t => t.status === "running" || t.status === "pending").length; const total = allTasks.length; const completedTasks = allTasks.filter( t => t.status === "completed" && t.started_at && t.completed_at ); const totalDuration = completedTasks.reduce((sum, t) => { const start = new Date(t.started_at!).getTime(); const end = new Date(t.completed_at!).getTime(); return sum + (end - start) / 1000; }, 0); const avgDurationSeconds = completedTasks.length > 0 ? totalDuration / completedTasks.length : 0; return { total, successCount, failedCount, runningCount, successRate: total > 0 ? (successCount / total) * 100 : 0, avgDurationSeconds, }; }, [tasks]); // 打开详情弹窗 const handleRowClick = async (task: AgentTask) => { setSelectedTask(task); await fetchTaskLogs(task.id); }; const openConfig = (agent: Agent) => { setConfigAgent(agent); setConfigJson(JSON.stringify(agent.config ?? {}, null, 2)); }; const saveConfig = async () => { if (!token || !configAgent) return; try { setSavingConfig(true); const parsed = JSON.parse(configJson); await agentsApi.updateConfig(token, configAgent.id, parsed); setConfigAgent(null); const updated = await agentsApi.list(token); setAgents(updated); } catch (err) { console.error("保存配置失败:", err); } finally { setSavingConfig(false); } }; const filterButtons: { status: FilterStatus; label: string }[] = [ { status: "all", label: "全部" }, { status: "running", label: "运行中" }, { status: "completed", label: "已完成" }, { status: "failed", label: "失败" }, ]; return (
{/* 页面标题 */}

Agent监控

监控Agent执行状态和历史记录

{/* 统计摘要卡片 */}
} trend="neutral" /> } trend={stats.successRate >= 80 ? "up" : "down"} /> 0 ? `${stats.avgDurationSeconds.toFixed(1)}s` : "-"} icon={} trend="neutral" />
Agent 配置 {agents.length === 0 ? (

暂无 Agent

) : (
{agents.map((agent) => (

{agent.name}

{agent.type}

{agent.status}
))}
)}
{/* 状态筛选 */}
{filterButtons.map(({ status, label }) => ( ))}
{/* 执行历史列表 */} 执行历史 {loading ? (
{[1, 2, 3].map(i => ( ))}
) : error ? (

{error}

) : tasks.length === 0 ? (

暂无执行记录

) : ( 任务类型 状态 耗时 创建时间 错误信息 {tasks.map(task => { const config = STATUS_CONFIG[task.status]; return ( handleRowClick(task)} className="cursor-pointer hover:bg-muted/40" > {task.task_type} {config.icon} {config.label} {formatDuration(task.started_at, task.completed_at)} {formatDate(task.created_at)} {task.error_message || "-"} ); })}
)}
{/* 执行详情弹窗 */} setSelectedTask(null)}> 执行详情 {selectedTask && (
{/* 基本信息 */}

任务ID

{selectedTask.id}

任务类型

{selectedTask.task_type}

状态

{STATUS_CONFIG[selectedTask.status].icon} {STATUS_CONFIG[selectedTask.status].label}

优先级

{selectedTask.priority}

开始时间

{selectedTask.started_at ? formatDate(selectedTask.started_at) : "-"}

完成时间

{selectedTask.completed_at ? formatDate(selectedTask.completed_at) : "-"}

{/* 错误信息 */} {selectedTask.error_message && (

错误信息

{selectedTask.error_message}

)} {/* 执行日志 */}

执行日志

{loadingLogs ? (
{[1, 2, 3].map(i => ( ))}
) : taskLogs.length === 0 ? (

暂无日志

) : (
{taskLogs.map(log => (
[{formatDate(log.created_at)}] [{log.log_level}] {log.message}
))}
)}
)}
setConfigAgent(null)}> 配置 — {configAgent?.name} {configAgent && (