import { useState } from "react"; export default function MessageList({ messages }) { const [expandedChunks, setExpandedChunks] = useState({}); const toggleChunks = (idx) => { setExpandedChunks((prev) => ({ ...prev, [idx]: !prev[idx] })); }; if (!messages.length) { return (
💬

Ask a question about your document

); } return (
{messages.map((msg, i) => (
{/* Status line shown while waiting */} {msg.status && (
{msg.status}
)} {/* Answer text */} {msg.content ?

{msg.content}

: !msg.status &&

Thinking…

} {/* Retrieved chunks */} {msg.chunks?.length > 0 && (
{expandedChunks[i] && msg.chunks.map((chunk, j) => { const score = typeof chunk.score === "number" ? chunk.score : typeof chunk.raw_score === "number" ? chunk.raw_score : null; const rawScore = typeof chunk.raw_score === "number" ? chunk.raw_score : null; const scoreColor = score === null ? "text-gray-400" : score >= 0.75 ? "text-emerald-600 font-semibold" : score >= 0.5 ? "text-yellow-600" : score > 0 ? "text-red-500" : "text-gray-400"; const scoreLabel = score === null ? "score unavailable" : `${(score * 100).toFixed(1)} similarity`; const rawScoreLabel = rawScore === null || rawScore === score ? null : `raw similarity ${(rawScore * 100).toFixed(1)}`; return (
#{j + 1} {scoreLabel} {rawScoreLabel ? ` · ${rawScoreLabel}` : ""}
{chunk.section_heading && (

{chunk.section_heading}

)}

{chunk.text}

); })}
)} {/* Timings */} {msg.timings && Object.keys(msg.timings).length > 0 && (

Pipeline Timings

{Object.entries(msg.timings).map(([key, val]) => (
{key.replace("_ms", "").replace(/_/g, " ")} {Math.round(Number(val))}ms
))}
)}
))}
); }