Zayne Rea Sprague
Initial deploy: aggregate trace visualizer
8b41737
import { useEffect, useState } from "react";
import type { OverviewData, PanelNav } from "../types";
interface OverviewLevelProps {
datasetId: string;
fetchOverview: (dsId: string) => Promise<OverviewData>;
onDrillDown: (nav: PanelNav) => void;
}
export default function OverviewLevel({ datasetId, fetchOverview, onDrillDown }: OverviewLevelProps) {
const [data, setData] = useState<OverviewData | null>(null);
useEffect(() => {
fetchOverview(datasetId).then(setData).catch(() => {});
}, [datasetId, fetchOverview]);
if (!data) return <div className="p-4 text-gray-400">Loading overview...</div>;
return (
<div className="p-4 space-y-3">
{/* Experiment metadata */}
<div className="flex gap-3 text-xs text-gray-400">
<span>Model: <span className="text-gray-200">{data.metadata.model}</span></span>
<span>Method: <span className="text-gray-200">{data.metadata.method}</span></span>
<span>k: <span className="text-gray-200">{data.metadata.k}</span></span>
<span>Run: <span className="text-gray-200">{data.metadata.run_id}</span></span>
</div>
{/* GEPA iteration cards */}
<div className="space-y-2">
{data.gepa_iterations.map((gi) => (
<div
key={gi.gepa_iter}
className="bg-gray-800 border border-gray-700 rounded-lg p-4 hover:border-orange-500 cursor-pointer transition-colors"
onClick={() =>
onDrillDown({
datasetId,
level: 2,
gepaIter: gi.gepa_iter,
})
}
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-3">
<span className="bg-orange-600 text-white text-xs font-bold px-2 py-0.5 rounded-full">
GEPA {gi.gepa_iter}
</span>
{gi.has_final_answer && (
<span className="bg-emerald-900 text-emerald-300 text-xs px-2 py-0.5 rounded">
FINAL
</span>
)}
</div>
<span className="text-xs text-gray-400">
{gi.total_execution_time.toFixed(1)}s
</span>
</div>
<div className="flex gap-4 text-xs text-gray-400">
<span>{gi.n_rlm_iters} RLM iters</span>
<span>{gi.n_rlm_calls} calls</span>
<span>
{((gi.total_input_tokens + gi.total_output_tokens) / 1000).toFixed(1)}k tokens
</span>
</div>
{gi.final_answer_preview && (
<div className="mt-2 text-xs text-gray-500 truncate">
{gi.final_answer_preview}
</div>
)}
</div>
))}
</div>
</div>
);
}