/** * Command Center header: population + run + baseline selectors, run status, * cache stats chip, and the two entry-point actions (generate population, * launch evaluation run). The action buttons are exported so the page-level * empty state can reuse them front and center. */ import { useMemo, useState } from 'react'; import Alert from '@mui/material/Alert'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Chip from '@mui/material/Chip'; import CircularProgress from '@mui/material/CircularProgress'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogTitle from '@mui/material/DialogTitle'; import FormControlLabel from '@mui/material/FormControlLabel'; import MenuItem from '@mui/material/MenuItem'; import Switch from '@mui/material/Switch'; import TextField from '@mui/material/TextField'; import Tooltip from '@mui/material/Tooltip'; import Typography from '@mui/material/Typography'; import { Database, FlaskConical } from 'lucide-react'; import type { CacheStats, EvaluationRunInfo, PopulationMeta } from '../../types/megaeval'; import { createRun, fmtCompact, generatePopulation } from '../../services/megaeval'; import { fmtPct } from '../labeleval/shared'; import { GLOSSARY } from '../../content/glossary'; import { GlossaryContent } from '../help/InfoTip'; import { RunStatusChip } from './shared'; // ---------------------------------------------------------------- action buttons export function GeneratePopulationButton({ onGenerated, variant = 'outlined', size = 'small', }: { onGenerated: (pop: PopulationMeta) => void; variant?: 'outlined' | 'contained'; size?: 'small' | 'medium' | 'large'; }) { const [open, setOpen] = useState(false); const [numObjects, setNumObjects] = useState('320000'); const [name, setName] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const submit = async () => { setBusy(true); setError(null); try { const parsed = Number(numObjects); const pop = await generatePopulation({ ...(name.trim() ? { name: name.trim() } : {}), num_objects: Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed) : 320000, }); setOpen(false); onGenerated(pop); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } }; return ( <> (busy ? undefined : setOpen(false))} maxWidth="xs" fullWidth> Generate evaluation population {error ? ( {error} ) : null} setName(e.target.value)} placeholder="e.g. q3-highway-mix" /> setNumObjects(e.target.value)} helperText="1K – 1.2M synthetic annotated objects (default 320K)" /> ); } export function NewRunButton({ populationId, onCreated, variant = 'contained', size = 'small', }: { populationId: string | null; onCreated: (run: EvaluationRunInfo) => void; variant?: 'outlined' | 'contained'; size?: 'small' | 'medium' | 'large'; }) { const [open, setOpen] = useState(false); const [modelVersion, setModelVersion] = useState('perception-v2.1'); const [injectRegression, setInjectRegression] = useState(false); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const submit = async () => { if (!populationId) return; setBusy(true); setError(null); try { const run = await createRun({ population_id: populationId, model_version: modelVersion.trim() || 'perception-v2.1', ...(injectRegression ? { overrides: { night_penalty: 0.3, vru_penalty: 0.1 } } : {}), }); setOpen(false); onCreated(run); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } }; return ( <> (busy ? undefined : setOpen(false))} maxWidth="xs" fullWidth> Launch evaluation run {error ? ( {error} ) : null} setModelVersion(e.target.value)} /> setInjectRegression(e.target.checked)} /> } label={ Inject regression (demo) Applies overrides night_penalty=0.30, vru_penalty=0.10 } /> Runs are asynchronous: the run is queued, evaluated across distributed workers, then published. ); } // ---------------------------------------------------------------- header bar export default function HeaderBar({ populations, populationId, onPopulationChange, runs, runId, onRunChange, baselineRunId, onBaselineChange, selectedRun, cache, onGenerated, onRunCreated, }: { populations: PopulationMeta[]; populationId: string | null; onPopulationChange: (id: string) => void; runs: EvaluationRunInfo[]; runId: string | null; onRunChange: (id: string) => void; baselineRunId: string | null; onBaselineChange: (id: string | null) => void; selectedRun: EvaluationRunInfo | null; cache: CacheStats | null; onGenerated: (pop: PopulationMeta) => void; onRunCreated: (run: EvaluationRunInfo) => void; }) { const sortedRuns = useMemo( () => [...runs].sort((a, b) => (b.created_at ?? '').localeCompare(a.created_at ?? '')), [runs] ); const publishedRuns = useMemo(() => sortedRuns.filter((r) => r.status === 'published'), [sortedRuns]); const runLabel = (r: EvaluationRunInfo) => `${r.model_version} · ${r.run_id.slice(0, 8)}${r.status === 'published' ? '' : ` (${r.status})`}`; return ( } enterDelay={500}> onPopulationChange(e.target.value)} sx={{ minWidth: 220 }} disabled={populations.length === 0} > {populations.map((p) => ( {p.name} · {fmtCompact(p.num_objects)} objects ))} } enterDelay={500}> r.run_id === runId) ? runId : ''} onChange={(e) => onRunChange(e.target.value)} sx={{ minWidth: 240 }} disabled={sortedRuns.length === 0} > {sortedRuns.map((r) => ( {runLabel(r)} ))} r.run_id === baselineRunId) ? baselineRunId : '' } onChange={(e) => onBaselineChange(e.target.value === '' ? null : e.target.value)} sx={{ minWidth: 220 }} disabled={publishedRuns.length === 0} > None {publishedRuns .filter((r) => r.run_id !== runId) .map((r) => ( {runLabel(r)} ))} {selectedRun ? : null} {cache ? ( {`now: ${cache.entries} entries · ${cache.hits} hits / ${cache.misses} misses`} } > ) : null} ); }