diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 65db2223..a66cb06c 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -69,7 +69,7 @@ export default defineConfig({ } }, optimizeDeps: { - exclude: ['chunk-PZ64DZKH.js', 'chunk-JMKENWIY.js', 'chunk-UXYB6GHG.js'] + exclude: ['chunk-PZ64DZKH.js', 'chunk-JMKENWIY.js', 'chunk-UXYB6GHG.js', 'chunk-ALDIEZMG.js'] } } }) diff --git a/src/main/services/MCPService.ts b/src/main/services/MCPService.ts index 4726b464..f386aba1 100644 --- a/src/main/services/MCPService.ts +++ b/src/main/services/MCPService.ts @@ -28,7 +28,6 @@ export default class MCPService extends EventEmitter { constructor() { super() this.createServerLoadingPromise() - this.requestServers() } /** @@ -40,19 +39,6 @@ export default class MCPService extends EventEmitter { }) } - /** - * Request server data from renderer process Redux - */ - public requestServers(): void { - const mainWindow = windowService.getMainWindow() - if (mainWindow) { - log.info('[MCP] Requesting servers from Redux') - mainWindow.webContents.send('mcp:request-servers') - } else { - log.warn('[MCP] Main window not available, cannot request servers') - } - } - /** * Set servers received from Redux and trigger initialization if needed */ diff --git a/src/renderer/src/components/Icons/ToolsCallingIcon.tsx b/src/renderer/src/components/Icons/ToolsCallingIcon.tsx index 7009fb8a..323c9570 100644 --- a/src/renderer/src/components/Icons/ToolsCallingIcon.tsx +++ b/src/renderer/src/components/Icons/ToolsCallingIcon.tsx @@ -9,7 +9,7 @@ const ToolsCallingIcon: FC - + diff --git a/src/renderer/src/components/ModelTags.tsx b/src/renderer/src/components/ModelTags.tsx index 6415d725..0bc3038b 100644 --- a/src/renderer/src/components/ModelTags.tsx +++ b/src/renderer/src/components/ModelTags.tsx @@ -1,7 +1,7 @@ import { isEmbeddingModel, + isFunctionCallingModel, isReasoningModel, - isToolCallingModel, isVisionModel, isWebSearchModel } from '@renderer/config/models' @@ -31,7 +31,7 @@ const ModelTags: FC = ({ model, showFree = true, showReasoning = {isVisionModel(model) && } {isWebSearchModel(model) && } {showReasoning && isReasoningModel(model) && } - {showToolsCalling && isToolCallingModel(model) && } + {showToolsCalling && isFunctionCallingModel(model) && } {isEmbeddingModel(model) && {t('models.embedding')}} {showFree && isFreeModel(model) && {t('models.free')}} diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 0985560b..064eb152 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -178,14 +178,18 @@ 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', 'qwen'] -export const TOOL_CALLING_REGEX = new RegExp(`\\b(?:${TOOL_CALLING_MODELS.join('|')})\\b`, 'i') -export function isToolCallingModel(model: Model): boolean { +export const FUNCTION_CALLING_MODELS = ['gpt-4o', 'gpt-4o-mini', 'gpt-4', 'gpt-4.5', 'claude', 'qwen'] +export const FUNCTION_CALLING_REGEX = new RegExp(`\\b(?:${FUNCTION_CALLING_MODELS.join('|')})\\b`, 'i') +export function isFunctionCallingModel(model: Model): boolean { + if (model.type?.includes('function_calling')) { + return true + } + if (['gemini', 'deepseek', 'anthropic'].includes(model.provider)) { return true } - return TOOL_CALLING_REGEX.test(model.id) + return FUNCTION_CALLING_REGEX.test(model.id) } export function getModelLogo(modelId: string) { @@ -1741,21 +1745,7 @@ export const SYSTEM_MODELS: Record = { group: 'Jina' } ], - //加前缀是为了展示图标 - xirang: [ - { - id: 'xirang-4bd107bff85941239e27b1509eccfe98', - provider: 'xirang', - name: 'DeepSeek-R1', - group: 'xirang' - }, - { - id: 'xirang-9dc913a037774fc0b248376905c85da5', - provider: 'xirang', - name: 'DeepSeek-V3', - group: 'xirang' - } - ], + xirang: [], 'tencent-cloud-ti': [ { id: 'deepseek-r1', diff --git a/src/renderer/src/hooks/useMCPServers.ts b/src/renderer/src/hooks/useMCPServers.ts index 9a5cb0f9..8e04a701 100644 --- a/src/renderer/src/hooks/useMCPServers.ts +++ b/src/renderer/src/hooks/useMCPServers.ts @@ -5,12 +5,6 @@ import { useEffect } from 'react' const ipcRenderer = window.electron.ipcRenderer -// Set up IPC listener for main process requests -ipcRenderer.on('mcp:request-servers', () => { - 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) => { store.dispatch(setMCPServers(servers)) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 369d5f59..e25b2782 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -505,13 +505,14 @@ "reasoning": "Reasoning", "search": "Search models...", "stream_output": "Stream output", - "tool_calling": "Tool Calling", + "function_calling": "Function Calling", "type": { "embedding": "Embedding", "reasoning": "Reasoning", "select": "Select Model Types", "text": "Text", - "vision": "Vision" + "vision": "Vision", + "function_calling": "Function Calling" }, "vision": "Vision", "websearch": "WebSearch" diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index ff0e5747..8fb8b2b1 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -505,13 +505,14 @@ "reasoning": "推論", "search": "モデルを検索...", "stream_output": "ストリーム出力", - "tool_calling": "ツールコール", + "function_calling": "関数呼び出し", "type": { "embedding": "埋め込み", "reasoning": "推論", "select": "モデルタイプを選択", "text": "テキスト", - "vision": "画像" + "vision": "画像", + "function_calling": "関数呼び出し" }, "vision": "画像", "websearch": "ウェブ検索" diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 846d30e9..65f7fda5 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -505,13 +505,14 @@ "reasoning": "Рассуждение", "search": "Поиск моделей...", "stream_output": "Потоковый вывод", - "tool_calling": "Инструмент вызова", + "function_calling": "Вызов функции", "type": { "embedding": "Встраиваемые", "reasoning": "Рассуждение", "select": "Выберите тип модели", "text": "Текст", - "vision": "Изображение" + "vision": "Изображение", + "function_calling": "Вызов функции" }, "vision": "Визуальные", "websearch": "Веб-поисковые" diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 53d1a6ac..5c514945 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -505,13 +505,14 @@ "reasoning": "推理", "search": "搜索模型...", "stream_output": "流式输出", - "tool_calling": "工具调用", + "function_calling": "函数调用", "type": { "embedding": "嵌入", "reasoning": "推理", "select": "选择模型类型", "text": "文本", - "vision": "图像" + "vision": "图像", + "function_calling": "函数调用" }, "vision": "视觉", "websearch": "联网" diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index dbe58e97..d300d2cb 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -505,13 +505,14 @@ "reasoning": "推理", "search": "搜尋模型...", "stream_output": "串流輸出", - "tool_calling": "工具調用", + "function_calling": "函數調用", "type": { "embedding": "嵌入", "reasoning": "推理", "select": "選擇模型類型", "text": "文字", - "vision": "影像" + "vision": "影像", + "function_calling": "函數調用" }, "vision": "視覺", "websearch": "網路搜尋" diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index 5ff93e73..d03a6d54 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -8,7 +8,7 @@ import { useKnowledgeFiles } from '@renderer/hooks/useKnowledgeFiles' import { reset } from '@renderer/services/BackupService' import { AppInfo } from '@renderer/types' import { formatFileSize } from '@renderer/utils' -import { Button, Modal, Typography } from 'antd' +import { Button, Typography } from 'antd' import { FC, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -49,7 +49,7 @@ const DataSettings: FC = () => { } const handleClearCache = () => { - Modal.confirm({ + window.modal.confirm({ title: t('settings.data.clear_cache.title'), content: t('settings.data.clear_cache.confirm'), okText: t('settings.data.clear_cache.button'), @@ -69,7 +69,7 @@ const DataSettings: FC = () => { } const handleRemoveAllFiles = () => { - Modal.confirm({ + window.modal.confirm({ centered: true, title: t('settings.data.app_knowledge.remove_all') + ` (${formatFileSize(size)}) `, content: t('settings.data.app_knowledge.remove_all_confirm'), diff --git a/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx b/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx index 5aa7ea42..66c37ca9 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx @@ -1,5 +1,5 @@ import { DownOutlined, UpOutlined } from '@ant-design/icons' -import { isEmbeddingModel, isReasoningModel, isVisionModel } from '@renderer/config/models' +import { isEmbeddingModel, isFunctionCallingModel, isReasoningModel, isVisionModel } from '@renderer/config/models' import { Model, ModelType } from '@renderer/types' import { getDefaultGroupName } from '@renderer/utils' import { Button, Checkbox, Divider, Flex, Form, Input, Modal } from 'antd' @@ -112,14 +112,15 @@ const ModelEditContent: FC = ({ model, onUpdateModel, ope const defaultTypes = [ ...(isVisionModel(model) ? ['vision'] : []), ...(isEmbeddingModel(model) ? ['embedding'] : []), - ...(isReasoningModel(model) ? ['reasoning'] : []) + ...(isReasoningModel(model) ? ['reasoning'] : []), + ...(isFunctionCallingModel(model) ? ['tools'] : []) ] as ModelType[] // 合并现有选择和默认类型 const selectedTypes = [...new Set([...(model.type || []), ...defaultTypes])] const showTypeConfirmModal = (type: string) => { - Modal.confirm({ + window.modal.confirm({ title: t('settings.moresetting.warn'), content: t('settings.moresetting.check.warn'), okText: t('settings.moresetting.check.confirm'), @@ -161,6 +162,11 @@ const ModelEditContent: FC = ({ model, onUpdateModel, ope label: t('models.type.reasoning'), value: 'reasoning', disabled: isReasoningModel(model) && !selectedTypes.includes('reasoning') + }, + { + label: t('models.type.function_calling'), + value: 'function_calling', + disabled: isFunctionCallingModel(model) && !selectedTypes.includes('function_calling') } ]} /> diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index 7b4c022c..458eaade 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -119,7 +119,7 @@ export type Provider = { export type ProviderType = 'openai' | 'anthropic' | 'gemini' | 'qwenlm' | 'azure-openai' -export type ModelType = 'text' | 'vision' | 'embedding' | 'reasoning' +export type ModelType = 'text' | 'vision' | 'embedding' | 'reasoning' | 'function_calling' export type Model = { id: string