File size: 4,210 Bytes
c2df9c2
 
 
2c3d303
c2df9c2
2c3d303
c2df9c2
2c3d303
88cc829
c2df9c2
 
2c3d303
 
 
 
c2df9c2
 
 
 
 
 
 
2c3d303
 
 
 
 
 
 
 
 
c2df9c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fc7da9f
 
 
 
 
 
 
 
 
 
 
 
c2df9c2
 
 
 
 
 
fc7da9f
 
 
 
 
 
 
 
 
 
 
 
c2df9c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2c3d303
c2df9c2
 
5935dee
c2df9c2
9684fe8
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={{ 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;