import { memo, useEffect, useRef, useState } from "react"; import { Brain } from "lucide-react"; import { truncateText } from "../utils/format"; import type { ReasoningPart } from "../types/parts"; import { Markdown } from "../markdown/markdown"; import { RunRowShell } from "./run-row-shell"; import { ExpandableContent } from "./expandable-content"; export interface InlineThinkingItemProps { part: ReasoningPart; defaultOpen?: boolean; autoCollapse?: boolean; className?: string; contentClassName?: string; } export const InlineThinkingItem = memo( ({ part, defaultOpen = false, autoCollapse = true, className, contentClassName, }: InlineThinkingItemProps) => { const [open, setOpen] = useState(defaultOpen); const autoCollapsedRef = useRef(false); const startTime = part.time?.start; const endTime = part.time?.end; const durationMs = startTime != null && endTime != null ? endTime - startTime : undefined; const isActive = startTime != null && endTime == null; const preview = part.text ? truncateText(part.text, 120) : undefined; useEffect(() => { if (isActive) { autoCollapsedRef.current = false; setOpen(true); return; } if (autoCollapse && !autoCollapsedRef.current && durationMs != null) { const timer = window.setTimeout(() => { setOpen(false); autoCollapsedRef.current = true; }, 900); return () => window.clearTimeout(timer); } }, [autoCollapse, durationMs, isActive]); return ( } title={isActive ? "Thinking…" : "Reasoning"} description={preview} status={isActive ? "running" : "idle"} startTime={startTime} durationMs={durationMs} open={open} onOpenChange={setOpen} className={className} > {part.text ? (
{part.text}
) : (
No reasoning text provided.
)}
); }, ); InlineThinkingItem.displayName = "InlineThinkingItem";