diff --git a/components/Composer.tsx b/components/Composer.tsx
index 6d1fbe62c..36eb3b8c4 100644
--- a/components/Composer.tsx
+++ b/components/Composer.tsx
@@ -10,7 +10,7 @@ import TelegramIcon from '@mui/icons-material/Telegram';
import { useComposerStore } from '../utilities/store';
import { useSpeechRecognition } from '../utilities/speechRecognition';
-import { NoSSR } from './NoSSR';
+import { NoSSR } from './util/NoSSR';
/// Text template helpers
diff --git a/components/ChatMessage.tsx b/components/Message.tsx
similarity index 94%
rename from components/ChatMessage.tsx
rename to components/Message.tsx
index 6e9500811..98632b4a9 100644
--- a/components/ChatMessage.tsx
+++ b/components/Message.tsx
@@ -22,7 +22,7 @@ import StopOutlinedIcon from '@mui/icons-material/StopOutlined';
import { Alert, Avatar, Box, Button, IconButton, ListDivider, ListItem, ListItemDecorator, Menu, MenuItem, Stack, Textarea, Tooltip, Typography, useTheme } from '@mui/joy';
import { SxProps, Theme } from '@mui/joy/styles/types';
-import { Link } from './Link';
+import { Link } from './util/Link';
// One message in the chat
@@ -154,7 +154,7 @@ function RunnableCode({ codeBlock, theme }: { codeBlock: CodeMessageBlock, theme
);
}
-function ChatMessageCodeBlock({ codeBlock, theme, sx }: { codeBlock: CodeMessageBlock, theme: Theme, sx?: SxProps }) {
+function CodeBlock({ codeBlock, theme, sx }: { codeBlock: CodeMessageBlock, theme: Theme, sx?: SxProps }) {
const [showSandpack, setShowSandpack] = React.useState(false);
const handleCopyToClipboard = () =>
@@ -183,15 +183,47 @@ function ChatMessageCodeBlock({ codeBlock, theme, sx }: { codeBlock: CodeMessage
;
}
-function prettyModel(model: string): string {
+function prettyBaseModel(model: string): string {
if (model.startsWith('gpt-4')) return 'gpt-4';
if (model.startsWith('gpt-3.5-turbo')) return '3.5-turbo';
return model;
}
+function explainErrorInMessage(message: UiMessage) {
+ let errorMessage: JSX.Element | null = null;
+ const isAssistantError = message.role === 'assistant' && (message.text.startsWith('Error: ') || message.text.startsWith('OpenAI API error: '));
+ if (isAssistantError) {
+ if (message.text.startsWith('OpenAI API error: 429 Too Many Requests')) {
+ // TODO: retry at the api/chat level a few times instead of showing this error
+ errorMessage = <>
+ The model appears to be occupied at the moment. Kindly select GPT-3.5 Turbo via settings icon,
+ or give it another go by selecting Run again from the message menu.
+ >;
+ } else if (message.text.includes('"model_not_found"')) {
+ // note that "model_not_found" is different than "The model `gpt-xyz` does not exist" message
+ errorMessage = <>
+ Your API key appears to be unauthorized for {message.model || 'this model'}. You can change to GPT-3.5 Turbo via the settings
+ icon and simultaneously request
+ access to the desired model.
+ >;
+ } else if (message.text.includes('"context_length_exceeded"')) {
+ // TODO: propose to summarize or split the input?
+ const pattern: RegExp = /maximum context length is (\d+) tokens.+resulted in (\d+) tokens/;
+ const match = pattern.exec(message.text);
+ const usedText = match ? ` (${match[2]} tokens, max ${match[1]})` : '';
+ errorMessage = <>
+ This thread surpasses the maximum size allowed for {message.model || 'this model'}{usedText}.
+ Please consider removing some earlier messages from the conversation, start a new conversation,
+ choose a model with larger context, or submit a shorter new message.
+ >;
+ }
+ }
+ return { errorMessage, isAssistantError };
+}
+
/**
- * ChatMessage component is a customizable chat message UI component that supports
+ * The Message component is a customizable chat message UI component that supports
* different roles (user, assistant, and system), text editing, syntax highlighting,
* and code execution using Sandpack for TypeScript, JavaScript, and HTML code blocks.
* The component also provides options for copying code to clipboard and expanding
@@ -201,7 +233,7 @@ function prettyModel(model: string): string {
* @param {Function} props.onDelete - The function to call when the delete button is clicked.
* @param {Function} props.onEdit - The function to call when the edit button is clicked and the edited text is submitted.
*/
-export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void, onEdit: (text: string) => void, onRunAgain: () => void }) {
+export function Message(props: { uiMessage: UiMessage, onDelete: () => void, onEdit: (text: string) => void, onRunAgain: () => void }) {
const theme = useTheme();
const message = props.uiMessage;
@@ -253,34 +285,7 @@ export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void,
// soft error handling
- let errorMessage: JSX.Element | null = null;
- const isAssistantError = message.role === 'assistant' && (message.text.startsWith('Error: ') || message.text.startsWith('OpenAI API error: '));
- if (isAssistantError) {
- if (message.text.startsWith('OpenAI API error: 429 Too Many Requests')) {
- // TODO: retry at the api/chat level a few times instead of showing this error
- errorMessage = <>
- The model appears to be occupied at the moment. Kindly select GPT-3.5 Turbo via settings icon,
- or give it another go by selecting Run again from the message menu.
- >;
- } else if (message.text.includes('"model_not_found"')) {
- // note that "model_not_found" is different than "The model `gpt-xyz` does not exist" message
- errorMessage = <>
- Your API key appears to be unauthorized for {message.model || 'this model'}. You can change to GPT-3.5 Turbo via the settings
- icon and simultaneously request
- access to the desired model.
- >;
- } else if (message.text.includes('"context_length_exceeded"')) {
- // TODO: propose to summarize or split the input?
- const pattern: RegExp = /maximum context length is (\d+) tokens.+resulted in (\d+) tokens/;
- const match = pattern.exec(message.text);
- const usedText = match ? ` (${match[2]} tokens, max ${match[1]})` : '';
- errorMessage = <>
- This thread surpasses the maximum size allowed for {message.model || 'this model'}{usedText}.
- Please consider removing some earlier messages from the conversation, start a new conversation,
- choose a model with larger context, or submit a shorter new message.
- >;
- }
- }
+ const { isAssistantError, errorMessage } = explainErrorInMessage(message);
// theming
@@ -342,10 +347,12 @@ export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void,
:
)}
- {message.role === 'system' && (system)}
+ {message.role === 'system' && (
+ system
+ )}
{message.role === 'assistant' && (
- {prettyModel(message.model)}
+ {prettyBaseModel(message.model)}
)}
@@ -388,7 +395,7 @@ export function ChatMessage(props: { uiMessage: UiMessage, onDelete: () => void,
{parseAndHighlightCodeBlocks(collapsedText).map((part, index) =>
part.type === 'code' ? (
-
+
) : (
diff --git a/components/Settings.tsx b/components/Settings.tsx
index 9c8311409..5b3079b84 100644
--- a/components/Settings.tsx
+++ b/components/Settings.tsx
@@ -4,8 +4,8 @@ import { shallow } from 'zustand/shallow';
import { Box, Button, Input, Modal, ModalClose, ModalDialog, Option, Select, Typography } from '@mui/joy';
import { GptChatModelId, GptChatModels, useSettingsStore } from '../utilities/store';
-import { Link } from './Link';
-import { NoSSR } from './NoSSR';
+import { Link } from './util/Link';
+import { NoSSR } from './util/NoSSR';
export const isValidOpenAIApiKey = (apiKey?: string) =>
diff --git a/components/Link.tsx b/components/util/Link.tsx
similarity index 100%
rename from components/Link.tsx
rename to components/util/Link.tsx
diff --git a/components/NoSSR.tsx b/components/util/NoSSR.tsx
similarity index 100%
rename from components/NoSSR.tsx
rename to components/util/NoSSR.tsx
diff --git a/pages/api/chat.ts b/pages/api/chat.ts
index 810c4509d..d9ed9b755 100644
--- a/pages/api/chat.ts
+++ b/pages/api/chat.ts
@@ -9,7 +9,7 @@ if (!process.env.OPENAI_API_KEY)
// definition for OpenAI wire types
-export interface ChatMessage {
+interface ChatMessage {
role: 'assistant' | 'system' | 'user';
content: string;
}
diff --git a/pages/index.tsx b/pages/index.tsx
index 6af3ac838..e56f08934 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -8,10 +8,10 @@ import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined';
import SmartToyTwoToneIcon from '@mui/icons-material/SmartToyTwoTone';
import { ChatApiInput } from './api/chat';
-import { ChatMessage, UiMessage } from '../components/ChatMessage';
import { Composer } from '../components/Composer';
import { GptChatModels, SystemPurposeId, SystemPurposes, useSettingsStore } from '../utilities/store';
-import { NoSSR } from '../components/NoSSR';
+import { Message, UiMessage } from '../components/Message';
+import { NoSSR } from '../components/util/NoSSR';
import { isValidOpenAIApiKey, Settings } from '../components/Settings';
@@ -255,10 +255,10 @@ export default function Conversation() {
<>
{messages.map(message =>
- handleListDelete(message.uid)}
- onEdit={newText => handleListEdit(message.uid, newText)}
- onRunAgain={() => handleListRunAgain(message.uid)} />)}
+ handleListDelete(message.uid)}
+ onEdit={newText => handleListEdit(message.uid, newText)}
+ onRunAgain={() => handleListRunAgain(message.uid)} />)}
>
diff --git a/tsconfig.json b/tsconfig.json
index 86f9cc8c1..0f7aeb965 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "es5",
+ "target": "ES6",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,