"use client"; import { useEffect, useRef, useState, type ReactNode } from "react"; import { BookOpenIcon } from "lucide-react"; import { graphContextOfMessage, type GraphContextData } from "@/src/core"; import { formatTokens } from "@/components/usage-format"; /** * The knowledge-context delivery marker (vision-context-injection.md): the * quiet transcript line for the injected prior-knowledge block — CLICKABLE * (owner observability ask, 2026-09-15): the popover shows exactly which * propositions were delivered, IN DELIVERY ORDER (most similar first — * the order the selection filled the budget), each with its folded current * understanding level. The record part is the audit trail; this makes it * readable at the seam where it landed. * * Same quiet-line discipline as the SystemLine family (centered, muted, * small); same popover discipline as the stats-detail (close on outside * pointerdown + Escape, anchored below the marker). */ export function GraphContextMarker({ message, testId = "graph-context", }: { /** The steer message (marker-only user message). */ message: { parts: ReadonlyArray<{ type: string; data?: unknown }> }; testId?: string; }) { const [open, setOpen] = useState(false); const data = graphContextOfMessage(message); const ref = useRef(null); useEffect(() => { if (!open) return; const onPointerDown = (e: PointerEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false); }; const onKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") setOpen(false); }; document.addEventListener("pointerdown", onPointerDown); document.addEventListener("keydown", onKeyDown); return () => { document.removeEventListener("pointerdown", onPointerDown); document.removeEventListener("keydown", onKeyDown); }; }, [open]); const summary = data ? `Graph context — ~${formatTokens(data.tokens)} · ${data.propositions.length} propositions` : "Graph context"; return (
{open && data && }
); } /** The popover body — exported for render tests. Delivery order preserved. */ export function GraphContextList({ data }: { data: GraphContextData }): ReactNode { return (
Prior knowledge delivered ~{formatTokens(data.tokens)} tok of {data.budget} budget

Most similar first — the order the budget filled. The tags are your current understanding level for each proposition.

    {data.propositions.map((p, i) => (
  1. {i + 1}. {p.level && ( {p.level} )} {p.statement}
  2. ))}
); }