"use client"; import { Suspense } from "react"; import { useSearchParams, useRouter } from "next/navigation"; import { useOrchestratorStatus } from "@/hooks/use-agents"; import { useTasks } from "@/hooks/use-tasks"; import { useUsageSummary, useUsageTimeSeries, useAgentUsage, useTeamUsage, useModelUsage, useUsageProjection, useCacheEfficiency, useUsageSessions, } from "@/hooks/use-usage"; import { TaskStatus, Team } from "@/types"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; import { Skeleton } from "@/components/ui/skeleton"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { OfflineState } from "@/components/ui/offline-state"; import { DeliveryTabContent } from "@/components/metrics/delivery-tab"; import { UsageTimeSeriesChart, ModelUsageDonut, AgentUsageChart, TeamUsageChart, SessionsTable, } from "@/components/metrics"; import { Activity, TrendingUp, TrendingDown, Clock, AlertTriangle, Users, CheckCircle, XCircle, Zap, Timer, Coins, Sparkles, } from "lucide-react"; import type { UsageProjection as UP, CacheEfficiencyResponse as CER, } from "@/types"; // ─── Humanized number formatting ───────────────────────────────────────────── /** Format counts with K/M suffix for values >= 1000. */ function humanizeCount(n: number): string { if (n >= 1_000_000) return (n / 1_000_000).toFixed(1) + "M"; if (n >= 1_000) return (n / 1_000).toFixed(1) + "K"; return String(n); } /** Format token counts (same as humanizeCount but used for token display). */ function fmtTokens(n: number): string { if (n >= 1_000_000) return (n / 1_000_000).toFixed(2) + "M"; if (n >= 1_000) return (n / 1_000).toFixed(1) + "K"; return String(n); } // ─── Shared sub-components ──────────────────────────────────────────────────── interface MetricCardProps { title: string; value: string | number; subtitle?: string; icon: React.ReactNode; trend?: "up" | "down" | "neutral"; trendValue?: string; } function MetricCard({ title, value, subtitle, icon, trend, trendValue, }: MetricCardProps) { const displayValue = typeof value === "number" ? humanizeCount(value) : value; return ( {title} {icon}
{displayValue}
{subtitle && (

{subtitle}

)} {trend && trendValue && (
{trendValue}
)}
); } interface TeamHealthCardProps { team: Team; activeTasks: number; blockedTasks: number; completedToday: number; } function TeamHealthCard({ team, activeTasks, blockedTasks, completedToday, }: TeamHealthCardProps) { const healthScore = Math.max(0, 100 - blockedTasks * 20); return ( {team.replace(/_/g, " ")} Cell
{healthScore}%
{activeTasks}
Active
{blockedTasks}
Blocked
{completedToday}
Done
); } // ─── Performance tab content ───────────────────────────────────────────────── function PerformanceTabContent() { const { data: tasks, error: tasksError, refetch: refetchTasks } = useTasks(); const { data: status, error: statusError, refetch: refetchStatus, } = useOrchestratorStatus(); const isOffline = (tasksError || statusError) && (tasksError?.message?.includes("Network Error") || statusError?.message?.includes("Network Error")); const refetch = () => { refetchTasks(); refetchStatus(); }; const taskList = tasks || []; const agentList = status?.agents || []; // Velocity metrics const completedToday = taskList.filter((t) => { if (!t.completed_at) return false; const completed = new Date(t.completed_at); const today = new Date(); return completed.toDateString() === today.toDateString(); }).length; const completedThisWeek = taskList.filter((t) => { if (!t.completed_at) return false; const completed = new Date(t.completed_at); const weekAgo = new Date(); weekAgo.setDate(weekAgo.getDate() - 7); return completed > weekAgo; }).length; // Task status counts const pending = taskList.filter( (t) => t.status === TaskStatus.PENDING, ).length; const inProgress = taskList.filter( (t) => t.status === TaskStatus.IN_PROGRESS, ).length; const blocked = taskList.filter( (t) => t.status === TaskStatus.BLOCKED, ).length; const awaitingQa = taskList.filter( (t) => t.status === TaskStatus.AWAITING_QA, ).length; const completed = taskList.filter( (t) => t.status === TaskStatus.COMPLETED, ).length; // Agent counts const runningAgents = status?.by_state?.running || agentList.filter((a) => a.state === "running").length; const idleAgents = status?.by_state?.idle || agentList.filter((a) => a.state === "idle" || a.state === "stopped").length; const waitingAgents = status?.waiting_count || agentList.filter((a) => a.state === "waiting_long").length; const errorAgents = status?.by_state?.error || agentList.filter((a) => a.state === "error").length; // Team metrics const teamMetrics = Object.values(Team).map((team) => { const teamTasks = taskList.filter((t) => t.team === team); return { team, activeTasks: teamTasks.filter((t) => [TaskStatus.IN_PROGRESS, TaskStatus.CLAIMED].includes(t.status), ).length, blockedTasks: teamTasks.filter((t) => t.status === TaskStatus.BLOCKED) .length, completedToday: teamTasks.filter((t) => { if (!t.completed_at) return false; const c = new Date(t.completed_at); const today = new Date(); return c.toDateString() === today.toDateString(); }).length, }; }); if (isOffline) { return ( ); } return (
{/* Velocity Metrics */}

