vision-agent / lib /hooks /useVisionAgent.ts
wuyiqunLu
feat: encode uri for s3 url when loading (#104)
c7e97b5 unverified
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;