import { useCallback } from 'react' import { BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, ResponsiveContainer, Cell, PieChart, Pie, Legend, } from 'recharts' import { RefreshCw, Zap, Database, TrendingUp, Clock } from 'lucide-react' import Card from '../components/ui/Card' import Button from '../components/ui/Button' import Spinner from '../components/ui/Spinner' import { usePolling } from '../hooks/usePolling' import { getForgeQueue, getForgeStats } from '../api/client' const NEON = '#00d4ff' const GREEN = '#00ff88' const RED = '#ff3366' const ORANGE = '#ff9900' function CustomTooltip({ active, payload, label }) { if (!active || !payload?.length) return null return (

{label}

{payload.map(p => (

{p.name}: {p.value}

))}
) } const QUEUE_ZONES = [ { key: 'learnable_count', label: 'Learnable', color: GREEN, desc: '0.20 ≤ pass@k ≤ 0.85' }, { key: 'too_easy_count', label: 'Too Easy', color: NEON, desc: 'pass@k > 0.85' }, { key: 'too_hard_count', label: 'Too Hard', color: RED, desc: 'pass@k < 0.20' }, { key: 'pending_estimation_count', label: 'Pending Estimation', color: ORANGE, desc: 'awaiting pass@k estimate' }, ] export default function ForgeQueue() { const qFetcher = useCallback(() => getForgeQueue(), []) const sFetcher = useCallback(() => getForgeStats(), []) const { data: queue, loading: qLoad, refresh: qRefresh } = usePolling(qFetcher, 4000) const { data: stats, loading: sLoad } = usePolling(sFetcher, 4000) const barData = QUEUE_ZONES.map(z => ({ name: z.label, count: queue?.[z.key] ?? 0, color: z.color, })) const pieData = QUEUE_ZONES .map(z => ({ name: z.label, value: queue?.[z.key] ?? 0, color: z.color })) .filter(d => d.value > 0) const totalTasks = (queue?.seed_task_count ?? 0) + (queue?.generated_task_count ?? 0) return (

Forge Queue

Curriculum scheduler - adaptive task difficulty management

{/* Zone cards */}
{QUEUE_ZONES.map(z => (
{z.label} {queue?.replenishment_triggered && z.key === 'learnable_count' && ( replenishing )}
{queue ? queue[z.key] ?? 0 : }
{z.desc}
))}
{/* Source cards */}
{[ { icon: Database, label: 'Seed Tasks', key: 'seed_task_count', color: NEON }, { icon: Zap, label: 'Generated Tasks', key: 'generated_task_count', color: GREEN }, { icon: TrendingUp, label: 'Acceptance Rate', key: null, color: ORANGE }, { icon: Clock, label: 'Total Episodes', key: null, color: '#7080aa' }, ].map(({ icon: Icon, label, key, color }) => { let value if (key) value = queue?.[key] ?? (qLoad ? null : 0) else if (label === 'Acceptance Rate') value = stats?.generator_acceptance_rate != null ? `${(stats.generator_acceptance_rate * 100).toFixed(1)}%` : (sLoad ? null : 'n/a') else value = stats?.total_episodes ?? (sLoad ? null : 0) return (
{label}
{value ?? }
) })}
{/* Bar chart */}

Queue Counts by Zone

{barData.some(d => d.count > 0) ? ( } /> {barData.map((d, i) => ( ))} ) : (
{qLoad ? : 'no data'}
)}
{/* Pie */}

Zone Distribution

{pieData.length > 0 ? ( <> {pieData.map((d, i) => ( ))} } />
{pieData.map(d => ( {d.name}: {d.value} ))}
) : (
{qLoad ? : 'no data'}
)}
{/* Learnable threshold reference */}

Difficulty Thresholds

too-hard
learnable zone (0.20 – 0.85)
too-easy
{/* Markers */}
0.000.200.851.00
) }