'use client'; import { useEffect, useState } from 'react'; import { ListTodo, Send, Loader2, RefreshCw, Clock, CheckCircle2, XCircle, Zap, AlertTriangle } from 'lucide-react'; import { api, type QueueJob, type QueueStatus } from '@/lib/api'; const PRIORITY_LABELS = ['CRITICAL', 'HIGH', 'NORMAL', 'LOW']; const PRIORITY_COLORS = [ 'bg-red-500/20 text-red-300 border-red-500/30', 'bg-orange-500/20 text-orange-300 border-orange-500/30', 'bg-blue-500/20 text-blue-300 border-blue-500/30', 'bg-slate-500/20 text-slate-300 border-slate-500/30', ]; function PriorityBadge({ priority }: { priority: number }) { const cls = PRIORITY_COLORS[priority] ?? PRIORITY_COLORS[2]; return ( {PRIORITY_LABELS[priority] ?? 'NORMAL'} ); } function JobStatusIcon({ status }: { status: string }) { if (status === 'COMPLETE') return ; if (status === 'FAILED') return ; if (status === 'RUNNING') return ; if (status === 'CANCELLED') return ; return ; } export default function QueuePanel() { const [status, setStatus] = useState(null); const [jobs, setJobs] = useState([]); const [loading, setLoading] = useState(false); const [err, setErr] = useState(null); // Submit form const [prompt, setPrompt] = useState(''); const [priority, setPriority] = useState(2); const [submitting, setSubmitting] = useState(false); const reload = async () => { setLoading(true); try { const [st, jb] = await Promise.all([api.queueStatus(), api.listQueueJobs()]); setStatus(st); setJobs(jb.jobs); setErr(null); } catch (e: any) { setErr(e.message); } finally { setLoading(false); } }; useEffect(() => { reload(); const t = setInterval(reload, 3000); return () => clearInterval(t); }, []); const submit = async (e: React.FormEvent) => { e.preventDefault(); if (!prompt.trim()) return; setSubmitting(true); try { const title = prompt.split('\n')[0].slice(0, 80); await api.queueSubmit(title, prompt, priority); setPrompt(''); await reload(); } catch (e: any) { setErr(e.message); } finally { setSubmitting(false); } }; return ( {/* Stats row */} Queue Depth {status?.queue_depth ?? '—'} Running {status?.running_jobs ?? '—'} Backend {status?.backend ?? '—'} {/* Submit to queue */} Submit to Queue setPrompt(e.target.value)} rows={3} placeholder="Describe the task to queue..." className="w-full rounded-lg border border-white/10 bg-slate-800/60 p-3 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500" /> Priority: setPriority(Number(e.target.value))} className="text-xs bg-slate-700 border border-slate-600 text-slate-200 rounded px-2 py-1 focus:outline-none" > 0 — CRITICAL 1 — HIGH 2 — NORMAL 3 — LOW {submitting ? : } Queue Task {/* Error */} {err && ( {err} )} {/* Queued jobs */} Queued Jobs {jobs.length > 0 && ( {jobs.length} )} Refresh {jobs.length === 0 ? ( No jobs in queue. ) : ( {jobs.map(job => ( #{job.task_id} {job.prompt.slice(0, 60)} job: {job.job_id} · status: {job.status} {job.retry_count > 0 && ` · retries: ${job.retry_count}`} ))} )} ); }
Queue Depth
{status?.queue_depth ?? '—'}
Running
{status?.running_jobs ?? '—'}
Backend
No jobs in queue.
job: {job.job_id} · status: {job.status} {job.retry_count > 0 && ` · retries: ${job.retry_count}`}