diff --git a/packages/ocular-ui/components/chat/chat-helpers/index.tsx b/packages/ocular-ui/components/chat/chat-helpers/index.tsx index 969c9905..09512cf2 100644 --- a/packages/ocular-ui/components/chat/chat-helpers/index.tsx +++ b/packages/ocular-ui/components/chat/chat-helpers/index.tsx @@ -18,6 +18,8 @@ import { toast } from "sonner" import { v4 as uuidv4 } from "uuid" import { createReader,readStream } from '@/lib/stream'; import { da, ro } from "date-fns/locale" +import { set } from "nprogress" +import { processStreamChatResponse } from "@/lib/parse-chat-stream" export const handleChat = async ( @@ -54,49 +56,7 @@ export const fetchChatResponse = async ( api.chats.sendMessage(chat.id,{message:content,stream:true},cancelTokenSource) .then(async response => { console.log("Streaming Copilot Response") - const reader = createReader(response.body); - const chunks = readStream(reader); - for await (const chunk of chunks) { - setChatMessages(prevChatMessages => { - const updatedMessages = [...prevChatMessages]; - if (idx=== 0) { - updatedMessages.push({ - message: { - chat_id: chunk.metadata?.chat_id, - content: chunk.choices[0].delta.content, - created_at: new Date(), - id: "123", - role: chunk.metadata.role, - updated_at: new Date(), - user_id: chunk.metadata.user_id - }, - fileItems: [] - }); - idx++; - } else { - const lastMessage = updatedMessages[updatedMessages.length - 1]; - lastMessage.message.content = chunk.choices[0].delta.content; - lastMessage.message.updated_at = new Date(); - } - return updatedMessages; - }); - } - - // setChatMessages(prevChatMessages => [...prevChatMessages, - // { - // message: { - // chat_id: data.metadata?.chat_id, - // content: data.choices[0].delta.content, - // created_at: new Date(), - // id: "123", - // role: data.metadata.role, - // updated_at: new Date(), - // user_id: data.metadata.user_id - // }, - // fileItems: [] - // } - // ]); - + processStreamChatResponse(response,setChatMessages,chat.id); }) .catch(error => { console.error(error); @@ -104,41 +64,6 @@ export const fetchChatResponse = async ( }); } - // lastChatMessage: ChatMessage, -export const processResponse = async ( - response: Response, - cancelTokenSource: CancelTokenSource, - setFirstTokenReceived: React.Dispatch>, - setChatMessages: React.Dispatch>, - // setToolInUse: React.Dispatch> -) => { - let fullText = "" - let contentToAdd = "" - - - if (response) { - - router.push(`/dashboard/chat/${response.message.chat_id}`) - setChatMessages(prevChatMessages => [...prevChatMessages, - { - message: { - chat_id: response.message.chat_id, - content: response.message.content, - created_at: response.message.created_at, - id: response.message.id, - role: response.message.role, - updated_at: response.message.updated_at, - user_id: response.message.user_id - }, - fileItems: [] - } - ]); - // return fullText - return response.message.content - } else { - throw new Error("Response body is null") - } -} export const handleCreateChat = async ( messageContent: string, diff --git a/packages/ocular-ui/components/chat/chat-hooks/use-chat-handler.tsx b/packages/ocular-ui/components/chat/chat-hooks/use-chat-handler.tsx index da9e7c55..ce2ffefb 100644 --- a/packages/ocular-ui/components/chat/chat-hooks/use-chat-handler.tsx +++ b/packages/ocular-ui/components/chat/chat-hooks/use-chat-handler.tsx @@ -6,6 +6,8 @@ import { handleCreateChat, handleChat, } from "../chat-helpers/index" +import { v4 as uuidv4 } from 'uuid'; + export const useChatHandler = () => { @@ -88,12 +90,13 @@ export const useChatHandler = () => { chat_id: currentChat?.id, content: messageContent, created_at: new Date(), - id: "123", + id: uuidv4(), role: "user", updated_at: new Date(), user_id: currentChat?.user_id }, - fileItems: [] + fileItems: [], + followUpQuestions:[] } ]); diff --git a/packages/ocular-ui/components/chat/chat-messages.tsx b/packages/ocular-ui/components/chat/chat-messages.tsx index e45c1829..503aaca6 100644 --- a/packages/ocular-ui/components/chat/chat-messages.tsx +++ b/packages/ocular-ui/components/chat/chat-messages.tsx @@ -2,23 +2,76 @@ import { ApplicationContext } from "@/context/context" import { FC, useContext, useState } from "react" import { Message } from "../messages/message" import { Message as MessageType } from "@/types/chat" +import { formatLabel } from '@/lib/utils'; +import Image from 'next/image'; +import { Separator } from "../ui/separator"; +import { useChatHandler } from "./chat-hooks/use-chat-handler"; +import {v4 as uuidv4} from 'uuid'; -interface ChatMessagesProps {} +interface ChatMessagesProps { } -export const ChatMessages: FC = ({}) => { +export const ChatMessages: FC = ({ }) => { const { chatMessages } = useContext(ApplicationContext) const [editingMessage, setEditingMessage] = useState() + const { + chatInputRef, + handleSendMessage, + } = useChatHandler() + return chatMessages - .sort((a, b) => new Date(a.message.created_at).getTime() - new Date(b.message.created_at).getTime()) + .sort((a, b) => new Date(a.message.created_at).getTime() - new Date(b.message.created_at).getTime()) .map((chatMessage, index, array) => { return ( - +
+ + {chatMessage.message.role === "assistant" && chatMessage.fileItems?.length > 0 &&
+

Sources

+ +
} + {chatMessage.message.role === "assistant" &&
+ {chatMessage.fileItems?.map((fileItem) => { + return ( +
+
+
+ {fileItem.title} +

+ {formatLabel(fileItem.source)} +

+
+

+
+
+ ) + })} +
} + {chatMessage.message.role === "assistant" && chatMessage.followUpQuestions?.length > 0 &&
+

Related

+ +
} + {chatMessage.message.role === "assistant" &&
+ {chatMessage.followUpQuestions?.map((question, index) => { + return ( +
handleSendMessage(question, false)} + > +

{question}

+
+ ) + })} +
} +
) }) } diff --git a/packages/ocular-ui/components/chat/chat-ui.tsx b/packages/ocular-ui/components/chat/chat-ui.tsx index e1a41b8e..b94dd363 100644 --- a/packages/ocular-ui/components/chat/chat-ui.tsx +++ b/packages/ocular-ui/components/chat/chat-ui.tsx @@ -8,6 +8,7 @@ import { ChatMessages } from "./chat-messages" import { ChatSecondaryButtons } from "./chat-secondary-buttons" import api from "@/services/api" +import { set } from "nprogress" interface ChatUIProps {} @@ -17,6 +18,7 @@ export const ChatUI: FC = ({}) => { const params = useParams() const { + chatMessages, setChatMessages, selectedChat, setSelectedChat, @@ -51,7 +53,7 @@ export const ChatUI: FC = ({}) => { } else { setLoading(false) } - }, [params]) + }, [params]); const fetchMessages = async () => { const fetchedMessages = await api.chats.retrieve(params.chatid as string) @@ -60,7 +62,12 @@ export const ChatUI: FC = ({}) => { message, } }) - setChatMessages(fetchedChatMessages) + const currentChatMessages = localStorage.getItem(params.chatid as string); + if(currentChatMessages){ + setChatMessages(JSON.parse(currentChatMessages)); + return; + } + setChatMessages(fetchedChatMessages); } const fetchChat = async () => { diff --git a/packages/ocular-ui/components/messages/message-codeblock.tsx b/packages/ocular-ui/components/messages/message-codeblock.tsx index 6e0aa3be..c57e67d1 100644 --- a/packages/ocular-ui/components/messages/message-codeblock.tsx +++ b/packages/ocular-ui/components/messages/message-codeblock.tsx @@ -3,7 +3,7 @@ import { useCopyToClipboard } from "@/lib/hooks/use-copy-to-clipboard" import { IconCheck, IconCopy, IconDownload } from "@tabler/icons-react" import { FC, memo } from "react" import { Prism as SyntaxHighlighter } from "react-syntax-highlighter" -import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism" +import { dracula } from "react-syntax-highlighter/dist/cjs/styles/prism" interface MessageCodeBlockProps { language: string @@ -86,7 +86,7 @@ export const MessageCodeBlock: FC = memo( } return ( -
+
{language}
@@ -111,12 +111,15 @@ export const MessageCodeBlock: FC = memo(
{ const [showResults, setShowResults] = useState(false); @@ -20,7 +21,9 @@ export const AIResults = ({ content, ai_citations }) => {

Copilot

- {content} +
+ +
{ai_citations && ai_citations.length > 0 && (