diff --git a/src/renderer/src/pages/home/Messages/MessageMenubar.tsx b/src/renderer/src/pages/home/Messages/MessageMenubar.tsx index 0c36556f4f..16679982c4 100644 --- a/src/renderer/src/pages/home/Messages/MessageMenubar.tsx +++ b/src/renderer/src/pages/home/Messages/MessageMenubar.tsx @@ -30,7 +30,6 @@ import { } from '@renderer/utils/export' import { Button, Dropdown, Popconfirm, Tooltip } from 'antd' import dayjs from 'dayjs' -import { isEmpty } from 'lodash' import { FC, memo, useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -55,7 +54,6 @@ const MessageMenubar: FC = (props) => { const [isTranslating, setIsTranslating] = useState(false) const assistantModel = assistant?.model const { - messages, loading, editMessage, setStreamMessage, @@ -87,18 +85,10 @@ const MessageMenubar: FC = (props) => { const handleResendUserMessage = useCallback( async (messageUpdate?: Message) => { if (!loading) { - const groupdMessages = messages.filter((m) => m.askId === message.id) - - // Resend all grouped messages - if (!isEmpty(groupdMessages)) { - await resendMessage(message, assistant) - return - } - await resendMessage(messageUpdate ?? message, assistant) } }, - [message, resendMessage, assistant, messages, loading] + [assistant, loading, message, resendMessage] ) const onEdit = useCallback(async () => { @@ -331,19 +321,17 @@ const MessageMenubar: FC = (props) => { )} - {!isGrouped && ( - } - onConfirm={() => deleteMessage(message)}> - e.stopPropagation()}> - - - - - - )} + } + onConfirm={() => deleteMessage(message)}> + e.stopPropagation()}> + + + + + {!isUserMessage && ( e.domEvent.stopPropagation() }} diff --git a/src/renderer/src/pages/home/Messages/NewTopicButton.tsx b/src/renderer/src/pages/home/Messages/NewTopicButton.tsx index 9ec74cca93..60a3f5e535 100644 --- a/src/renderer/src/pages/home/Messages/NewTopicButton.tsx +++ b/src/renderer/src/pages/home/Messages/NewTopicButton.tsx @@ -29,6 +29,8 @@ const Container = styled.div` display: flex; justify-content: center; align-items: center; + margin-bottom: 10px; + margin-top: -10px; ` const Button = styled(AntdButton)<{ $theme: ThemeMode }>` diff --git a/src/renderer/src/store/messages.ts b/src/renderer/src/store/messages.ts index 2274ff118f..1763ad2945 100644 --- a/src/renderer/src/store/messages.ts +++ b/src/renderer/src/store/messages.ts @@ -9,7 +9,7 @@ import type { AppDispatch, RootState } from '@renderer/store' import type { Assistant, Message, Topic } from '@renderer/types' import { Model } from '@renderer/types' import { clearTopicQueue, getTopicQueue, waitForTopicQueue } from '@renderer/utils/queue' -import { cloneDeep, throttle } from 'lodash' +import { cloneDeep, isEmpty, throttle } from 'lodash' export interface MessagesState { messagesByTopic: Record @@ -95,9 +95,11 @@ const messagesSlice = createSlice({ }, addMessage: (state, action: PayloadAction<{ topicId: string; messages: Message | Message[] }>) => { const { topicId, messages } = action.payload + if (!state.messagesByTopic[topicId]) { state.messagesByTopic[topicId] = [] } + if (Array.isArray(messages)) { // 为了兼容多模型新发消息,一次性添加多个助手消息 // 不是什么好主意,不符合语义 @@ -112,6 +114,7 @@ const messagesSlice = createSlice({ action: PayloadAction<{ topicId: string; messages: Message | Message[]; position?: number }> ) => { const { topicId, messages, position } = action.payload + if (!state.messagesByTopic[topicId]) { state.messagesByTopic[topicId] = [] } @@ -136,6 +139,7 @@ const messagesSlice = createSlice({ ) => { const { topicId, messageId, updates } = action.payload const topicMessages = state.messagesByTopic[topicId] + if (topicMessages) { const message = topicMessages.find((msg) => msg.id === messageId) if (message) { @@ -160,9 +164,11 @@ const messagesSlice = createSlice({ }, setStreamMessage: (state, action: PayloadAction<{ topicId: string; message: Message | null }>) => { const { topicId, message } = action.payload + if (!state.streamMessagesByTopic[topicId]) { state.streamMessagesByTopic[topicId] = {} } + if (message) { state.streamMessagesByTopic[topicId][message.id] = message } @@ -193,11 +199,13 @@ const messagesSlice = createSlice({ // 添加新消息 state.messagesByTopic[topicId].push(streamMessage) } + // 删除流状态 delete state.streamMessagesByTopic[topicId][messageId] }, clearStreamMessage: (state, action: PayloadAction<{ topicId: string; messageId: string }>) => { const { topicId, messageId } = action.payload + if (state.streamMessagesByTopic[topicId]) { delete state.streamMessagesByTopic[topicId][messageId] } @@ -231,6 +239,7 @@ const handleResponseMessageUpdate = ( if (message.status === 'success') { autoRenameTopic(assistant, topicId) } + if (message.status !== 'sending') { dispatch(commitStreamMessage({ topicId, messageId: message.id })) const state = getState() @@ -246,9 +255,7 @@ const handleResponseMessageUpdate = ( const syncMessagesWithDB = async (topicId: string, messages: Message[]) => { const topic = await db.topics.get(topicId) if (topic) { - await db.topics.update(topicId, { - messages - }) + await db.topics.update(topicId, { messages }) } else { await db.topics.add({ id: topicId, messages }) } @@ -281,12 +288,13 @@ export const sendMessage = // 处理助手消息 let assistantMessages: Message[] = [] - if (options?.resendAssistantMessage) { + if (!isEmpty(options?.resendAssistantMessage)) { // 直接使用传入的助手消息,进行重置 const messageToReset = options.resendAssistantMessage if (Array.isArray(messageToReset)) { assistantMessages = messageToReset.map((m) => { - const resetMessage = resetAssistantMessage(m, assistant.model) + const isGroupedMessage = messageToReset.length > 1 + const resetMessage = resetAssistantMessage(m, isGroupedMessage ? m.model : assistant.model) // 更新状态 dispatch(updateMessage({ topicId: topic.id, messageId: m.id, updates: resetMessage })) // 使用重置后的消息 @@ -324,18 +332,27 @@ export const sendMessage = // 最后一个具有相同askId的助手消息,在其后插入 let position: number | undefined if (options?.isMentionModel) { + // 寻找用户提问对应的助手回答消息位置 const lastAssistantIndex = currentMessages.findLastIndex( (m) => m.role === 'assistant' && m.askId === userMessage.id ) + + // 如果找到了助手消息,在助手消息后插入 if (lastAssistantIndex !== -1) { position = lastAssistantIndex + 1 + } else { + // 如果找不到助手消息,则在用户消息后插入 + const userMessageIndex = currentMessages.findIndex((m) => m.role === 'user' && m.id === userMessage.id) + if (userMessageIndex !== -1) { + position = userMessageIndex + 1 + } } } dispatch( appendMessage({ topicId: topic.id, - messages: !options?.isMentionModel ? [userMessage, ...assistantMessages] : assistantMessages, + messages: options?.isMentionModel ? assistantMessages : [userMessage, ...assistantMessages], position }) ) @@ -393,15 +410,10 @@ export const sendMessage = return messagesUpToUser.filter((m) => !m.status?.includes('ing')) } - // 如果找不到对应的用户消息,使用原有逻辑 - // 按理说不会找不到 先注释掉看看 - // if (messageIndex !== -1) { - // const messagesUpToAssistant = messages.slice(0, messageIndex) - // return messagesUpToAssistant.filter((m) => !m.status?.includes('ing')) - // } // 没有找到消息索引的情况,过滤所有消息 return messages.filter((m) => !m.status?.includes('ing')) } + await fetchChatCompletion({ message: { ...assistantMessage }, messages: handleMessages(), @@ -461,12 +473,14 @@ export const resendMessage = if (message.role === 'user') { // 查找此用户消息对应的助手消息 const assistantMessage = topicMessages.filter((m) => m.role === 'assistant' && m.askId === message.id) + return dispatch( sendMessage(message, assistant, topic, { resendAssistantMessage: assistantMessage, // 用户可能把助手消息删了,然后重新发送用户消息 - // 如果isMentionModel为false,则只会发送add助手消息 - isMentionModel: !assistantMessage + // 如果 isMentionModel 为 false, 则只会发送 add 助手消息 + isMentionModel: isEmpty(assistantMessage), + mentions: message.mentions }) ) }