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
This commit is contained in:
parent
cf92752e79
commit
56dd2d17e7
@ -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
|
export const NOT_SUPPORTED_REGEX = /(?:^tts|rerank|whisper|speech)/i
|
||||||
|
|
||||||
// Tool calling models
|
// 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 const TOOL_CALLING_REGEX = new RegExp(`\\b(?:${TOOL_CALLING_MODELS.join('|')})\\b`, 'i')
|
||||||
export function isToolCallingModel(model: Model): boolean {
|
export function isToolCallingModel(model: Model): boolean {
|
||||||
if (['gemini', 'deepseek', 'anthropic'].includes(model.provider)) {
|
if (['gemini', 'deepseek', 'anthropic'].includes(model.provider)) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
import store, { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||||
import { setMCPServers as _setMCPServers } from '@renderer/store/mcp'
|
import { setMCPServers } from '@renderer/store/mcp'
|
||||||
import { MCPServer } from '@renderer/types'
|
import { MCPServer } from '@renderer/types'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
@ -7,17 +7,13 @@ const ipcRenderer = window.electron.ipcRenderer
|
|||||||
|
|
||||||
// Set up IPC listener for main process requests
|
// Set up IPC listener for main process requests
|
||||||
ipcRenderer.on('mcp:request-servers', () => {
|
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
|
const servers = store.getState().mcp.servers
|
||||||
ipcRenderer.send('mcp:servers-from-renderer', servers)
|
ipcRenderer.send('mcp:servers-from-renderer', servers)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Listen for server changes from main process
|
// Listen for server changes from main process
|
||||||
ipcRenderer.on('mcp:servers-changed', (_event, servers) => {
|
ipcRenderer.on('mcp:servers-changed', (_event, servers) => {
|
||||||
// This needs to dispatch outside of a hook, so we use the store directly
|
store.dispatch(setMCPServers(servers))
|
||||||
const { store } = require('@renderer/store')
|
|
||||||
store.dispatch(_setMCPServers(servers))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const useMCPServers = () => {
|
export const useMCPServers = () => {
|
||||||
@ -33,8 +29,8 @@ export const useMCPServers = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadServers = async () => {
|
const loadServers = async () => {
|
||||||
try {
|
try {
|
||||||
const servers = await ipcRenderer.invoke('mcp:list-servers')
|
const servers = await window.api.mcp.listServers()
|
||||||
dispatch(_setMCPServers(servers))
|
dispatch(setMCPServers(servers))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load MCP servers:', error)
|
console.error('Failed to load MCP servers:', error)
|
||||||
}
|
}
|
||||||
@ -45,7 +41,7 @@ export const useMCPServers = () => {
|
|||||||
|
|
||||||
const addMCPServer = async (server: MCPServer) => {
|
const addMCPServer = async (server: MCPServer) => {
|
||||||
try {
|
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
|
// Main process will send back updated servers via mcp:servers-changed
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to add MCP server:', error)
|
console.error('Failed to add MCP server:', error)
|
||||||
@ -55,7 +51,7 @@ export const useMCPServers = () => {
|
|||||||
|
|
||||||
const updateMCPServer = async (server: MCPServer) => {
|
const updateMCPServer = async (server: MCPServer) => {
|
||||||
try {
|
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
|
// Main process will send back updated servers via mcp:servers-changed
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to update MCP server:', error)
|
console.error('Failed to update MCP server:', error)
|
||||||
@ -65,7 +61,7 @@ export const useMCPServers = () => {
|
|||||||
|
|
||||||
const deleteMCPServer = async (name: string) => {
|
const deleteMCPServer = async (name: string) => {
|
||||||
try {
|
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
|
// Main process will send back updated servers via mcp:servers-changed
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to delete MCP server:', error)
|
console.error('Failed to delete MCP server:', error)
|
||||||
@ -75,7 +71,7 @@ export const useMCPServers = () => {
|
|||||||
|
|
||||||
const setMCPServerActive = async (name: string, isActive: boolean) => {
|
const setMCPServerActive = async (name: string, isActive: boolean) => {
|
||||||
try {
|
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
|
// Main process will send back updated servers via mcp:servers-changed
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to set MCP server active status:', error)
|
console.error('Failed to set MCP server active status:', error)
|
||||||
|
|||||||
@ -222,7 +222,8 @@
|
|||||||
"select": "Select",
|
"select": "Select",
|
||||||
"topics": "Topics",
|
"topics": "Topics",
|
||||||
"warning": "Warning",
|
"warning": "Warning",
|
||||||
"you": "You"
|
"you": "You",
|
||||||
|
"more": "More"
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "Docs"
|
"title": "Docs"
|
||||||
|
|||||||
@ -222,7 +222,8 @@
|
|||||||
"select": "選択",
|
"select": "選択",
|
||||||
"topics": "トピック",
|
"topics": "トピック",
|
||||||
"warning": "警告",
|
"warning": "警告",
|
||||||
"you": "あなた"
|
"you": "あなた",
|
||||||
|
"more": "もっと"
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "ドキュメント"
|
"title": "ドキュメント"
|
||||||
|
|||||||
@ -222,7 +222,8 @@
|
|||||||
"select": "Выбрать",
|
"select": "Выбрать",
|
||||||
"topics": "Топики",
|
"topics": "Топики",
|
||||||
"warning": "Предупреждение",
|
"warning": "Предупреждение",
|
||||||
"you": "Вы"
|
"you": "Вы",
|
||||||
|
"more": "Ещё"
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "Документация"
|
"title": "Документация"
|
||||||
|
|||||||
@ -222,7 +222,8 @@
|
|||||||
"select": "选择",
|
"select": "选择",
|
||||||
"topics": "话题",
|
"topics": "话题",
|
||||||
"warning": "警告",
|
"warning": "警告",
|
||||||
"you": "用户"
|
"you": "用户",
|
||||||
|
"more": "更多"
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "帮助文档"
|
"title": "帮助文档"
|
||||||
|
|||||||
@ -222,7 +222,8 @@
|
|||||||
"select": "選擇",
|
"select": "選擇",
|
||||||
"topics": "話題",
|
"topics": "話題",
|
||||||
"warning": "警告",
|
"warning": "警告",
|
||||||
"you": "您"
|
"you": "您",
|
||||||
|
"more": "更多"
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "說明文件"
|
"title": "說明文件"
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useTheme } from '@renderer/context/ThemeProvider'
|
|||||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||||
import { addMCPServer, deleteMCPServer, setMCPServerActive, updateMCPServer } from '@renderer/store/mcp'
|
import { addMCPServer, deleteMCPServer, setMCPServerActive, updateMCPServer } from '@renderer/store/mcp'
|
||||||
import { MCPServer } from '@renderer/types'
|
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 TextArea from 'antd/es/input/TextArea'
|
||||||
import { FC, useEffect, useState } from 'react'
|
import { FC, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -113,20 +113,20 @@ const MCPSettings: FC = () => {
|
|||||||
window.api.mcp
|
window.api.mcp
|
||||||
.updateServer(mcpServer)
|
.updateServer(mcpServer)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
message.success(t('settings.mcp.updateSuccess'))
|
window.message.success(t('settings.mcp.updateSuccess'))
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
setIsModalVisible(false)
|
setIsModalVisible(false)
|
||||||
form.resetFields()
|
form.resetFields()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
message.error(`${t('settings.mcp.updateError')}: ${error.message}`)
|
window.message.error(`${t('settings.mcp.updateError')}: ${error.message}`)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
dispatch(updateMCPServer(mcpServer))
|
dispatch(updateMCPServer(mcpServer))
|
||||||
} else {
|
} else {
|
||||||
// Check for duplicate name
|
// Check for duplicate name
|
||||||
if (mcpServers.some((server: MCPServer) => server.name === mcpServer.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)
|
setLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -134,13 +134,13 @@ const MCPSettings: FC = () => {
|
|||||||
window.api.mcp
|
window.api.mcp
|
||||||
.addServer(mcpServer)
|
.addServer(mcpServer)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
message.success(t('settings.mcp.addSuccess'))
|
window.message.success(t('settings.mcp.addSuccess'))
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
setIsModalVisible(false)
|
setIsModalVisible(false)
|
||||||
form.resetFields()
|
form.resetFields()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
message.error(`${t('settings.mcp.addError')}: ${error.message}`)
|
window.message.error(`${t('settings.mcp.addError')}: ${error.message}`)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
dispatch(addMCPServer(mcpServer))
|
dispatch(addMCPServer(mcpServer))
|
||||||
@ -152,20 +152,21 @@ const MCPSettings: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleDelete = (serverName: string) => {
|
const handleDelete = (serverName: string) => {
|
||||||
Modal.confirm({
|
window.modal.confirm({
|
||||||
title: t('settings.mcp.confirmDelete'),
|
title: t('settings.mcp.confirmDelete'),
|
||||||
content: t('settings.mcp.confirmDeleteMessage'),
|
content: t('settings.mcp.confirmDeleteMessage'),
|
||||||
okText: t('common.delete'),
|
okText: t('common.delete'),
|
||||||
okButtonProps: { danger: true },
|
okButtonProps: { danger: true },
|
||||||
cancelText: t('common.cancel'),
|
cancelText: t('common.cancel'),
|
||||||
|
centered: true,
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
window.api.mcp
|
window.api.mcp
|
||||||
.deleteServer(serverName)
|
.deleteServer(serverName)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
message.success(t('settings.mcp.deleteSuccess'))
|
window.message.success(t('settings.mcp.deleteSuccess'))
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
message.error(`${t('settings.mcp.deleteError')}: ${error.message}`)
|
window.message.error(`${t('settings.mcp.deleteError')}: ${error.message}`)
|
||||||
})
|
})
|
||||||
dispatch(deleteMCPServer(serverName))
|
dispatch(deleteMCPServer(serverName))
|
||||||
}
|
}
|
||||||
@ -179,7 +180,7 @@ const MCPSettings: FC = () => {
|
|||||||
// Optional: Show success message or update UI
|
// Optional: Show success message or update UI
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
message.error(`${t('settings.mcp.toggleError')}: ${error.message}`)
|
window.message.error(`${t('settings.mcp.toggleError')}: ${error.message}`)
|
||||||
})
|
})
|
||||||
dispatch(setMCPServerActive({ name, isActive }))
|
dispatch(setMCPServerActive({ name, isActive }))
|
||||||
}
|
}
|
||||||
@ -217,7 +218,7 @@ const MCPSettings: FC = () => {
|
|||||||
ellipsis={{
|
ellipsis={{
|
||||||
rows: 1,
|
rows: 1,
|
||||||
expandable: 'collapsible',
|
expandable: 'collapsible',
|
||||||
symbol: 'more',
|
symbol: t('common.more'),
|
||||||
onExpand: () => {}, // Empty callback required for proper functionality
|
onExpand: () => {}, // Empty callback required for proper functionality
|
||||||
tooltip: true
|
tooltip: true
|
||||||
}}
|
}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user