components/ToolCall.tsx (111 lines of code) (raw):

import React from "react"; import { ToolCallItem } from "@/lib/assistant"; import { BookOpenText, ChevronRight, Clock, Zap } from "lucide-react"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { coy } from "react-syntax-highlighter/dist/esm/styles/prism"; import { agentTools } from "@/config/tools-list"; interface ToolCallProps { toolCall: ToolCallItem; } function FunctionCall({ toolCall }: ToolCallProps) { const [showDetails, setShowDetails] = React.useState(false); const toggleShowDetails = () => { setShowDetails(!showDetails); }; const formatName = (name: string) => { return name.replace(/_/g, " ").replace("-", " "); }; return ( <div className="w-full mb-4"> <div className="flex gap-1 items-center justify-end w-full px-4 text-[#ED6A5E] cursor-pointer" onClick={toggleShowDetails} > <div className="flex gap-2 items-center"> <Zap size={16} /> <div className="text-sm font-medium"> {toolCall.name && agentTools.includes(toolCall.name) ? `Suggested ${formatName(toolCall.name || "")}` : toolCall.status === "completed" ? `Called ${formatName(toolCall.name || "")}` : `Calling ${formatName(toolCall.name || "")}...`} </div> </div> <div className={`transform transition-transform duration-300 ${ showDetails ? "rotate-90" : "rotate-0" }`} > <ChevronRight size={16} /> </div> </div> {showDetails && ( <div className="bg-[#fafafa] rounded-xl p-2 mx-2 md:ml-24 mt-4 mb-2"> <div className="max-h-96 overflow-y-scroll text-xs border-b mx-6 p-2"> <SyntaxHighlighter customStyle={{ backgroundColor: "#fafafa", padding: "8px", paddingLeft: "0px", marginTop: 0, marginBottom: 0, }} language="json" style={coy} > {JSON.stringify(toolCall.parsedArguments, null, 2)} </SyntaxHighlighter> </div> <div className="max-h-96 overflow-y-scroll mx-6 p-2 text-xs"> {toolCall.output ? ( <SyntaxHighlighter customStyle={{ backgroundColor: "#fafafa", padding: "8px", paddingLeft: "0px", marginTop: 0, }} language="json" style={coy} > {JSON.stringify(JSON.parse(toolCall.output), null, 2)} </SyntaxHighlighter> ) : ( <div className="text-zinc-500 flex items-center gap-2 py-2"> <Clock size={16} /> Waiting for result... </div> )} </div> </div> )} </div> ); } function FileSearchCall({ toolCall }: ToolCallProps) { return ( <div className="flex gap-2 items-center text-[#ED6A5E] justify-end w-full mb-4 mr-2"> <BookOpenText size={16} /> <div className="text-sm font-medium mb-0.5"> {toolCall.status === "completed" ? "Searched files" : "Searching files..."} </div> </div> ); } export default function ToolCall({ toolCall }: ToolCallProps) { return ( <div className="flex justify-start pt-2"> {(() => { switch (toolCall.tool_type) { case "function_call": return <FunctionCall toolCall={toolCall} />; case "file_search_call": return <FileSearchCall toolCall={toolCall} />; default: return null; } })()} </div> ); }