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