import { useEffect, useState } from 'react'; import { Play, RotateCcw, Dices } from 'lucide-react'; import type { BackendRuntimeStatus, Difficulty, ScenarioTemplate, ResetParams } from '@/types'; import { cn } from '@/lib/utils'; import { sfx } from '@/lib/audio'; import { healthCheck } from '@/lib/api'; const TEMPLATES: { value: ScenarioTemplate; label: string }[] = [ { value: 'math_reasoning', label: 'Math Reasoning' }, { value: 'ml_benchmark', label: 'ML Benchmark' }, { value: 'finance_trading', label: 'Finance Trading' }, ]; const DIFFICULTIES: { value: Difficulty; label: string }[] = [ { value: 'easy', label: 'Easy' }, { value: 'medium', label: 'Medium' }, { value: 'hard', label: 'Hard' }, ]; interface ControlsProps { onStart: (params: ResetParams) => void; onStep?: () => void; disabled?: boolean; episodeActive?: boolean; className?: string; initialSeed?: number; initialTemplate?: ScenarioTemplate; initialDifficulty?: Difficulty; runtimeStatus?: BackendRuntimeStatus | null; } export default function Controls({ onStart, onStep, disabled, episodeActive, className, initialSeed, initialTemplate, initialDifficulty, runtimeStatus, }: ControlsProps) { const [seed, setSeed] = useState(initialSeed?.toString() ?? '42'); const [template, setTemplate] = useState(initialTemplate ?? 'ml_benchmark'); const [difficulty, setDifficulty] = useState(initialDifficulty ?? 'medium'); const [backendStatus, setBackendStatus] = useState<'checking' | 'ok' | 'error'>('checking'); const [backendMessage, setBackendMessage] = useState('Checking backend connection...'); useEffect(() => { if (initialSeed !== undefined) { setSeed(initialSeed.toString()); } }, [initialSeed]); useEffect(() => { if (initialTemplate) { setTemplate(initialTemplate); } }, [initialTemplate]); useEffect(() => { if (initialDifficulty) { setDifficulty(initialDifficulty); } }, [initialDifficulty]); useEffect(() => { let cancelled = false; async function checkBackend() { setBackendStatus('checking'); setBackendMessage('Checking backend connection...'); try { await healthCheck(); if (!cancelled) { setBackendStatus('ok'); setBackendMessage('Backend connected. The live environment is ready.'); } } catch (error) { if (!cancelled) { const message = error instanceof Error ? error.message : 'Backend unavailable.'; setBackendStatus('error'); setBackendMessage(message); } } } void checkBackend(); return () => { cancelled = true; }; }, []); function randomSeed() { sfx.click(); setSeed(Math.floor(Math.random() * 10000).toString()); } function handleStart() { sfx.click(); onStart({ seed: seed ? parseInt(seed, 10) : undefined, template, difficulty }); } return (

Replication Setup

Choose the seeded paper-derived benchmark that becomes this negotiation environment.

{backendMessage}

{runtimeStatus && (

Scientist runtime: {runtimeStatus.scientist_runtime} {' '}({runtimeStatus.scientist_model})

)}
{DIFFICULTIES.map((d) => ( ))}
setSeed(e.target.value)} disabled={disabled || episodeActive} placeholder="Random" className="w-full rounded-md border border-border bg-background px-2 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50" />
{episodeActive && onStep && ( )}
); }