File size: 4,227 Bytes
c2df9c2 2c3d303 c2df9c2 2c3d303 c2df9c2 2c3d303 88cc829 c2df9c2 2c3d303 c2df9c2 2c3d303 c2df9c2 fc7da9f c2df9c2 fc7da9f c2df9c2 2c3d303 c2df9c2 5935dee c2df9c2 5935dee fc7da9f 5935dee aab77fe 5935dee c2df9c2 fc7da9f 5935dee c2df9c2 5935dee c2df9c2 2c3d303 c2df9c2 5935dee c2df9c2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
"use client";
import styles from './page.module.css';
import { useEffect, useRef, useState } from 'react';
import { useChat } from 'ai/react';
import { Message } from 'ai';
import ReactMarkdown from "react-markdown";
import { functionCallHandler } from './hooks/useFunctions';
import Input from './input';
const Page: React.FC = () => {
// Ref for the messages container
const messagesRef = useRef<HTMLDivElement>(null);
const [keyboardHeight, setKeyboardHeight] = useState(0);
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
const { messages, input, setInput, handleSubmit, isLoading } = useChat({
experimental_onFunctionCall: functionCallHandler,
onError: (error: any) => {
console.log(error);
},
});
const inputRef = useRef(null);
useEffect(() => {
if (messagesRef.current) {
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
}
}, [messages]);
const [isExpanded, setIsExpanded] = useState(false);
const toggleExpand = () => {
setIsExpanded(!isExpanded);
};
const roleUIConfig: {
[key: string]: {
bgColor: string;
avatarColor: string;
// eslint-disable-next-line no-unused-vars
dialogComponent: (message: Message) => JSX.Element;
};
} = {
user: {
bgColor: "bg-white",
avatarColor: "bg-black",
dialogComponent: (message: Message) => (
<div className="message-content-container">
<ReactMarkdown
className=""
components={{
a: (props) => (
<a {...props} target="_blank" rel="noopener noreferrer" />
),
}}
>
{message.content}
</ReactMarkdown>
</div>
),
},
assistant: {
bgColor: "bg-gray-100",
avatarColor: "bg-green-500",
dialogComponent: (message: Message) => (
<div className="message-content-container">
<ReactMarkdown
className=""
components={{
a: (props) => (
<a {...props} target="_blank" rel="noopener noreferrer" />
),
}}
>
{message.content}
</ReactMarkdown>
</div>
),
},
function: {
bgColor: "bg-gray-200",
avatarColor: "bg-blue-500",
dialogComponent: (message: Message) => {
return (
<div className="flex flex-col">
{isExpanded && (
<div className="py-1">{message.content}</div>
)}
</div>
);
},
}
};
return (
<main className={styles.main}>
<div className={styles.messages} ref={messagesRef}>
{messages.length > 0 ? (
messages.map((message, i) => {
const messageClass = `${styles.message} ${message.role === 'user' ? styles['message-user'] : ''}`;
return (
<div key={i} className={messageClass} style={{ display: 'flex', alignItems: 'center' }}>
{message.content === "" && message.function_call != undefined ? (
typeof message.function_call === "object" ? (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div>
Using{" "}
<span className="font-bold">
{message.function_call.name}
</span>{" "}
...
</div>
<div>
{message.function_call.arguments}
</div>
</div>
) : (
<div className="function-call">{message.function_call}</div>
)
) : (
<div className="message-text">
{roleUIConfig[message.role].dialogComponent(message)}
</div>
)}
</div>
);
})
) : null}
</div>
<Input inputRef={inputRef} handleSubmit={handleSubmit as any} setInput={setInput} input={input} />
</main>
);
}
export default Page;
|