diff --git a/web/containers/ErrorMessage/index.test.tsx b/web/containers/ErrorMessage/index.test.tsx
index 306a80e324..d9866d3c0f 100644
--- a/web/containers/ErrorMessage/index.test.tsx
+++ b/web/containers/ErrorMessage/index.test.tsx
@@ -30,20 +30,23 @@ describe('ErrorMessage Component', () => {
beforeEach(() => {
jest.clearAllMocks()
- ;(useAtomValue as jest.Mock).mockReturnValue([])
- ;(useSetAtom as jest.Mock).mockReturnValue(mockSetMainState)
- ;(useSetAtom as jest.Mock).mockReturnValue(mockSetSelectedSettingScreen)
- ;(useSetAtom as jest.Mock).mockReturnValue(mockSetModalTroubleShooting)
- ;(useSendChatMessage as jest.Mock).mockReturnValue({
- resendChatMessage: mockResendChatMessage,
- })
+ ; (useAtomValue as jest.Mock).mockReturnValue([])
+ ; (useSetAtom as jest.Mock).mockReturnValue(mockSetMainState)
+ ; (useSetAtom as jest.Mock).mockReturnValue(mockSetSelectedSettingScreen)
+ ; (useSetAtom as jest.Mock).mockReturnValue(mockSetModalTroubleShooting)
+ ; (useSendChatMessage as jest.Mock).mockReturnValue({
+ resendChatMessage: mockResendChatMessage,
+ })
})
it('renders error message with InvalidApiKey correctly', () => {
const message: ThreadMessage = {
id: '1',
- status: MessageStatus.Error,
- error_code: ErrorCode.InvalidApiKey,
+ metadata: {
+ error: MessageStatus.Error,
+ error_code: ErrorCode.InvalidApiKey,
+ },
+ status: "completed",
content: [{ text: { value: 'Invalid API Key' } }],
} as ThreadMessage
@@ -56,8 +59,11 @@ describe('ErrorMessage Component', () => {
it('renders general error message correctly', () => {
const message: ThreadMessage = {
id: '1',
- status: MessageStatus.Error,
- error_code: ErrorCode.Unknown,
+ status: "completed",
+ metadata: {
+ error: MessageStatus.Error,
+ error_code: ErrorCode.Unknown
+ },
content: [{ text: { value: 'Unknown error occurred' } }],
} as ThreadMessage
@@ -69,9 +75,11 @@ describe('ErrorMessage Component', () => {
it('opens troubleshooting modal when link is clicked', () => {
const message: ThreadMessage = {
id: '1',
- status: MessageStatus.Error,
- error_code: ErrorCode.Unknown,
- content: [{ text: { value: 'Unknown error occurred' } }],
+ status: "completed",
+ metadata: {
+ error: MessageStatus.Error,
+ error_code: ErrorCode.Unknown,
+ }, content: [{ text: { value: 'Unknown error occurred' } }],
} as ThreadMessage
render()
diff --git a/web/containers/ErrorMessage/index.tsx b/web/containers/ErrorMessage/index.tsx
index 95b87fc53b..e0705e6b6d 100644
--- a/web/containers/ErrorMessage/index.tsx
+++ b/web/containers/ErrorMessage/index.tsx
@@ -53,7 +53,7 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
const getErrorTitle = () => {
const engine = getEngine()
- switch (message.error_code) {
+ switch (message.metadata?.error_code) {
case ErrorCode.InvalidApiKey:
case ErrorCode.AuthenticationError:
return (
@@ -102,7 +102,7 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
return (
- {message.status === MessageStatus.Error && (
+ {!!message.metadata?.error && (
{
const updatedMessage = await extensionManager
.get
(ExtensionTypeEnum.Conversational)
?.createMessage(message)
+ .catch(() => undefined)
if (updatedMessage) {
deleteMessage(message.id)
addNewMessage(updatedMessage)
diff --git a/web/helpers/atoms/ChatMessage.atom.ts b/web/helpers/atoms/ChatMessage.atom.ts
index 7cdeb69463..5df44e0312 100644
--- a/web/helpers/atoms/ChatMessage.atom.ts
+++ b/web/helpers/atoms/ChatMessage.atom.ts
@@ -141,7 +141,7 @@ export const deleteMessageAtom = atom(null, (get, set, id: string) => {
if (threadId) {
// Should also delete error messages to clear out the error state
newData[threadId] = newData[threadId].filter(
- (e) => e.id !== id && e.status !== MessageStatus.Error
+ (e) => e.id !== id && !e.metadata?.error
)
set(chatMessages, newData)
diff --git a/web/hooks/useActiveModel.ts b/web/hooks/useActiveModel.ts
index e436d116e0..ed704dd612 100644
--- a/web/hooks/useActiveModel.ts
+++ b/web/hooks/useActiveModel.ts
@@ -10,7 +10,6 @@ import { LAST_USED_MODEL_ID } from './useRecommendedModel'
import { vulkanEnabledAtom } from '@/helpers/atoms/AppConfig.atom'
import { activeAssistantAtom } from '@/helpers/atoms/Assistant.atom'
import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom'
-import { activeThreadAtom } from '@/helpers/atoms/Thread.atom'
export const activeModelAtom = atom(undefined)
export const loadModelErrorAtom = atom(undefined)
@@ -29,7 +28,6 @@ export const stateModelAtom = atom({
export function useActiveModel() {
const [activeModel, setActiveModel] = useAtom(activeModelAtom)
- const activeThread = useAtomValue(activeThreadAtom)
const [stateModel, setStateModel] = useAtom(stateModelAtom)
const downloadedModels = useAtomValue(downloadedModelsAtom)
const setLoadModelError = useSetAtom(loadModelErrorAtom)
diff --git a/web/hooks/useCreateNewThread.ts b/web/hooks/useCreateNewThread.ts
index 944b446545..c4c77d0a4f 100644
--- a/web/hooks/useCreateNewThread.ts
+++ b/web/hooks/useCreateNewThread.ts
@@ -230,8 +230,10 @@ export const useCreateNewThread = () => {
await extensionManager
.get(ExtensionTypeEnum.Conversational)
?.createThreadAssistant(thread.id, assistantInfo)
+ .catch(console.error)
return thread
})
+ .catch(() => undefined)
}
return {
diff --git a/web/hooks/usePath.ts b/web/hooks/usePath.ts
index 315072000a..464ff0b580 100644
--- a/web/hooks/usePath.ts
+++ b/web/hooks/usePath.ts
@@ -1,4 +1,4 @@
-import { openFileExplorer, joinPath, baseName, fs } from '@janhq/core'
+import { openFileExplorer, joinPath, baseName } from '@janhq/core'
import { useAtomValue } from 'jotai'
import { getFileInfo } from '@/utils/file'
diff --git a/web/hooks/useSendChatMessage.ts b/web/hooks/useSendChatMessage.ts
index f1582d2797..66b031849d 100644
--- a/web/hooks/useSendChatMessage.ts
+++ b/web/hooks/useSendChatMessage.ts
@@ -200,6 +200,7 @@ export default function useSendChatMessage() {
const createdMessage = await extensionManager
.get(ExtensionTypeEnum.Conversational)
?.createMessage(newMessage)
+ .catch(() => undefined)
if (!createdMessage) return
diff --git a/web/screens/Thread/ThreadCenterPanel/ChatItem/index.tsx b/web/screens/Thread/ThreadCenterPanel/ChatItem/index.tsx
index 1fa3ef1155..57876d0448 100644
--- a/web/screens/Thread/ThreadCenterPanel/ChatItem/index.tsx
+++ b/web/screens/Thread/ThreadCenterPanel/ChatItem/index.tsx
@@ -23,9 +23,7 @@ const ChatItem = forwardRef[((message, ref) => {
const [content, setContent] = useState(message.content)
const [status, setStatus] = useState(message.status)
const [errorMessage, setErrorMessage] = useState(
- message.isCurrentMessage && message.status === MessageStatus.Error
- ? message
- : undefined
+ message.isCurrentMessage && !!message?.metadata?.error ? message : undefined
)
function onMessageUpdate(data: ThreadMessage) {
@@ -52,16 +50,18 @@ const ChatItem = forwardRef][((message, ref) => {
return (
<>
- {status !== MessageStatus.Error && content?.length > 0 && (
- ]
-
-
- )}
+ {status !== MessageStatus.Error &&
+ !message.metadata?.error &&
+ content?.length > 0 && (
+
+
+
+ )}
{errorMessage && !message.loadModelError && (
)}
diff --git a/web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx b/web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx
index 9b81ea6518..88f6a72b05 100644
--- a/web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx
+++ b/web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx
@@ -89,7 +89,7 @@ const EditChatInput: React.FC = ({ message }) => {
.get(ExtensionTypeEnum.Conversational)
?.deleteMessage(message.thread_id, message.id)
)
- )
+ ).catch(console.error)
setMessages(threadId, newMessages)
sendChatMessage(editPrompt, false, newMessages)
}
diff --git a/web/screens/Thread/ThreadCenterPanel/MessageToolbar/index.tsx b/web/screens/Thread/ThreadCenterPanel/MessageToolbar/index.tsx
index a15f0ec583..a7b59216a4 100644
--- a/web/screens/Thread/ThreadCenterPanel/MessageToolbar/index.tsx
+++ b/web/screens/Thread/ThreadCenterPanel/MessageToolbar/index.tsx
@@ -109,7 +109,7 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
)}
{message.id === messages[messages.length - 1]?.id &&
- messages[messages.length - 1].status !== MessageStatus.Error &&
+ !messages[messages.length - 1]?.metadata?.error &&
!messages[messages.length - 1].attachments?.length && (
{
+const DocMessage = ({
+ id,
+ metadata,
+}: {
+ id: string
+ metadata: Record
| undefined
+}) => {
const { onViewFile } = usePath()
- const [fileInfo, setFileInfo] = useState<
- { filename: string; id: string } | undefined
- >()
- useEffect(() => {
- if (!fileInfo) {
- getFileInfo(id).then((data) => {
- setFileInfo(data)
- })
- }
- }, [fileInfo, id])
return (
@@ -29,10 +25,14 @@ const DocMessage = ({ id }: { id: string }) => {
- {fileInfo?.filename}
+ {metadata && 'filename' in metadata
+ ? (metadata.filename as string)
+ : id}
- {fileInfo?.id ?? id}
+ {metadata && 'size' in metadata
+ ? toGibibytes(Number(metadata.size))
+ : id}
diff --git a/web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx b/web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx
index c029da74d7..e870e09e71 100644
--- a/web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx
+++ b/web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx
@@ -127,7 +127,10 @@ const MessageContainer: React.FC<
<>
{image && }
{attachedFile && (
-
+
)}
{editMessage === props.id ? (
diff --git a/web/utils/messageRequestBuilder.ts b/web/utils/messageRequestBuilder.ts
index 269dfcee4c..c3da9cbd80 100644
--- a/web/utils/messageRequestBuilder.ts
+++ b/web/utils/messageRequestBuilder.ts
@@ -6,7 +6,6 @@ import {
ChatCompletionRole,
MessageRequest,
MessageRequestType,
- MessageStatus,
ModelInfo,
Thread,
ThreadMessage,
@@ -35,7 +34,7 @@ export class MessageRequestBuilder {
this.model = model
this.thread = thread
this.messages = messages
- .filter((e) => e.status !== MessageStatus.Error)
+ .filter((e) => !e.metadata?.error)
.map((msg) => ({
role: msg.role,
content: msg.content[0]?.text?.value ?? '.',
diff --git a/web/utils/threadMessageBuilder.ts b/web/utils/threadMessageBuilder.ts
index 8a776d5df3..1162dd2f62 100644
--- a/web/utils/threadMessageBuilder.ts
+++ b/web/utils/threadMessageBuilder.ts
@@ -16,6 +16,7 @@ export class ThreadMessageBuilder {
content: ThreadContent[] = []
attachments: Attachment[] = []
+ metadata: Record = {}
constructor(messageRequest: MessageRequestBuilder) {
this.messageRequest = messageRequest
@@ -33,6 +34,7 @@ export class ThreadMessageBuilder {
completed_at: timestamp,
object: 'thread.message',
content: this.content,
+ metadata: this.metadata,
}
}
@@ -68,6 +70,10 @@ export class ThreadMessageBuilder {
},
],
})
+ this.metadata = {
+ filename: fileUpload.name,
+ size: fileUpload.file?.size,
+ }
}
return this