import { useState, useRef, useEffect } from "react"; import { Send, Sparkles } from "lucide-react"; import api from "@/lib/api"; const SUGGESTIONS = [ "Why is the hallucination risk highest at step 1?", "Did internal state at step 1 causally affect step 3?", "Which features drift the most across the trajectory?", "Summarize the cross-step patch matrix findings.", ]; export default function CircuitQueryBox({ runId, trajectoryReady }) { const [msgs, setMsgs] = useState([]); const [val, setVal] = useState(""); const [busy, setBusy] = useState(false); const endRef = useRef(null); useEffect(() => { if (!runId) return; api.listQueries(runId) .then((d) => { const ordered = (d.queries || []).slice().reverse(); setMsgs( ordered.flatMap((q) => [ { role: "user", text: q.query }, { role: "assistant", text: q.answer }, ]), ); }) .catch(() => {}); }, [runId]); useEffect(() => { endRef.current?.scrollIntoView({ behavior: "smooth" }); }, [msgs.length]); async function send(text) { const t = (text ?? val).trim(); if (!t || !trajectoryReady) return; setMsgs((m) => [...m, { role: "user", text: t }]); setVal(""); setBusy(true); try { const res = await api.query(runId, { query: t }); setMsgs((m) => [...m, { role: "assistant", text: res.answer }]); } catch (e) { setMsgs((m) => [ ...m, { role: "assistant", text: `[error: ${e.message}]` }, ]); } finally { setBusy(false); } } return (
NL circuit query grounded in run artifacts • claude-sonnet-4-5
{msgs.length === 0 ? (
Ask any question about the trajectory. Suggestions:
{SUGGESTIONS.map((s, i) => ( ))}
) : ( msgs.map((m, i) => (
{m.role === "user" ? "you" : "neuroscope"}
{m.text}
)) )} {busy && (
thinking… (model + sae + patch context being summarized for the LLM)
)}
setVal(e.target.value)} onKeyDown={(e) => e.key === "Enter" && send()} placeholder={ trajectoryReady ? "e.g. why is risk highest at step 3?" : "trajectory still running…" } disabled={!trajectoryReady || busy} className="flex-1 rounded-md border bg-transparent px-2 py-1.5 font-mono text-[12px] text-[color:var(--ns-fg-primary)] placeholder:text-[color:var(--ns-fg-faint)] focus:outline-none" style={{ borderColor: "var(--ns-border-subtle)" }} data-testid="nl-circuit-query-input" />
); }