import { useState, useEffect } from "react"; import { CheckCircle, XCircle, Loader2, Square, Clock } from "lucide-react"; import type { AgentHeartbeatRun } from "../api"; import { fetchAgentRuns } from "../api"; interface AgentRunHistoryProps { agentId: string; projectId?: string; } const STATUS_ICONS: Record = { completed: { icon: CheckCircle, color: "var(--color-success, #3fb950)" }, failed: { icon: XCircle, color: "var(--color-error, #f85149)" }, active: { icon: Loader2, color: "var(--in-progress, #bc8cff)" }, terminated: { icon: Square, color: "var(--text-muted, #8b949e)" }, }; export function AgentRunHistory({ agentId, projectId }: AgentRunHistoryProps) { const [runs, setRuns] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { setIsLoading(true); fetchAgentRuns(agentId, 50, projectId) .then(setRuns) .catch(() => setRuns([])) .finally(() => setIsLoading(false)); }, [agentId, projectId]); if (isLoading) { return
Loading runs...
; } if (runs.length === 0) { return
No runs yet
; } return (
{runs.map(run => { const statusInfo = STATUS_ICONS[run.status] ?? STATUS_ICONS.terminated; const StatusIcon = statusInfo.icon; const duration = run.endedAt ? Math.round((new Date(run.endedAt).getTime() - new Date(run.startedAt).getTime()) / 1000) : null; const usage = run.usageJson; return (
{run.id} {new Date(run.startedAt).toLocaleString()}
{duration !== null && ( {duration}s )} {usage && ( {((usage.inputTokens + usage.outputTokens) / 1000).toFixed(1)}k tokens )} {run.triggerDetail && ( {run.triggerDetail} )}
); })}
); }