diff --git a/src/components/ops/memory-panel.tsx b/src/components/ops/memory-panel.tsx index 6b74b95..70a259c 100644 --- a/src/components/ops/memory-panel.tsx +++ b/src/components/ops/memory-panel.tsx @@ -15,6 +15,18 @@ import { toast } from "sonner"; import { MEMORY_CATEGORIES } from "@/lib/types"; import { IconButton, PanelFrame, RefreshButton, SectionTitle } from "./shared"; + +/** Keys the server generates when the caller supplied none. */ +function isGeneratedKey(key: string): boolean { + return /^memory_[0-9a-f-]{36}$/i.test(key); +} + +/** Enough of a memory to tell one row from another in a label. */ +function previewOf(content: string): string { + const flat = content.replace(/\s+/g, " ").trim(); + return flat.length > 48 ? `${flat.slice(0, 48)}…` : flat; +} + export function MemoryPanel() { const { data, loading, error, refresh } = useAsync(() => api.memory(100), []); const [content, setContent] = React.useState(""); @@ -46,6 +58,17 @@ export function MemoryPanel() { } }; + const copyKey = async (key: string) => { + try { + await navigator.clipboard.writeText(key); + toast.success("Key copied"); + } catch { + // Clipboard is blocked outside a secure context; show the key so it can + // still be selected by hand rather than failing silently. + toast.message(key); + } + }; + const del = async () => { const key = pendingForget?.key; if (!key) return; @@ -65,10 +88,11 @@ export function MemoryPanel() { return (
}> - Memory entries{" "} + Memory entries {data && ( - · {data.count} + {" · "} + {data.count} {data.total > data.count ? ` of ${data.total}` : ""} )} @@ -119,8 +143,8 @@ export function MemoryPanel() { setPendingForget({ key: e.key, content: e.content })} disabled={w} - title="Forget" - aria-label="Forget this memory" + title={`Forget "${previewOf(e.content)}"`} + aria-label={`Forget "${previewOf(e.content)}"`} className="hover:bg-destructive/10 hover:text-destructive disabled:opacity-50" > {w ? : } @@ -128,9 +152,20 @@ export function MemoryPanel() {
- {e.key} - · {relativeTime(e.timestamp)} + · + {/* A generated key is an address, not a name: it is 43 + characters of UUID that only matters when reaching this + entry from the API or CLI. Keep it available — clicking + copies it — without letting it outweigh the content. */} +
);