diff --git a/README.md b/README.md index 4b4c0ff..dba533a 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,11 @@ Expect frequent improvements. - [ ] Folders - [ ] Custom model settings - [ ] Prompt templates -- [ ] Regenerate responses +- [ ] Regenerate & edit responses **Recent updates:** +- [x] Error handling (3/20/23) - [x] GPT-4 support (access required) (3/20/23) - [x] Search conversations (3/19/23) - [x] Code syntax highlighting (3/18/23) diff --git a/components/Chat/Chat.tsx b/components/Chat/Chat.tsx index 1318322..501291e 100644 --- a/components/Chat/Chat.tsx +++ b/components/Chat/Chat.tsx @@ -1,21 +1,26 @@ import { Conversation, Message, OpenAIModel } from "@/types"; -import { FC, useEffect, useRef } from "react"; +import { FC, useEffect, useRef, useState } from "react"; import { ChatInput } from "./ChatInput"; import { ChatLoader } from "./ChatLoader"; import { ChatMessage } from "./ChatMessage"; import { ModelSelect } from "./ModelSelect"; +import { Regenerate } from "./Regenerate"; interface Props { conversation: Conversation; models: OpenAIModel[]; messageIsStreaming: boolean; + modelError: boolean; + messageError: boolean; loading: boolean; lightMode: "light" | "dark"; - onSend: (message: Message) => void; + onSend: (message: Message, isResend: boolean) => void; onModelChange: (conversation: Conversation, model: OpenAIModel) => void; } -export const Chat: FC = ({ conversation, models, messageIsStreaming, loading, lightMode, onSend, onModelChange }) => { +export const Chat: FC = ({ conversation, models, messageIsStreaming, modelError, messageError, loading, lightMode, onSend, onModelChange }) => { + const [currentMessage, setCurrentMessage] = useState(); + const messagesEndRef = useRef(null); const scrollToBottom = () => { @@ -28,45 +33,68 @@ export const Chat: FC = ({ conversation, models, messageIsStreaming, load return (
-
- {conversation.messages.length === 0 ? ( - <> -
- onModelChange(conversation, model)} - /> -
+ {modelError ? ( +
+
Error fetching models.
+
Make sure your OpenAI API key is set in the bottom left of the sidebar or in a .env.local file and refresh.
+
If you completed this step, OpenAI may be experiencing issues.
+
+ ) : ( + <> +
+ {conversation.messages.length === 0 ? ( + <> +
+ onModelChange(conversation, model)} + /> +
-
{loading ? "Loading..." : "Chatbot UI"}
- - ) : ( - <> -
Model: {conversation.model.name}
+
{models.length === 0 ? "Loading..." : "Chatbot UI"}
+ + ) : ( + <> +
Model: {conversation.model.name}
- {conversation.messages.map((message, index) => ( - - ))} + {conversation.messages.map((message, index) => ( + + ))} - {loading && } + {loading && } -
+ + )} +
+ + {messageError ? ( + { + if (currentMessage) { + onSend(currentMessage, true); + } + }} /> - - )} -
- - + ) : ( + { + setCurrentMessage(message); + onSend(message, false); + }} + /> + )} + + )}
); }; diff --git a/components/Chat/Regenerate.tsx b/components/Chat/Regenerate.tsx new file mode 100644 index 0000000..40c7de2 --- /dev/null +++ b/components/Chat/Regenerate.tsx @@ -0,0 +1,21 @@ +import { IconRefresh } from "@tabler/icons-react"; +import { FC } from "react"; + +interface Props { + onRegenerate: () => void; +} + +export const Regenerate: FC = ({ onRegenerate }) => { + return ( +
+
Sorry, there was an error.
+ +
+ ); +}; diff --git a/pages/index.tsx b/pages/index.tsx index 52c588c..26db5eb 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -16,17 +16,32 @@ export default function Home() { const [messageIsStreaming, setMessageIsStreaming] = useState(false); const [showSidebar, setShowSidebar] = useState(true); const [apiKey, setApiKey] = useState(""); + const [messageError, setMessageError] = useState(false); + const [modelError, setModelError] = useState(false); - const handleSend = async (message: Message) => { + const handleSend = async (message: Message, isResend: boolean) => { if (selectedConversation) { - let updatedConversation: Conversation = { - ...selectedConversation, - messages: [...selectedConversation.messages, message] - }; + let updatedConversation: Conversation; + + if (isResend) { + const updatedMessages = [...selectedConversation.messages]; + updatedMessages.pop(); + + updatedConversation = { + ...selectedConversation, + messages: [...updatedMessages, message] + }; + } else { + updatedConversation = { + ...selectedConversation, + messages: [...selectedConversation.messages, message] + }; + } setSelectedConversation(updatedConversation); setLoading(true); setMessageIsStreaming(true); + setMessageError(false); const response = await fetch("/api/chat", { method: "POST", @@ -42,6 +57,8 @@ export default function Home() { if (!response.ok) { setLoading(false); + setMessageIsStreaming(false); + setMessageError(true); return; } @@ -50,6 +67,8 @@ export default function Home() { if (!data) { setLoading(false); setMessageIsStreaming(false); + setMessageError(true); + return; } @@ -218,8 +237,6 @@ export default function Home() { }; const fetchModels = async (key: string) => { - setLoading(true); - const response = await fetch("/api/models", { method: "POST", headers: { @@ -229,13 +246,20 @@ export default function Home() { key }) }); - const data = await response.json(); - if (data) { - setModels(data); + if (!response.ok) { + setModelError(true); + return; } - setLoading(false); + const data = await response.json(); + + if (!data) { + setModelError(true); + return; + } + + setModels(data); }; useEffect(() => { @@ -336,6 +360,8 @@ export default function Home() {