"use client"; import styles from './page.module.css'; import { useEffect, useState } from 'react'; import { useChat } from 'ai/react'; import { FunctionCallHandler, Message, nanoid } from 'ai'; import ReactMarkdown from "react-markdown"; import { Bot, User } from "lucide-react"; import { toast } from 'sonner'; import { FunctionIcon } from './icons'; import { updateBackground } from './util'; import Input from './input'; const Page: React.FC = () => { useEffect(() => { updateBackground(); const interval = setInterval(updateBackground, 600); return () => clearInterval(interval); }, []); const functionCallHandler: FunctionCallHandler = async ( chatMessages, functionCall, ) => { let result; const { name, arguments: args } = functionCall; const response = await fetch("/api/functions", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ args: args, name: name }) } as any); if (!response.ok) { const errorText = await response.text(); toast.error(`Something went wrong: ${errorText}`); return; } result = await response.text(); return { messages: [ ...chatMessages, { id: nanoid(), name: functionCall.name, role: "function" as const, content: result, }, ], }; }; const { messages, input, setInput, handleSubmit, isLoading } = useChat({ experimental_onFunctionCall: functionCallHandler, onError: (error: any) => { console.log(error); }, }); const [isExpanded, setIsExpanded] = useState(false); const toggleExpand = () => { setIsExpanded(!isExpanded); }; const roleUIConfig: { [key: string]: { avatar: JSX.Element; bgColor: string; avatarColor: string; // eslint-disable-next-line no-unused-vars dialogComponent: (message: Message) => JSX.Element; }; } = { user: { avatar: , bgColor: "bg-white", avatarColor: "bg-black", dialogComponent: (message: Message) => (
( ), }} > {message.content}
), }, assistant: { avatar: , bgColor: "bg-gray-100", avatarColor: "bg-green-500", dialogComponent: (message: Message) => (
( ), }} > {message.content}
), }, function: { avatar:
, bgColor: "bg-gray-200", avatarColor: "bg-blue-500", dialogComponent: (message: Message) => { return (
{isExpanded && (
{message.content}
)}
); }, } }; return (
{messages.length > 0 ? ( messages.map((message, i) => { const messageClass = `${styles.message} ${message.role === 'user' ? styles['message-user'] : ''}`; return (
{roleUIConfig[message.role].avatar}
{message.content === "" && message.function_call != undefined ? ( typeof message.function_call === "object" ? (
Using{" "} {message.function_call.name} {" "} ...
{message.function_call.arguments}
) : (
{message.function_call}
) ) : (
{roleUIConfig[message.role].dialogComponent(message)}
)}
); }) ) : null}
); } export default Page;