}
title="Delete persona"
description={`Remove "${draft.name || "this persona"}" permanently? Students will no longer see it.`}
confirmLabel="Delete"
destructive
onConfirm={onDelete}
/>
change("description", e.target.value)}
placeholder="One sentence shown in the dropdown"
/>
{errorMsg &&
{errorMsg}
}
)}
);
}
// ── Main editor ───────────────────────────────────────────────────────────────
export function PersonaEditor() {
const [personas, setPersonas] = useState([]);
async function load() {
try {
const r = await fetch("/api/personas");
const d = await r.json();
setPersonas(d.personas ?? []);
} catch {}
}
useEffect(() => { load(); }, []);
// Save a single updated persona
async function saveOne(updated: Persona) {
const next = personas.map((p) => (p.id === updated.id ? updated : p));
const r = await fetch("/api/personas", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(next),
});
if (!r.ok) throw new Error(await r.text());
const data = await r.json();
setPersonas(data.personas);
}
function remove(id: string) {
const next = personas.filter((p) => p.id !== id);
fetch("/api/personas", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(next),
})
.then((r) => r.json())
.then((d) => setPersonas(d.personas ?? next))
.catch(() => setPersonas(next));
}
function addNew() {
setPersonas((prev) => [
...prev,
{ id: uid(), name: "", description: "", prompt: "" },
]);
}
async function reset() {
const r = await fetch("/api/personas/reset", { method: "POST" });
if (!r.ok) throw new Error(await r.text());
const data = await r.json();
setPersonas(data.personas);
}
return (
Personas
Reset to defaults
}
title="Reset personas?"
description="All custom personas will be replaced with the bundled defaults. This cannot be undone."
confirmLabel="Reset"
destructive
onConfirm={reset}
/>
Each card saves individually. Changes are written to{" "}
personas.json and synced
to your HF Dataset.