import { useEffect, useState, type FormEvent } from "react"; import { memoryApi } from "../api/endpoints"; import type { MemoryNote } from "../api/types"; import { ConfirmButton, errorMessage } from "./ui"; const EXAMPLES = [ { key: "audience", value: "" }, { key: "tone", value: "" }, { key: "avoid", value: "" }, ]; /** The writer's standing notes: what the research chat always knows, in every notebook. The chat also adds * notes on its own when the writer says something lasting, and every note can be edited or removed here. */ export function MemoryNotes() { const [notes, setNotes] = useState(null); const [limit, setLimit] = useState(20); const [key, setKey] = useState(""); const [value, setValue] = useState(""); const [error, setError] = useState(null); const load = () => memoryApi.list().then( (d) => { setNotes(d.items); setLimit(d.limit); }, () => setError("Could not load your notes."), ); useEffect(() => { void load(); }, []); const add = async (e: FormEvent) => { e.preventDefault(); setError(null); try { await memoryApi.put(key, value); setKey(""); setValue(""); await load(); } catch (err) { setError(errorMessage(err)); } }; const edit = async (note: MemoryNote, next: string) => { if (next.trim() === note.value) return; setError(null); try { await memoryApi.put(note.key, next); await load(); } catch (err) { setError(errorMessage(err)); await load(); } }; const remove = async (note: MemoryNote) => { await memoryApi.remove(note.key); await load(); }; return ( <>

Notes the assistant reads before every answer, in every notebook. It saves new ones when you tell it something lasting, like who you write for. Your posts stay the only source it cites.

{notes && notes.length === 0 &&

No notes yet.

} {notes?.map((n) => (
{n.key} {n.source === "auto" ? "saved from chat" : "written by you"} remove(n)}>Delete
edit(n, e.target.value)} />
))}
{EXAMPLES.map((x) => ( ))}
{notes?.length ?? 0} of {limit} notes
{error &&

{error}

} ); }