"use client"; import { useState } from "react"; import { Wrench, ChevronDown, ChevronRight, Lightbulb } from "lucide-react"; import type { Message, ToolCall } from "@/lib/types"; type Verbosity = "compact" | "normal" | "full"; interface Props { message: Message; toolResults: Map; verbosity?: Verbosity; showTimestamp?: boolean; } function ReasoningBlock({ text }: { text: string }) { const [open, setOpen] = useState(false); const preview = text.slice(0, 120); return (
{open ? (
          {text}
        
) : (

{preview}{text.length > 120 ? "..." : ""}

)}
); } function ToolCallBlock({ tc, result, defaultOpen, showResult }: { tc: ToolCall; result?: { name: string; content: string }; defaultOpen: boolean; showResult: boolean }) { const [open, setOpen] = useState(defaultOpen); let args: Record = {}; try { args = JSON.parse(tc.function.arguments); } catch {} return (
{open && (
            {JSON.stringify(args, null, 2)}
          
{showResult && result && (
              {result.content.slice(0, 2000)}{result.content.length > 2000 ? "..." : ""}
            
)}
)}
); } export function MessageBubble({ message, toolResults, verbosity = "normal", showTimestamp = false }: Props) { const isUser = message.role === "user"; const content = message.content || ""; const reasoning = message.reasoning || ""; let toolCalls: ToolCall[] = []; if (message.tool_calls) { try { toolCalls = JSON.parse(message.tool_calls); } catch {} } if (!content && toolCalls.length === 0 && !reasoning) return null; const showTools = verbosity !== "compact" && toolCalls.length > 0; const showReasoning = verbosity === "full" && reasoning; const expandTools = verbosity === "full"; return (
{/* Reasoning / thinking */} {showReasoning && } {/* Content */} {content && (

{verbosity === "compact" && content.length > 300 ? content.slice(0, 300) + "..." : content}

)} {/* Tool calls */} {showTools && (
{expandTools ? ( toolCalls.map((tc) => ( )) ) : toolCalls.length <= 3 ? ( toolCalls.map((tc) => ( )) ) : ( )}
)} {/* No content indicator for tool-only messages in full mode */} {!content && showTools && verbosity === "full" && (
(tool calls only)
)} {/* Timestamp */} {showTimestamp && message.timestamp && (
{new Date(message.timestamp * 1000).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
)}
); } function CollapsedTools({ toolCalls, toolResults }: { toolCalls: ToolCall[]; toolResults: Map }) { const [open, setOpen] = useState(false); return (
{open && toolCalls.map((tc) => ( ))}
); }