"use client" import { useState, useEffect, useRef } from "react" import { useRouter } from "next/navigation" import Link from "next/link" import { getProviders, getBenchmarks, getModels, startCompare, type SelectionMode, type SampleType, type SamplingConfig, } from "@/lib/api" import { SingleSelect } from "@/components/single-select" import { MultiSelect } from "@/components/multi-select" export default function NewComparePage() { const router = useRouter() const [loading, setLoading] = useState(true) const [submitting, setSubmitting] = useState(false) const [error, setError] = useState(null) const [providers, setProviders] = useState<{ name: string; displayName: string }[]>([]) const [benchmarks, setBenchmarks] = useState<{ name: string; displayName: string }[]>([]) const [models, setModels] = useState({}) const [form, setForm] = useState({ providers: [] as string[], benchmark: "", compareId: "", judgeModel: "gpt-4o", answeringModel: "gpt-4o", selectionMode: "full" as SelectionMode, sampleType: "consecutive" as SampleType, perCategory: "2", limit: "", }) const [editingCompareId, setEditingCompareId] = useState(false) const compareIdInputRef = useRef(null) useEffect(() => { loadOptions() }, []) useEffect(() => { if (editingCompareId && compareIdInputRef.current) { compareIdInputRef.current.focus() compareIdInputRef.current.select() } }, [editingCompareId]) async function loadOptions() { try { const [providersRes, benchmarksRes, modelsRes] = await Promise.all([ getProviders(), getBenchmarks(), getModels(), ]) setProviders(providersRes.providers) setBenchmarks(benchmarksRes.benchmarks) setModels(modelsRes.models) if (benchmarksRes.benchmarks.length > 0) { setForm((f) => ({ ...f, benchmark: benchmarksRes.benchmarks[0].name })) } } catch (e) { setError(e instanceof Error ? e.message : "Failed to load options") } finally { setLoading(false) } } function generateCompareId() { const now = new Date() const date = now.toISOString().slice(0, 10).replace(/-/g, "") const time = now.toISOString().slice(11, 19).replace(/:/g, "") return `compare-${date}-${time}` } const displayCompareId = form.compareId || generateCompareId() async function handleSubmit(e: React.FormEvent) { e.preventDefault() // Validate providers if (form.providers.length < 2) { setError("Please select at least 2 providers for comparison") return } const compareId = form.compareId || generateCompareId() let sampling: SamplingConfig | undefined if (form.selectionMode === "full") { sampling = { mode: "full" } } else if (form.selectionMode === "sample") { const perCategoryValue = parseInt(form.perCategory) || 2 sampling = { mode: "sample", sampleType: form.sampleType, perCategory: perCategoryValue, } } else if (form.selectionMode === "limit" && form.limit) { sampling = { mode: "limit", limit: parseInt(form.limit), } } try { setSubmitting(true) setError(null) await startCompare({ providers: form.providers, benchmark: form.benchmark, compareId, judgeModel: form.judgeModel, answeringModel: form.answeringModel, sampling, }) router.push(`/compare`) } catch (e) { setError(e instanceof Error ? e.message : "Failed to start comparison") setSubmitting(false) } } const allModels = [...Object.values(models).flat()] as { alias: string; displayName: string }[] const providerOptions = providers.map((p) => ({ value: p.name, label: p.displayName })) const benchmarkOptions = benchmarks.map((b) => ({ value: b.name, label: b.displayName })) const modelOptions = allModels.map((m) => ({ value: m.alias, label: m.displayName || m.alias })) if (loading) { return (
) } return (
Compare / New Comparison
{!editingCompareId ? ( ) : ( setForm({ ...form, compareId: e.target.value })} onBlur={() => setEditingCompareId(false)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === "Escape") { setEditingCompareId(false) } }} className="w-full px-3 py-2 text-sm bg-[#222222] border border-[#444444] rounded text-text-primary placeholder-text-muted focus:outline-none focus:border-accent font-mono lowercase" /> )} {form.providers.length > 0 && (
Providers:{" "} {form.providers .map((providerId) => { const provider = providers.find((p) => p.name === providerId) return provider?.displayName || providerId }) .join(", ")}
)}
setForm({ ...form, providers: selected })} placeholder="Select at least 2 providers..." />
{form.providers.length > 0 && form.providers.length < 2 && (

At least 2 providers are required for comparison

)}
setForm({ ...form, benchmark: value })} placeholder="Select benchmark" />
setForm({ ...form, judgeModel: value })} placeholder="Select model" />
setForm({ ...form, answeringModel: value })} placeholder="Select model" />
{(["full", "sample", "limit"] as SelectionMode[]).map((mode) => { const isSelected = form.selectionMode === mode const labels = { full: "Full", sample: "Sample", limit: "Limit" } return ( ) })}
{form.selectionMode === "sample" && (
setForm({ ...form, perCategory: e.target.value })} placeholder="2" min="1" /> per category
{(["consecutive", "random"] as SampleType[]).map((type) => { const isSelected = form.sampleType === type return ( ) })}
)} {form.selectionMode === "limit" && (
setForm({ ...form, limit: e.target.value })} placeholder="e.g. 100" min="1" />
)}
{error && (
{error}
)}
Cancel
) }