import { useEffect, useMemo, useState } from "react"; import { ChevronLeft, ChevronRight, ExternalLink, Play } from "lucide-react"; import { Button } from "@/components/ui/button"; import { EVAL_REPLAY_MODEL, getTrajectorySteps, SAMPLE_TASKS, type TrajectoryStep, } from "@/data/benchmarkContent"; type TrajectoryViewerProps = { taskId?: string; }; function StepCard({ step, active, onClick, }: { step: TrajectoryStep; active: boolean; onClick: () => void; }) { const bg = step.kind === "evaluation" ? step.passed ? "bg-emerald-950/80 border-emerald-700/50" : "bg-red-950/80 border-red-800/50" : step.kind === "response" ? "bg-slate-800/80 border-slate-600/50" : "bg-slate-800/60 border-slate-700/50"; return ( {step.label} {step.summary} {step.kind === "evaluation" && ( click for details → )} ); } export function TrajectoryViewer({ taskId }: TrajectoryViewerProps) { const [activeTaskId, setActiveTaskId] = useState(taskId ?? SAMPLE_TASKS[0]?.id ?? ""); const [stepIdx, setStepIdx] = useState(0); const [detailStep, setDetailStep] = useState(null); useEffect(() => { if (taskId) { setActiveTaskId(taskId); setStepIdx(0); setDetailStep(null); } }, [taskId]); const activeTask = SAMPLE_TASKS.find((t) => t.id === activeTaskId) ?? SAMPLE_TASKS[0]; const steps = useMemo(() => { if (!activeTask) return []; return getTrajectorySteps(activeTask, EVAL_REPLAY_MODEL); }, [activeTask]); const evalStep = steps.find((s) => s.kind === "evaluation"); const passedMatch = evalStep?.summary.match(/(\d+)\s*\/\s*(\d+)/); const passedCount = passedMatch ? parseInt(passedMatch[1], 10) : 0; const totalCp = passedMatch ? parseInt(passedMatch[2], 10) : activeTask?.evaluationCheckpoints.length ?? 0; const currentStep = detailStep ?? steps[stepIdx]; const goPrev = () => { setDetailStep(null); setStepIdx((i) => Math.max(0, i - 1)); }; const goNext = () => { setDetailStep(null); setStepIdx((i) => Math.min(steps.length - 1, i + 1)); }; if (!activeTask || steps.length === 0) { return ( Select a task above to view evaluation replay. ); } return ( {SAMPLE_TASKS.map((t) => { const active = activeTaskId === t.id; return ( { setActiveTaskId(t.id); setStepIdx(0); setDetailStep(null); }} className={`text-xs font-semibold px-3 py-1.5 rounded-full border transition-colors ${ active ? "bg-teal-700 text-white border-teal-700" : "bg-white text-slate-600 border-slate-200 hover:border-teal-300" }`} > {t.taskName} ); })} {activeTask.title} {activeTaskId} · {EVAL_REPLAY_MODEL} (gpt-5-mini eval) · {passedCount} / {totalCp} checkpoints passed Evaluation replay {activeTaskId} Prev = steps.length - 1} > Next {stepIdx + 1} / {steps.length} Play {steps.map((step, i) => ( { setStepIdx(i); setDetailStep(step); }} /> ))} {currentStep ? ( <> {currentStep.label} {currentStep.detail} > ) : ( Select a step to view details. )} ); }
{step.label}
{step.summary}
click for details →
Select a task above to view evaluation replay.
{activeTaskId} · {EVAL_REPLAY_MODEL} (gpt-5-mini eval) · {passedCount} / {totalCp} checkpoints passed
{currentStep.label}
{currentStep.detail}
Select a step to view details.