// Manual add-case modal (used from Evals → Dataset → Cases tab) // Reuses styles from evals-styles.css function AddCaseModal({ dataset, toolOptions = [], onClose, onAdded }) { const [input, setInput] = React.useState(""); const [expected, setExpected] = React.useState(""); const [expectedTools, setExpectedTools] = React.useState([]); const [toolName, setToolName] = React.useState(""); const [tags, setTags] = React.useState(""); const addTool = (value) => { const name = String(value || "").trim(); if (!name) return; setExpectedTools((current) => current.includes(name) ? current : [...current, name]); setToolName(""); }; const removeTool = (name) => setExpectedTools((current) => current.filter((item) => item !== name)); // Esc to close React.useEffect(() => { const fn = (e) => { if (e.key === "Escape") onClose(); }; document.addEventListener("keydown", fn); return () => document.removeEventListener("keydown", fn); }, [onClose]); const save = async () => { if (!input.trim()) return; try { const apiCase = await window.api.addDatasetCase(dataset.id, { input: input.trim(), expected: expected.trim() || null, tools: expectedTools, tags: tags.split(",").map((t) => t.trim()).filter(Boolean), source: { type: "manual" }, }); onAdded?.({ dataset, case: apiCase }); pushToast({ content: Added to {dataset.name}, duration: 3000 }); } catch (err) { alert("Save case failed: " + (err.message || err)); } onClose(); }; return (
{ if (e.target === e.currentTarget) onClose(); }}>
e.stopPropagation()}>

New case

Adding to {dataset.name}
Input — the user message · required