Precise error messages (#150)
* Introduce a component to display error messages * precise error message when api key is invalid
This commit is contained in:
		
							parent
							
								
									3f09a4c355
								
							
						
					
					
						commit
						b89ca2082e
					
				|  | @ -1,9 +1,10 @@ | ||||||
| import { Conversation, KeyValuePair, Message, OpenAIModel } from "@/types"; | import { Conversation, ErrorMessage, KeyValuePair, Message, OpenAIModel } from "@/types"; | ||||||
| import { FC, MutableRefObject, useCallback, useEffect, useRef, useState } from "react"; | import { FC, MutableRefObject, useCallback, useEffect, useRef, useState } from "react"; | ||||||
| import { useTranslation } from "next-i18next"; | import { useTranslation } from "next-i18next"; | ||||||
| import { ChatInput } from "./ChatInput"; | import { ChatInput } from "./ChatInput"; | ||||||
| import { ChatLoader } from "./ChatLoader"; | import { ChatLoader } from "./ChatLoader"; | ||||||
| import { ChatMessage } from "./ChatMessage"; | import { ChatMessage } from "./ChatMessage"; | ||||||
|  | import { ErrorMessageDiv } from "./ErrorMessageDiv"; | ||||||
| import { ModelSelect } from "./ModelSelect"; | import { ModelSelect } from "./ModelSelect"; | ||||||
| import { SystemPrompt } from "./SystemPrompt"; | import { SystemPrompt } from "./SystemPrompt"; | ||||||
| 
 | 
 | ||||||
|  | @ -13,7 +14,7 @@ interface Props { | ||||||
|   apiKey: string; |   apiKey: string; | ||||||
|   serverSideApiKeyIsSet: boolean; |   serverSideApiKeyIsSet: boolean; | ||||||
|   messageIsStreaming: boolean; |   messageIsStreaming: boolean; | ||||||
|   modelError: boolean; |   modelError: ErrorMessage | null; | ||||||
|   messageError: boolean; |   messageError: boolean; | ||||||
|   loading: boolean; |   loading: boolean; | ||||||
|   lightMode: "light" | "dark"; |   lightMode: "light" | "dark"; | ||||||
|  | @ -76,13 +77,7 @@ export const Chat: FC<Props> = ({ conversation, models, apiKey, serverSideApiKey | ||||||
|           <div className="text-2xl font-semibold text-center text-gray-800 dark:text-gray-100">{t('OpenAI API Key Required')}</div> |           <div className="text-2xl font-semibold text-center text-gray-800 dark:text-gray-100">{t('OpenAI API Key Required')}</div> | ||||||
|           <div className="text-center text-gray-500 dark:text-gray-400">{t('Please set your OpenAI API key in the bottom left of the sidebar.')}</div> |           <div className="text-center text-gray-500 dark:text-gray-400">{t('Please set your OpenAI API key in the bottom left of the sidebar.')}</div> | ||||||
|         </div> |         </div> | ||||||
|       ) : modelError ? ( |       ) : modelError ? <ErrorMessageDiv error={modelError} /> : ( | ||||||
|         <div className="flex flex-col justify-center mx-auto h-full w-[300px] sm:w-[500px] space-y-6"> |  | ||||||
|           <div className="text-center text-red-500">{t('Error fetching models.')}</div> |  | ||||||
|           <div className="text-center text-red-500">{t('Make sure your OpenAI API key is set in the bottom left of the sidebar.')}</div> |  | ||||||
|           <div className="text-center text-red-500">{t('If you completed this step, OpenAI may be experiencing issues.')}</div> |  | ||||||
|         </div> |  | ||||||
|       ) : ( |  | ||||||
|         <> |         <> | ||||||
|           <div |           <div | ||||||
|             className="overflow-scroll max-h-full" |             className="overflow-scroll max-h-full" | ||||||
|  |  | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | import { ErrorMessage } from "@/types"; | ||||||
|  | import { FC } from "react"; | ||||||
|  | 
 | ||||||
|  | interface Props { | ||||||
|  |     error: ErrorMessage | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const ErrorMessageDiv: FC<Props> = ({ error }) => { | ||||||
|  |     return ( | ||||||
|  |         <div className= "flex flex-col justify-center mx-auto h-full w-[300px] sm:w-[500px] space-y-6" > | ||||||
|  |             <div className="text-center text-red-500" >{error.title} {error.code ? <i>({error.code}) </i> : "" }</div > | ||||||
|  |             { error.messageLines.map((line, index) => ( | ||||||
|  |                 <div key={index} className="text-center text-red-500" > {line} </div> | ||||||
|  |             )) } | ||||||
|  |         </div> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | @ -17,7 +17,16 @@ const handler = async (req: Request): Promise<Response> => { | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     if (response.status !== 200) { |     if (response.status === 401) { | ||||||
|  |       return new Response( | ||||||
|  |         response.body, | ||||||
|  |         { | ||||||
|  |           status: 500, | ||||||
|  |           headers: response.headers | ||||||
|  |         } | ||||||
|  |       ); | ||||||
|  |     } else if (response.status !== 200) { | ||||||
|  |       console.error(`OpenAI API returned an error ${response.status}: ${await response.text()}`) | ||||||
|       throw new Error("OpenAI API returned an error"); |       throw new Error("OpenAI API returned an error"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| import { Chat } from "@/components/Chat/Chat"; | import { Chat } from "@/components/Chat/Chat"; | ||||||
| import { Navbar } from "@/components/Mobile/Navbar"; | import { Navbar } from "@/components/Mobile/Navbar"; | ||||||
| import { Sidebar } from "@/components/Sidebar/Sidebar"; | import { Sidebar } from "@/components/Sidebar/Sidebar"; | ||||||
| import { ChatBody, ChatFolder, Conversation, KeyValuePair, Message, OpenAIModel, OpenAIModelID, OpenAIModels } from "@/types"; | import { ChatBody, ChatFolder, Conversation, ErrorMessage, KeyValuePair, Message, OpenAIModel, OpenAIModelID, OpenAIModels } from "@/types"; | ||||||
| import { cleanConversationHistory, cleanSelectedConversation } from "@/utils/app/clean"; | import { cleanConversationHistory, cleanSelectedConversation } from "@/utils/app/clean"; | ||||||
| import { DEFAULT_SYSTEM_PROMPT } from "@/utils/app/const"; | import { DEFAULT_SYSTEM_PROMPT } from "@/utils/app/const"; | ||||||
| import { saveConversation, saveConversations, updateConversation } from "@/utils/app/conversation"; | import { saveConversation, saveConversations, updateConversation } from "@/utils/app/conversation"; | ||||||
|  | @ -18,6 +18,7 @@ interface HomeProps { | ||||||
|   serverSideApiKeyIsSet: boolean; |   serverSideApiKeyIsSet: boolean; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | ||||||
|   const { t } = useTranslation('chat') |   const { t } = useTranslation('chat') | ||||||
|   const [folders, setFolders] = useState<ChatFolder[]>([]); |   const [folders, setFolders] = useState<ChatFolder[]>([]); | ||||||
|  | @ -30,7 +31,7 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | ||||||
|   const [showSidebar, setShowSidebar] = useState<boolean>(true); |   const [showSidebar, setShowSidebar] = useState<boolean>(true); | ||||||
|   const [apiKey, setApiKey] = useState<string>(""); |   const [apiKey, setApiKey] = useState<string>(""); | ||||||
|   const [messageError, setMessageError] = useState<boolean>(false); |   const [messageError, setMessageError] = useState<boolean>(false); | ||||||
|   const [modelError, setModelError] = useState<boolean>(false); |   const [modelError, setModelError] = useState<ErrorMessage | null>(null); | ||||||
|   const [currentMessage, setCurrentMessage] = useState<Message>(); |   const [currentMessage, setCurrentMessage] = useState<Message>(); | ||||||
| 
 | 
 | ||||||
|   const stopConversationRef = useRef<boolean>(false); |   const stopConversationRef = useRef<boolean>(false); | ||||||
|  | @ -179,6 +180,15 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   const fetchModels = async (key: string) => { |   const fetchModels = async (key: string) => { | ||||||
|  |     const error = { | ||||||
|  |       title: t('Error fetching models.'), | ||||||
|  |       code: null, | ||||||
|  |       messageLines: [ | ||||||
|  |         t('Make sure your OpenAI API key is set in the bottom left of the sidebar.'), | ||||||
|  |         t('If you completed this step, OpenAI may be experiencing issues.') | ||||||
|  |       ] | ||||||
|  |     } as ErrorMessage; | ||||||
|  | 
 | ||||||
|     const response = await fetch("/api/models", { |     const response = await fetch("/api/models", { | ||||||
|       method: "POST", |       method: "POST", | ||||||
|       headers: { |       headers: { | ||||||
|  | @ -190,19 +200,26 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     if (!response.ok) { |     if (!response.ok) { | ||||||
|       setModelError(true); |       try { | ||||||
|  |         const data = await response.json(); | ||||||
|  |         Object.assign(error, { | ||||||
|  |           code: data.error?.code, | ||||||
|  |           messageLines: [data.error?.message] | ||||||
|  |         }) | ||||||
|  |       } catch (e) { } | ||||||
|  |       setModelError(error); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const data = await response.json(); |     const data = await response.json(); | ||||||
| 
 | 
 | ||||||
|     if (!data) { |     if (!data) { | ||||||
|       setModelError(true); |       setModelError(error); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     setModels(data); |     setModels(data); | ||||||
|     setModelError(false); |     setModelError(null); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   const handleLightMode = (mode: "dark" | "light") => { |   const handleLightMode = (mode: "dark" | "light") => { | ||||||
|  |  | ||||||
|  | @ -61,3 +61,9 @@ export interface LocalStorage { | ||||||
|   // added folders (3/23/23)
 |   // added folders (3/23/23)
 | ||||||
|   folders: ChatFolder[]; |   folders: ChatFolder[]; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export interface ErrorMessage { | ||||||
|  |   code: String | null, | ||||||
|  |   title: String, | ||||||
|  |   messageLines: String[] | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue