import React, { useCallback, useRef, useState } from 'react' import { api } from '../api' import type { Task } from '../types' import { panelStyle, titleStyle } from '../App' interface Props { tasks: Task[]; onComplete: () => void } interface RunResult { task_id: string; reward: number; steps: number; status: 'pending' | 'running' | 'done' | 'error'; log: string[] } const STRATEGIES = [ { id: 'greedy', label: 'Greedy Debugger', desc: 'Searches logs then reads the most suspicious file and patches it.' }, { id: 'systematic', label: 'Systematic SRE', desc: 'Lists files, reads all, diagnoses, then patches with full context.' }, { id: 'fast', label: 'Speed Runner', desc: 'Minimal steps — grep errors, read one file, submit patch immediately.' }, ] function buildActions(taskId: string, strategy: string): Array> { if (strategy === 'fast') { return [ { agent: 'debugger', action_type: 'search_logs', command: 'ERROR' }, { agent: 'debugger', action_type: 'list_files', file_path: '' }, { agent: 'coder', action_type: 'read_file', file_path: taskId === 'memory_leak' ? 'api/users.js' : taskId === 'db_deadlock' ? 'services/transfer.js' : taskId === 'cascade_failure' ? 'service-a/cache.js' : taskId === 'cpu_spike' ? 'workers/dataProcessor.js' : 'middleware/auth.js' }, { agent: 'coder', action_type: 'submit_patch', file_path: taskId === 'memory_leak' ? 'api/users.js' : taskId === 'db_deadlock' ? 'services/transfer.js' : taskId === 'cascade_failure' ? 'service-a/cache.js' : taskId === 'cpu_spike' ? 'workers/dataProcessor.js' : 'middleware/auth.js', patch_description: 'Fast patch attempt' }, ] } if (strategy === 'greedy') { return [ { agent: 'debugger', action_type: 'terminal', command: 'tail -n 20' }, { agent: 'debugger', action_type: 'search_logs', command: 'ERROR' }, { agent: 'debugger', action_type: 'list_files', file_path: '' }, { agent: 'coder', action_type: 'read_file', file_path: taskId === 'memory_leak' ? 'api/users.js' : taskId === 'db_deadlock' ? 'services/transfer.js' : taskId === 'cascade_failure' ? 'service-a/cache.js' : taskId === 'cpu_spike' ? 'workers/dataProcessor.js' : 'middleware/auth.js' }, { agent: 'coder', action_type: 'submit_patch', file_path: taskId === 'memory_leak' ? 'api/users.js' : taskId === 'db_deadlock' ? 'services/transfer.js' : taskId === 'cascade_failure' ? 'service-a/cache.js' : taskId === 'cpu_spike' ? 'workers/dataProcessor.js' : 'middleware/auth.js', patch_description: 'Greedy patch' }, ] } // systematic return [ { agent: 'coordinator', action_type: 'terminal', command: 'htop' }, { agent: 'debugger', action_type: 'terminal', command: 'tail -n 20' }, { agent: 'debugger', action_type: 'search_logs', command: 'ERROR' }, { agent: 'debugger', action_type: 'list_files', file_path: '' }, { agent: 'coder', action_type: 'read_file', file_path: taskId === 'memory_leak' ? 'api/users.js' : taskId === 'db_deadlock' ? 'services/transfer.js' : taskId === 'cascade_failure' ? 'service-a/cache.js' : taskId === 'cpu_spike' ? 'workers/dataProcessor.js' : 'middleware/auth.js' }, { agent: 'coder', action_type: 'submit_patch', file_path: taskId === 'memory_leak' ? 'api/users.js' : taskId === 'db_deadlock' ? 'services/transfer.js' : taskId === 'cascade_failure' ? 'service-a/cache.js' : taskId === 'cpu_spike' ? 'workers/dataProcessor.js' : 'middleware/auth.js', patch_description: 'Systematic patch after full analysis' }, ] } export function AutoRunPanel({ tasks, onComplete }: Props) { const [strategy, setStrategy] = useState('systematic') const [selectedTasks, setSelectedTasks] = useState(['memory_leak', 'db_deadlock', 'cascade_failure']) const [results, setResults] = useState([]) const [running, setRunning] = useState(false) const [delay, setDelay] = useState(400) const stopRef = useRef(false) const toggleTask = (id: string) => setSelectedTasks(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]) const runAll = useCallback(async () => { setRunning(true) stopRef.current = false const init: RunResult[] = selectedTasks.map(t => ({ task_id: t, reward: 0, steps: 0, status: 'pending', log: [] })) setResults(init) for (let i = 0; i < selectedTasks.length; i++) { if (stopRef.current) break const tid = selectedTasks[i] setResults(r => r.map((x, j) => j === i ? { ...x, status: 'running' } : x)) try { await api.reset(tid) const actions = buildActions(tid, strategy) let lastReward = 0 let steps = 0 const log: string[] = [`[START] task=${tid} strategy=${strategy}`] for (const action of actions) { if (stopRef.current) break await new Promise(r => setTimeout(r, delay)) const result = await api.step(action) steps++ log.push(`[STEP ${steps}] ${action.action_type} → ${result.done ? `DONE reward=${result.reward?.total?.toFixed(3)}` : 'ok'}`) setResults(r => r.map((x, j) => j === i ? { ...x, steps, log: [...log] } : x)) if (result.done) { lastReward = result.reward?.total || 0; break } } setResults(r => r.map((x, j) => j === i ? { ...x, reward: lastReward, steps, status: 'done', log } : x)) } catch (e) { setResults(r => r.map((x, j) => j === i ? { ...x, status: 'error', log: [`Error: ${e}`] } : x)) } } setRunning(false) onComplete() }, [selectedTasks, strategy, delay, onComplete]) const avgReward = results.filter(r => r.status === 'done').reduce((s, r) => s + r.reward, 0) / Math.max(1, results.filter(r => r.status === 'done').length) return (
{/* Config */}
🤖 Auto-Run Configuration
{STRATEGIES.map(s => (
setStrategy(s.id)} style={{ padding: '0.5rem 0.6rem', borderRadius: '0.4rem', cursor: 'pointer', marginBottom: '0.3rem', border: `1px solid ${strategy === s.id ? '#3b82f6' : '#1e2d4a'}`, background: strategy === s.id ? '#1e3a5f22' : 'transparent', }}>
{s.label}
{s.desc}
))}
{tasks.map(t => ( ))}
setDelay(Number(e.target.value))} style={{ width: '100%', accentColor: '#3b82f6' }} />
{running && ( )}
{/* Results */}
{results.length > 0 && (
📊 Run Results
{results.map((r, i) => { const color = r.status === 'done' ? (r.reward >= 0.7 ? '#22c55e' : r.reward >= 0.4 ? '#f59e0b' : '#ef4444') : r.status === 'running' ? '#60a5fa' : r.status === 'error' ? '#ef4444' : '#334155' return (
{r.task_id.replace('_', ' ')} {r.status === 'done' ? `${(r.reward * 100).toFixed(1)}%` : r.status === 'running' ? '⏳' : r.status === 'error' ? '❌' : '—'}
{r.status !== 'pending' && (
{r.log.map((l, j) => (
{l}
))}
)}
) })} {results.some(r => r.status === 'done') && (
Average Reward
= 0.7 ? '#22c55e' : avgReward >= 0.4 ? '#f59e0b' : '#ef4444' }}> {(avgReward * 100).toFixed(1)}%
)}
)}
) }