From 56dd2d17e7cb722201c9d6bfa2ffb7f12353b890 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Tue, 11 Mar 2025 10:32:10 +0800 Subject: [PATCH] feat(Models, MCP, Localization): Add Qwen to tool calling models and enhance MCP server management - Add 'qwen' to tool calling models list - Refactor MCP server hooks to use window.api methods - Add 'more' translation key across localization files - Improve MCP settings modal with window.api and window.modal methods --- src/renderer/src/config/models.ts | 2 +- src/renderer/src/hooks/useMCPServers.ts | 22 ++++++++---------- src/renderer/src/i18n/locales/en-us.json | 3 ++- src/renderer/src/i18n/locales/ja-jp.json | 3 ++- src/renderer/src/i18n/locales/ru-ru.json | 3 ++- src/renderer/src/i18n/locales/zh-cn.json | 3 ++- src/renderer/src/i18n/locales/zh-tw.json | 3 ++- .../src/pages/settings/MCPSettings.tsx | 23 ++++++++++--------- 8 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 2c07dc1f..0985560b 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -178,7 +178,7 @@ export const EMBEDDING_REGEX = /(?:^text-|embed|bge-|e5-|LLM2Vec|retrieval|uae-| export const NOT_SUPPORTED_REGEX = /(?:^tts|rerank|whisper|speech)/i // Tool calling models -export const TOOL_CALLING_MODELS = ['gpt-4o', 'gpt-4o-mini', 'gpt-4', 'gpt-4.5', 'claude'] +export const TOOL_CALLING_MODELS = ['gpt-4o', 'gpt-4o-mini', 'gpt-4', 'gpt-4.5', 'claude', 'qwen'] export const TOOL_CALLING_REGEX = new RegExp(`\\b(?:${TOOL_CALLING_MODELS.join('|')})\\b`, 'i') export function isToolCallingModel(model: Model): boolean { if (['gemini', 'deepseek', 'anthropic'].includes(model.provider)) { diff --git a/src/renderer/src/hooks/useMCPServers.ts b/src/renderer/src/hooks/useMCPServers.ts index b6a02379..9a5cb0f9 100644 --- a/src/renderer/src/hooks/useMCPServers.ts +++ b/src/renderer/src/hooks/useMCPServers.ts @@ -1,5 +1,5 @@ -import { useAppDispatch, useAppSelector } from '@renderer/store' -import { setMCPServers as _setMCPServers } from '@renderer/store/mcp' +import store, { useAppDispatch, useAppSelector } from '@renderer/store' +import { setMCPServers } from '@renderer/store/mcp' import { MCPServer } from '@renderer/types' import { useEffect } from 'react' @@ -7,17 +7,13 @@ const ipcRenderer = window.electron.ipcRenderer // Set up IPC listener for main process requests ipcRenderer.on('mcp:request-servers', () => { - // This needs to access Redux outside of a hook, so we use the store directly - const { store } = require('@renderer/store') const servers = store.getState().mcp.servers ipcRenderer.send('mcp:servers-from-renderer', servers) }) // Listen for server changes from main process ipcRenderer.on('mcp:servers-changed', (_event, servers) => { - // This needs to dispatch outside of a hook, so we use the store directly - const { store } = require('@renderer/store') - store.dispatch(_setMCPServers(servers)) + store.dispatch(setMCPServers(servers)) }) export const useMCPServers = () => { @@ -33,8 +29,8 @@ export const useMCPServers = () => { useEffect(() => { const loadServers = async () => { try { - const servers = await ipcRenderer.invoke('mcp:list-servers') - dispatch(_setMCPServers(servers)) + const servers = await window.api.mcp.listServers() + dispatch(setMCPServers(servers)) } catch (error) { console.error('Failed to load MCP servers:', error) } @@ -45,7 +41,7 @@ export const useMCPServers = () => { const addMCPServer = async (server: MCPServer) => { try { - await ipcRenderer.invoke('mcp:add-server', server) + await window.api.mcp.addServer(server) // Main process will send back updated servers via mcp:servers-changed } catch (error) { console.error('Failed to add MCP server:', error) @@ -55,7 +51,7 @@ export const useMCPServers = () => { const updateMCPServer = async (server: MCPServer) => { try { - await ipcRenderer.invoke('mcp:update-server', server) + await window.api.mcp.updateServer(server) // Main process will send back updated servers via mcp:servers-changed } catch (error) { console.error('Failed to update MCP server:', error) @@ -65,7 +61,7 @@ export const useMCPServers = () => { const deleteMCPServer = async (name: string) => { try { - await ipcRenderer.invoke('mcp:delete-server', name) + await window.api.mcp.deleteServer(name) // Main process will send back updated servers via mcp:servers-changed } catch (error) { console.error('Failed to delete MCP server:', error) @@ -75,7 +71,7 @@ export const useMCPServers = () => { const setMCPServerActive = async (name: string, isActive: boolean) => { try { - await ipcRenderer.invoke('mcp:set-server-active', { name, isActive }) + await window.api.mcp.setServerActive(name, isActive) // Main process will send back updated servers via mcp:servers-changed } catch (error) { console.error('Failed to set MCP server active status:', error) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index f8679a07..76eb4a33 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -222,7 +222,8 @@ "select": "Select", "topics": "Topics", "warning": "Warning", - "you": "You" + "you": "You", + "more": "More" }, "docs": { "title": "Docs" diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index c08d6fc9..74b71316 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -222,7 +222,8 @@ "select": "選択", "topics": "トピック", "warning": "警告", - "you": "あなた" + "you": "あなた", + "more": "もっと" }, "docs": { "title": "ドキュメント" diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index ed145321..23b6166d 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -222,7 +222,8 @@ "select": "Выбрать", "topics": "Топики", "warning": "Предупреждение", - "you": "Вы" + "you": "Вы", + "more": "Ещё" }, "docs": { "title": "Документация" diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 4f9cb34f..c16bcced 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -222,7 +222,8 @@ "select": "选择", "topics": "话题", "warning": "警告", - "you": "用户" + "you": "用户", + "more": "更多" }, "docs": { "title": "帮助文档" diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 21910d6f..8d542f00 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -222,7 +222,8 @@ "select": "選擇", "topics": "話題", "warning": "警告", - "you": "您" + "you": "您", + "more": "更多" }, "docs": { "title": "說明文件" diff --git a/src/renderer/src/pages/settings/MCPSettings.tsx b/src/renderer/src/pages/settings/MCPSettings.tsx index 31dec368..9975d577 100644 --- a/src/renderer/src/pages/settings/MCPSettings.tsx +++ b/src/renderer/src/pages/settings/MCPSettings.tsx @@ -3,7 +3,7 @@ import { useTheme } from '@renderer/context/ThemeProvider' import { useAppDispatch, useAppSelector } from '@renderer/store' import { addMCPServer, deleteMCPServer, setMCPServerActive, updateMCPServer } from '@renderer/store/mcp' import { MCPServer } from '@renderer/types' -import { Button, Card, Form, Input, message, Modal, Radio, Space, Switch, Table, Tag, Tooltip, Typography } from 'antd' +import { Button, Card, Form, Input, Modal, Radio, Space, Switch, Table, Tag, Tooltip, Typography } from 'antd' import TextArea from 'antd/es/input/TextArea' import { FC, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -113,20 +113,20 @@ const MCPSettings: FC = () => { window.api.mcp .updateServer(mcpServer) .then(() => { - message.success(t('settings.mcp.updateSuccess')) + window.message.success(t('settings.mcp.updateSuccess')) setLoading(false) setIsModalVisible(false) form.resetFields() }) .catch((error) => { - message.error(`${t('settings.mcp.updateError')}: ${error.message}`) + window.message.error(`${t('settings.mcp.updateError')}: ${error.message}`) setLoading(false) }) dispatch(updateMCPServer(mcpServer)) } else { // Check for duplicate name if (mcpServers.some((server: MCPServer) => server.name === mcpServer.name)) { - message.error(t('settings.mcp.duplicateName')) + window.message.error(t('settings.mcp.duplicateName')) setLoading(false) return } @@ -134,13 +134,13 @@ const MCPSettings: FC = () => { window.api.mcp .addServer(mcpServer) .then(() => { - message.success(t('settings.mcp.addSuccess')) + window.message.success(t('settings.mcp.addSuccess')) setLoading(false) setIsModalVisible(false) form.resetFields() }) .catch((error) => { - message.error(`${t('settings.mcp.addError')}: ${error.message}`) + window.message.error(`${t('settings.mcp.addError')}: ${error.message}`) setLoading(false) }) dispatch(addMCPServer(mcpServer)) @@ -152,20 +152,21 @@ const MCPSettings: FC = () => { } const handleDelete = (serverName: string) => { - Modal.confirm({ + window.modal.confirm({ title: t('settings.mcp.confirmDelete'), content: t('settings.mcp.confirmDeleteMessage'), okText: t('common.delete'), okButtonProps: { danger: true }, cancelText: t('common.cancel'), + centered: true, onOk: () => { window.api.mcp .deleteServer(serverName) .then(() => { - message.success(t('settings.mcp.deleteSuccess')) + window.message.success(t('settings.mcp.deleteSuccess')) }) .catch((error) => { - message.error(`${t('settings.mcp.deleteError')}: ${error.message}`) + window.message.error(`${t('settings.mcp.deleteError')}: ${error.message}`) }) dispatch(deleteMCPServer(serverName)) } @@ -179,7 +180,7 @@ const MCPSettings: FC = () => { // Optional: Show success message or update UI }) .catch((error) => { - message.error(`${t('settings.mcp.toggleError')}: ${error.message}`) + window.message.error(`${t('settings.mcp.toggleError')}: ${error.message}`) }) dispatch(setMCPServerActive({ name, isActive })) } @@ -217,7 +218,7 @@ const MCPSettings: FC = () => { ellipsis={{ rows: 1, expandable: 'collapsible', - symbol: 'more', + symbol: t('common.more'), onExpand: () => {}, // Empty callback required for proper functionality tooltip: true }}