"use client"; import { useState } from "react"; import Link from "next/link"; import { Search, Filter, Clock, CheckCircle, XCircle, Activity, GitBranch, Layers, ChevronLeft, ChevronRight, ArrowRight, } from "lucide-react"; import { cn, formatDuration, formatRelativeTime } from "@/lib/utils"; type TraceStatus = "RUNNING" | "COMPLETED" | "ERROR"; interface Trace { id: string; name: string; status: TraceStatus; startedAt: string; endedAt: string | null; durationMs: number | null; tags: string[]; metadata: Record; _count: { decisionPoints: number; spans: number; events: number; }; } interface TraceListProps { initialTraces: Trace[]; initialTotal: number; initialTotalPages: number; initialPage: number; } type FilterStatus = "ALL" | TraceStatus; const statusConfig: Record; color: string; bgColor: string }> = { RUNNING: { label: "Running", icon: Activity, color: "text-amber-400", bgColor: "bg-amber-500/10 border-amber-500/20", }, COMPLETED: { label: "Completed", icon: CheckCircle, color: "text-emerald-400", bgColor: "bg-emerald-500/10 border-emerald-500/20", }, ERROR: { label: "Error", icon: XCircle, color: "text-red-400", bgColor: "bg-red-500/10 border-red-500/20", }, }; export function TraceList({ initialTraces, initialTotal, initialTotalPages, initialPage, }: TraceListProps) { const [searchQuery, setSearchQuery] = useState(""); const [statusFilter, setStatusFilter] = useState("ALL"); const [currentPage, setCurrentPage] = useState(initialPage); const filteredTraces = initialTraces.filter((trace) => { const matchesSearch = trace.name.toLowerCase().includes(searchQuery.toLowerCase()) || trace.tags.some((tag) => tag.toLowerCase().includes(searchQuery.toLowerCase()) ); const matchesStatus = statusFilter === "ALL" || trace.status === statusFilter; return matchesSearch && matchesStatus; }); const filterChips: { value: FilterStatus; label: string }[] = [ { value: "ALL", label: "All" }, { value: "RUNNING", label: "Running" }, { value: "COMPLETED", label: "Completed" }, { value: "ERROR", label: "Error" }, ]; if (initialTraces.length === 0) { return ; } return (
{/* Header */}

Traces

{initialTotal} trace{initialTotal !== 1 ? "s" : ""} captured

{/* Search and Filter */}
setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-3 bg-neutral-900 border border-neutral-800 rounded-lg text-neutral-100 placeholder-neutral-500 focus:outline-none focus:border-emerald-500/50 focus:ring-1 focus:ring-emerald-500/50 transition-all" />
{filterChips.map((chip) => ( ))}
{/* Trace List */}
{filteredTraces.map((trace) => ( ))}
{/* Empty Filtered State */} {filteredTraces.length === 0 && initialTraces.length > 0 && (

No traces match your search criteria

)} {/* Pagination */} {initialTotalPages > 1 && (

Page {currentPage} of {initialTotalPages}

)}
); } function TraceCard({ trace }: { trace: Trace }) { const status = statusConfig[trace.status]; const StatusIcon = status.icon; return (
{/* Left: Name and Status */}

{trace.name}

{status.label}
{formatRelativeTime(trace.startedAt)} {formatDuration(trace.durationMs)}
{/* Middle: Stats */}
Decisions {trace._count.decisionPoints}
Spans {trace._count.spans}
{/* Right: Tags and Arrow */}
{trace.tags.length > 0 && (
{trace.tags.slice(0, 3).map((tag) => ( {tag} ))} {trace.tags.length > 3 && ( +{trace.tags.length - 3} )}
)}
); } function EmptyState() { return (

No traces yet

Install the SDK to start capturing traces from your AI agents

example.py
            
              from{" "}
              agentlens{" "}
              import{" "}
              init
              ,{" "}
              trace
              {"\n"}
              {"\n"}
              init
              (
              {"\n"}
              {"    "}
              api_key
              =
              "your-api-key"
              {"\n"}
              )
              {"\n"}
              {"\n"}
              @trace
              {"\n"}
              def{" "}
              my_agent
              ():
              {"\n"}
              {"    "}
              return{" "}
              
                "Hello, AgentLens!"
              
            
          
View Documentation
); }