diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index 2ae5d251..cf6b9be9 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -1,6 +1,7 @@ import { ElectronAPI } from '@electron-toolkit/preload' import type { FileMetadataResponse, ListFilesResponse, UploadFileResponse } from '@google/generative-ai/server' import { ExtractChunkData } from '@llm-tools/embedjs-interfaces' +import type { MCPServer, MCPTool } from '@renderer/types' import { AppInfo, FileType, KnowledgeBaseParams, KnowledgeItem, LanguageVarious, WebDavConfig } from '@renderer/types' import type { LoaderReturn } from '@shared/config/types' import type { OpenDialogOptions } from 'electron' @@ -129,7 +130,7 @@ declare global { deleteServer: (serverName: string) => Promise setServerActive: (name: string, isActive: boolean) => Promise // tools - listTools: () => Promise + listTools: () => Promise callTool: ({ client, name, args }: { client: string; name: string; args: any }) => Promise // status cleanup: () => Promise diff --git a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx index ad392960..9a7b4e91 100644 --- a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx +++ b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx @@ -132,6 +132,18 @@ const Inputbar: FC = ({ assistant: _assistant, setActiveTopic, topic }) = _text = text _files = files + const resizeTextArea = useCallback(() => { + const textArea = textareaRef.current?.resizableTextArea?.textArea + if (textArea) { + // 如果已经手动设置了高度,则不自动调整 + if (textareaHeight) { + return + } + textArea.style.height = 'auto' + textArea.style.height = textArea?.scrollHeight > 400 ? '400px' : `${textArea?.scrollHeight}px` + } + }, [textareaHeight]) + const sendMessage = useCallback(async () => { if (inputEmpty || loading) { return @@ -174,7 +186,19 @@ const Inputbar: FC = ({ assistant: _assistant, setActiveTopic, topic }) = } catch (error) { console.error('Failed to send message:', error) } - }, [inputEmpty, files, dispatch, text, assistant, topic, selectedKnowledgeBases, mentionModels, enabledMCPs, loading]) + }, [ + assistant, + dispatch, + enabledMCPs, + files, + inputEmpty, + loading, + mentionModels, + resizeTextArea, + selectedKnowledgeBases, + text, + topic + ]) const translate = async () => { if (isTranslating) { @@ -318,18 +342,6 @@ const Inputbar: FC = ({ assistant: _assistant, setActiveTopic, topic }) = EventEmitter.emit(EVENT_NAMES.NEW_CONTEXT) } - const resizeTextArea = () => { - const textArea = textareaRef.current?.resizableTextArea?.textArea - if (textArea) { - // 如果已经手动设置了高度,则不自动调整 - if (textareaHeight) { - return - } - textArea.style.height = 'auto' - textArea.style.height = textArea?.scrollHeight > 400 ? '400px' : `${textArea?.scrollHeight}px` - } - } - const onToggleExpended = () => { const isExpended = !expended setExpend(isExpended) diff --git a/src/renderer/src/pages/home/Messages/MessageGroup.tsx b/src/renderer/src/pages/home/Messages/MessageGroup.tsx index 0287e04a..ca75e87a 100644 --- a/src/renderer/src/pages/home/Messages/MessageGroup.tsx +++ b/src/renderer/src/pages/home/Messages/MessageGroup.tsx @@ -4,7 +4,6 @@ import { MultiModelMessageStyle } from '@renderer/store/settings' import type { Message, Topic } from '@renderer/types' import { classNames } from '@renderer/utils' import { Popover } from 'antd' -import type { Dispatch, SetStateAction } from 'react' import { memo, useCallback, useEffect, useState } from 'react' import styled, { css } from 'styled-components' @@ -15,12 +14,10 @@ interface Props { messages: (Message & { index: number })[] topic: Topic hidePresetMessages?: boolean - onSetMessages: Dispatch> } -const MessageGroup = ({ messages, topic, hidePresetMessages, onSetMessages }: Props) => { +const MessageGroup = ({ messages, topic, hidePresetMessages }: Props) => { const { multiModelMessageStyle: multiModelMessageStyleSetting, gridColumns, gridPopoverTrigger } = useSettings() - // const { t } = useTranslation() const [multiModelMessageStyle, setMultiModelMessageStyle] = useState(multiModelMessageStyleSetting) @@ -32,10 +29,6 @@ const MessageGroup = ({ messages, topic, hidePresetMessages, onSetMessages }: Pr const isHorizontal = multiModelMessageStyle === 'horizontal' const isGrid = multiModelMessageStyle === 'grid' - // const handleDeleteGroup = useCallback(async () => { - - // }, [messages, t, deleteGroupMessages]) - useEffect(() => { setSelectedIndex(messageLength - 1) }, [messageLength]) @@ -51,10 +44,7 @@ const MessageGroup = ({ messages, topic, hidePresetMessages, onSetMessages }: Pr hidePresetMessages, style: { paddingTop: isGrouped && ['horizontal', 'grid'].includes(multiModelMessageStyle) ? 0 : 15 - }, - onSetMessages - // onDeleteMessage, - // onGetMessages + } } const messageWrapper = ( @@ -99,8 +89,6 @@ const MessageGroup = ({ messages, topic, hidePresetMessages, onSetMessages }: Pr selectedIndex, topic, hidePresetMessages, - onSetMessages, - // onDeleteMessage, gridPopoverTrigger ] ) diff --git a/src/renderer/src/pages/home/Messages/MessageStream.tsx b/src/renderer/src/pages/home/Messages/MessageStream.tsx index 9a79f1de..b8ee3983 100644 --- a/src/renderer/src/pages/home/Messages/MessageStream.tsx +++ b/src/renderer/src/pages/home/Messages/MessageStream.tsx @@ -14,7 +14,6 @@ interface MessageStreamProps { hidePresetMessages?: boolean isGrouped?: boolean style?: React.CSSProperties - onSetMessages?: React.Dispatch> } const MessageStreamContainer = styled.div` @@ -30,8 +29,7 @@ const MessageStream: React.FC = ({ index, hidePresetMessages, isGrouped, - style, - onSetMessages + style }) => { // 获取流式消息 const streamMessage = useAppSelector((state) => selectStreamMessage(state, _message.topicId, _message.id)) @@ -63,7 +61,6 @@ const MessageStream: React.FC = ({ isGrouped={isGrouped} style={style} isStreaming={isStreaming} - onSetMessages={onSetMessages} /> ) diff --git a/src/renderer/src/pages/home/Messages/Messages.tsx b/src/renderer/src/pages/home/Messages/Messages.tsx index f563e303..7572dab1 100644 --- a/src/renderer/src/pages/home/Messages/Messages.tsx +++ b/src/renderer/src/pages/home/Messages/Messages.tsx @@ -200,7 +200,6 @@ const Messages: React.FC = ({ assistant, topic, setActiveTopic }) messages={groupMessages} topic={topic} hidePresetMessages={assistant.settings?.hideMessages} - onSetMessages={setDisplayMessages} /> ))} diff --git a/src/renderer/src/store/messages.ts b/src/renderer/src/store/messages.ts index 1ccfc1d9..75096253 100644 --- a/src/renderer/src/store/messages.ts +++ b/src/renderer/src/store/messages.ts @@ -243,6 +243,7 @@ export const sendMessage = // Initialize topic messages if not exists const initialState = getState() + if (!initialState.messages.messagesByTopic[topic.id]) { dispatch(clearTopicMessages(topic.id)) } @@ -278,6 +279,7 @@ export const sendMessage = assistantMessage.status = 'sending' assistantMessages.push(assistantMessage) } + dispatch( addMessage({ topicId: topic.id, @@ -287,6 +289,7 @@ export const sendMessage = } const queue = getTopicQueue(topic.id) + for (const assistantMessage of assistantMessages) { // Set as stream message instead of adding to messages dispatch(setStreamMessage({ topicId: topic.id, message: assistantMessage })) @@ -298,6 +301,7 @@ export const sendMessage = if (currentTopicMessages) { await syncMessagesWithDB(topic.id, currentTopicMessages) } + // 保证请求有序,防止请求静态,限制并发数量 await queue.add(async () => { try { diff --git a/src/renderer/src/windows/mini/chat/components/Message.tsx b/src/renderer/src/windows/mini/chat/components/Message.tsx index 4ff4f16b..d0d9d94d 100644 --- a/src/renderer/src/windows/mini/chat/components/Message.tsx +++ b/src/renderer/src/windows/mini/chat/components/Message.tsx @@ -3,12 +3,10 @@ import { useModel } from '@renderer/hooks/useModel' import { useSettings } from '@renderer/hooks/useSettings' import MessageContent from '@renderer/pages/home/Messages/MessageContent' import MessageErrorBoundary from '@renderer/pages/home/Messages/MessageErrorBoundary' -import { fetchChatCompletion } from '@renderer/services/ApiService' -import { getDefaultAssistant, getDefaultModel } from '@renderer/services/AssistantService' import { getMessageModelId } from '@renderer/services/MessagesService' import { Message } from '@renderer/types' import { isMiniWindow } from '@renderer/utils' -import { Dispatch, FC, memo, SetStateAction, useEffect, useMemo, useRef, useState } from 'react' +import { Dispatch, FC, memo, SetStateAction, useMemo, useRef } from 'react' import styled from 'styled-components' interface Props { @@ -23,8 +21,7 @@ interface Props { const getMessageBackground = (isBubbleStyle: boolean, isAssistantMessage: boolean) => isBubbleStyle ? (isAssistantMessage ? 'transparent' : 'var(--chat-background-user)') : undefined -const MessageItem: FC = ({ message: _message, index, total, route, onSetMessages, onGetMessages }) => { - const [message, setMessage] = useState(_message) +const MessageItem: FC = ({ message, index, total, route }) => { const model = useModel(getMessageModelId(message)) const isBubbleStyle = true const { messageFont, fontSize } = useSettings() @@ -40,32 +37,6 @@ const MessageItem: FC = ({ message: _message, index, total, route, onSetM const maxWidth = isMiniWindow() ? '480px' : '100%' - useEffect(() => { - if (onGetMessages && onSetMessages) { - if (message.status === 'sending') { - const messages = onGetMessages() - fetchChatCompletion({ - message, - messages: messages - .filter((m) => !m.status.includes('ing')) - .slice( - 0, - messages.findIndex((m) => m.id === message.id) - ), - assistant: { ...getDefaultAssistant(), model: getDefaultModel() }, - onResponse: (msg) => { - setMessage(msg) - if (msg.status !== 'pending') { - const _messages = messages.map((m) => (m.id === msg.id ? msg : m)) - onSetMessages(_messages) - } - } - }) - } - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [message.status]) - if (['summary', 'explanation'].includes(route) && index === total - 1) { return null } diff --git a/src/renderer/src/windows/mini/chat/components/Messages.tsx b/src/renderer/src/windows/mini/chat/components/Messages.tsx index a41583db..f710d367 100644 --- a/src/renderer/src/windows/mini/chat/components/Messages.tsx +++ b/src/renderer/src/windows/mini/chat/components/Messages.tsx @@ -23,12 +23,9 @@ const Messages: FC = ({ assistant, route }) => { const [messages, setMessages] = useState([]) const containerRef = useRef(null) - const messagesRef = useRef(messages) const { t } = useTranslation() - messagesRef.current = messages - const onSendMessage = useCallback( async (message: Message) => { setMessages((prev) => { @@ -40,10 +37,6 @@ const Messages: FC = ({ assistant, route }) => { [assistant] ) - const onGetMessages = useCallback(() => { - return messagesRef.current - }, []) - useEffect(() => { const unsubscribes = [EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, onSendMessage)] return () => unsubscribes.forEach((unsub) => unsub()) @@ -60,15 +53,7 @@ const Messages: FC = ({ assistant, route }) => { return ( {[...messages].reverse().map((message, index) => ( - + ))} )