/** Search only visible user/assistant text, never tool arguments or hidden reasoning. */ export function matchHistoryText(messages: unknown[], query: string): string | undefined { const needle = query.trim().toLocaleLowerCase(); if (!needle) return; for (const value of messages) { if (!value || typeof value !== "object") continue; const message = value as Record; if (message.role !== "user" && message.role !== "assistant") continue; const parts = Array.isArray(message.parts) ? message.parts : [message]; for (const value of parts) { if (!value || typeof value !== "object") continue; const part = value as Record; if (part.type !== "text" || typeof part.text !== "string") continue; const index = part.text.toLocaleLowerCase().indexOf(needle); if (index < 0) continue; const start = Math.max(0, index - 36); const end = Math.min(part.text.length, index + needle.length + 80); return `${start ? "…" : ""}${part.text.slice(start, end).replace(/\s+/g, " ")}${end < part.text.length ? "…" : ""}`; } } }