File size: 2,642 Bytes
a1c5622
a86b547
bc1cf4e
7286745
bc1cf4e
c7e97b5
 
4af6326
 
a86b547
5ec491a
a1c5622
 
d553ae5
a1c5622
7acedd7
c7e97b5
a1c5622
c7e97b5
 
 
 
 
 
 
a86b547
 
 
 
 
 
7286745
c7e97b5
7acedd7
84c9f51
a86b547
c7e97b5
bc1cf4e
c7e97b5
ba9285c
 
a86b547
ca7a659
 
 
a86b547
 
5ec491a
92f037b
5ec491a
c232e44
c7e97b5
84c9f51
c7e97b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7286745
c7e97b5
 
7286745
c7e97b5
84c9f51
c7e97b5
 
 
 
 
 
84c9f51
a86b547
c7e97b5
 
 
 
a86b547
 
 
 
 
 
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
import { useChat } from 'ai/react';
import { toast } from 'react-hot-toast';
import { useEffect, useRef } from 'react';
import { ChatWithMessages } from '../types';
import { convertDBMessageToAPIMessage } from '../utils/message';
import { useRouter } from 'next/navigation';
import { Message } from '@prisma/client';
import { useSetAtom } from 'jotai';
import { selectedMessageId } from '@/state/chat';

const useVisionAgent = (chat: ChatWithMessages) => {
  const { messages: dbMessages, id, mediaUrl } = chat;
  const latestDbMessage = dbMessages[dbMessages.length - 1];

  // Temporary solution for now while single we have to pass mediaUrl separately outside of the messages
  const router = useRouter();
  const setMessageId = useSetAtom(selectedMessageId);

  const {
    data = [],
    reload,
    append,
    messages,
    isLoading,
  } = useChat({
    api: '/api/vision-agent',
    onResponse(response) {
      if (response.status !== 200) {
        toast.error(response.statusText);
      }
    },
    onFinish: () => {
      setMessageId(latestDbMessage.id);
      router.refresh();
    },
    body: {
      mediaUrl: latestDbMessage.mediaUrl,
      chatId: id,
      messageId: latestDbMessage.id,
      // for some reason, the messages has to be stringified to be sent to the API
      apiMessages: JSON.stringify(convertDBMessageToAPIMessage(dbMessages)),
    },
    onError: err => {
      err && toast.error(err.message);
    },
  });

  /**
   * If case this is first time user navigated with init message, we need to reload the chat for the first response
   */
  const once = useRef(true);

  useEffect(() => {
    const appendDbMessage = async (latestDbMessage: Message) => {
      await append({
        id: latestDbMessage.id + '-user',
        content: latestDbMessage.prompt,
        role: 'user',
      });
    };
    if (isLoading || latestDbMessage.response || latestDbMessage.responseBody) {
      return;
    }
    if (messages.length === 0) {
      if (once.current) {
        once.current = false;
        appendDbMessage(latestDbMessage);
      }
      return;
    }
    if (
      messages.findIndex(message => message.id.includes(latestDbMessage.id)) ===
      -1
    ) {
      appendDbMessage(latestDbMessage);
    }
  }, [latestDbMessage, messages, isLoading]);

  const initDataIndex = data.findIndex(
    (m: any) =>
      m.type === 'init' && m.payload?.messageId === latestDbMessage.id,
  );

  return {
    data:
      initDataIndex >= 0
        ? (data.slice(initDataIndex + 1) as unknown as PrismaJson.MessageBody[])
        : [],
    reload,
    isLoading,
  };
};

export default useVisionAgent;