Velocity

} /> } /> } /> 0 ? Math.round((completed / taskList.length) * 100) + "%" : "0%" } subtitle="Of all tasks" icon={} />
{/* Task Status */}

Task Status

} /> } /> } /> } /> } />
{/* Agent Status */}

Agent Status

} /> } /> } /> } />
{/* Team Health */}

Team Health

{teamMetrics.map((tm) => ( ))}
); } // ─── Token Usage & Costs tab content ───────────────────────────────────────── function TokenUsageCostsSection() { const { data: summary, isLoading: loadingSnap } = useUsageSummary("24h"); const { data: timeSeries, isLoading: loadingTS } = useUsageTimeSeries("24h"); const { data: agentUsage, isLoading: loadingAgents } = useAgentUsage("24h"); const { data: teamUsage, isLoading: loadingTeams } = useTeamUsage("24h"); const { data: sessions, isLoading: loadingSessions } = useUsageSessions(100); const { data: modelUsage, isLoading: loadingModels } = useModelUsage("24h"); const { data: projection, isLoading: loadingProj } = useUsageProjection(); const { data: cacheStats, isLoading: loadingCache } = useCacheEfficiency("24h"); const trendUp = (summary?.trend_pct ?? 0) >= 0; return (
{/* Row 1 — Summary cards */}
} isLoading={loadingSnap} /> } isLoading={loadingSnap} /> } isLoading={loadingSnap} /> ) : ( ) } isLoading={loadingSnap} /> } isLoading={loadingSnap} /> } isLoading={loadingCache} />
{/* Row 2 — Time series + model donut */}
{/* Row 3 — Agent bar + team bar */}
{/* Row 4 — Projection + cache efficiency */}
{/* Row 5 — Sessions table */}
); } // ─── Helper sub-components ──────────────────────────────────────────────────── interface SummaryCardProps { title: string; value: string | undefined; icon: React.ReactNode; trend?: { dir: "up" | "down"; label: string }; isLoading: boolean; } function SummaryCard({ title, value, icon, trend, isLoading, }: SummaryCardProps) { return ( {title} {icon} {isLoading ? ( ) : ( <>
{value ?? "—"}
{trend && (

{trend.label}

)} )}
); } interface ProjectionCardProps { projection: UP | undefined; isLoading: boolean; } function ProjectionCard({ projection, isLoading }: ProjectionCardProps) { return ( Monthly Projection {isLoading ? ( ) : (
{projection != null ? "$" + projection.projected_monthly_cost_usd.toFixed(2) : "—"}

Based on {projection?.basis_days ?? 7}-day rolling average ($ {projection?.avg_daily_cost_usd.toFixed(4) ?? "—"}/day)

)}
); } interface CacheEfficiencyCardProps { cacheStats: CER | undefined; isLoading: boolean; } function CacheEfficiencyCard({ cacheStats, isLoading, }: CacheEfficiencyCardProps) { const pct = cacheStats ? cacheStats.cache_hit_rate * 100 : 0; return ( Cache Efficiency {isLoading ? ( ) : (
{pct.toFixed(1)}%

{cacheStats ? fmtTokens(cacheStats.tokens_cache_read) : "—"} cache reads · saved $ {cacheStats?.cost_saved_by_cache_usd.toFixed(4) ?? "—"}

)}
); } // ─── Tab types ──────────────────────────────────────────────────────────────── type MetricsTab = "performance" | "token-usage" | "delivery"; const VALID_METRICS_TABS: MetricsTab[] = [ "performance", "token-usage", "delivery", ]; function isValidMetricsTab(value: string | null): value is MetricsTab { return VALID_METRICS_TABS.includes(value as MetricsTab); } // ─── Main page content (uses useSearchParams) ───────────────────────────────── function MetricsPageContent() { const router = useRouter(); const searchParams = useSearchParams(); // Read ?tab= from URL, default to "performance" const rawTab = searchParams.get("tab"); const activeTab: MetricsTab = isValidMetricsTab(rawTab) ? rawTab : "performance"; function handleTabChange(value: string) { const params = new URLSearchParams(searchParams.toString()); params.set("tab", value); router.push(`?${params.toString()}`); } return (
{/* Header */}

Metrics

Performance analytics and operational insights

Performance Token Usage Delivery
); } // Wrap in Suspense for useSearchParams export default function MetricsPage() { return (
{Array.from({ length: 4 }).map((_, i) => ( ))}
} >
); }