mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 03:31:24 +08:00
fix: better mcp tool match and feedback (#8825)
* feat(mcp): 添加多工具匹配时的警告提示 当匹配到多个MCP工具或未匹配到所需工具时,显示相应的警告信息。同时在i18n中添加对应的翻译字段。 * feat(i18n): 添加MCP工具警告信息和模型列表刷新功能的多语言支持 * fix(mcp): 修复工具调用解析错误并优化日志消息 添加对工具调用解析错误的处理,当解析失败时显示错误信息 统一工具调用相关的日志消息格式,使用字符串插值替代拼接 * feat(i18n): 为MCP工具添加解析错误的多语言支持
This commit is contained in:
parent
d8d0ab5fc4
commit
636a430eb9
@ -383,6 +383,15 @@
|
||||
"settings": "Web Search Settings"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "Unable to convert to a valid tool call format: {{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "Multiple matching MCP tools exist, {{tool}} has been selected",
|
||||
"no_tool": "No matching MCP tool found for {{tool}}"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "ウェブ検索設定"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "有効なツール呼び出し形式に変換できません:{{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "複数の一致するMCPツールが存在するため、{{tool}} が選択されました",
|
||||
"no_tool": "必要なMCPツール {{tool}} が見つかりません"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "Настройки веб-поиска"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "Не удалось преобразовать в действительный формат вызова инструмента: {{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "Существует несколько совпадающих инструментов MCP, выбран {{tool}}",
|
||||
"no_tool": "Не удалось сопоставить требуемый инструмент MCP {{tool}}"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "网络搜索设置"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "无法转换为有效的工具调用格式:{{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "存在多个匹配的MCP工具,已选择 {{tool}}",
|
||||
"no_tool": "未匹配到所需的MCP工具 {{tool}}"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "網路搜尋設定"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "無法轉換為有效的工具呼叫格式:{{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "存在多個匹配的MCP工具,已選擇 {{tool}}",
|
||||
"no_tool": "未匹配到所需的MCP工具 {{tool}}"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "Ρυθμίσεις αναζήτησης στο διαδίκτυο"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "Δεν είναι δυνατή η μετατροπή σε έγκυρη μορφή κλήσης εργαλείου: {{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "Υπάρχουν πολλαπλά εργαλεία MCP που ταιριάζουν, επιλέχθηκε το {{tool}}",
|
||||
"no_tool": "Δεν βρέθηκε το απαιτούμενο εργαλείο MCP {{tool}}"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
@ -2991,6 +3000,7 @@
|
||||
"label": "Προσθήκη μοντέλων από τη λίστα"
|
||||
},
|
||||
"add_whole_group": "Προσθήκη ολόκληρης ομάδας",
|
||||
"refetch_list": "Επαναλήψτε τη λήψη της λίστας μοντέλων",
|
||||
"remove_listed": "Αφαίρεση μοντέλων από τη λίστα",
|
||||
"remove_model": "Αφαίρεση Μοντέλου",
|
||||
"remove_whole_group": "Αφαίρεση ολόκληρης ομάδας"
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "Configuración de búsqueda en red"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "No se puede convertir al formato de llamada de herramienta válido: {{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "Existen múltiples herramientas MCP coincidentes, se ha seleccionado {{tool}}",
|
||||
"no_tool": "No se encontró la herramienta MCP requerida {{tool}}"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
@ -2991,6 +3000,7 @@
|
||||
"label": "Agregar modelo en la lista"
|
||||
},
|
||||
"add_whole_group": "Agregar todo el grupo",
|
||||
"refetch_list": "Volver a obtener la lista de modelos",
|
||||
"remove_listed": "Eliminar modelo de la lista",
|
||||
"remove_model": "Eliminar modelo",
|
||||
"remove_whole_group": "Eliminar todo el grupo"
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "Paramètres de recherche en ligne"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "Impossible de convertir au format d'appel d'outil valide : {{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "Il existe plusieurs outils MCP correspondants, {{tool}} a été sélectionné",
|
||||
"no_tool": "Aucun outil MCP requis {{tool}} n'a été trouvé"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
@ -2991,6 +3000,7 @@
|
||||
"label": "Ajouter le modèle dans la liste"
|
||||
},
|
||||
"add_whole_group": "Ajouter tout le groupe",
|
||||
"refetch_list": "Récupérer à nouveau la liste des modèles",
|
||||
"remove_listed": "Supprimer un modèle de la liste",
|
||||
"remove_model": "Supprimer le modèle",
|
||||
"remove_whole_group": "Supprimer tout le groupe"
|
||||
|
||||
@ -383,6 +383,15 @@
|
||||
"settings": "Configurações de Pesquisa na Web"
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"error": {
|
||||
"parse_tool_call": "Não é possível converter para um formato de chamada de ferramenta válido: {{toolCall}}"
|
||||
},
|
||||
"warning": {
|
||||
"multiple_tools": "Existem várias ferramentas MCP correspondentes, a ferramenta {{tool}} foi selecionada",
|
||||
"no_tool": "Nenhuma ferramenta MCP necessária correspondente encontrada {{tool}}"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"new": {
|
||||
"branch": {
|
||||
@ -2991,6 +3000,7 @@
|
||||
"label": "Adicionar modelo da lista"
|
||||
},
|
||||
"add_whole_group": "Adicionar todo o grupo",
|
||||
"refetch_list": "Obter novamente a lista de modelos",
|
||||
"remove_listed": "Remover modelo da lista",
|
||||
"remove_model": "Remover Modelo",
|
||||
"remove_whole_group": "Remover todo o grupo"
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
import type { MCPToolCompleteChunk, MCPToolInProgressChunk, MCPToolPendingChunk } from '@renderer/types/chunk'
|
||||
import { ChunkType } from '@renderer/types/chunk'
|
||||
import { AwsBedrockSdkMessageParam, AwsBedrockSdkTool, AwsBedrockSdkToolCall } from '@renderer/types/sdk'
|
||||
import { t } from 'i18next'
|
||||
import { isArray, isObject, pull, transform } from 'lodash'
|
||||
import { nanoid } from 'nanoid'
|
||||
import OpenAI from 'openai'
|
||||
@ -253,20 +254,33 @@ export function openAIToolsToMcpTool(
|
||||
mcpTools: MCPTool[],
|
||||
toolCall: OpenAI.Responses.ResponseFunctionToolCall | ChatCompletionMessageToolCall
|
||||
): MCPTool | undefined {
|
||||
const tool = mcpTools.find((mcpTool) => {
|
||||
let toolName = ''
|
||||
try {
|
||||
if ('name' in toolCall) {
|
||||
return mcpTool.id === toolCall.name || mcpTool.name === toolCall.name
|
||||
toolName = toolCall.name
|
||||
} else {
|
||||
return mcpTool.id === toolCall.function.name || mcpTool.name === toolCall.function.name
|
||||
toolName = toolCall.function.name
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Error parsing tool call: ${toolCall}`, error as Error)
|
||||
window.message.error(t('chat.mcp.error.parse_tool_call', { toolCall: toolCall }))
|
||||
return undefined
|
||||
}
|
||||
const tools = mcpTools.filter((mcpTool) => {
|
||||
return mcpTool.id === toolName || mcpTool.name === toolName
|
||||
})
|
||||
if (tools.length > 1) {
|
||||
logger.warn(`Multiple MCP Tools found for tool call: ${toolName}`)
|
||||
window.message.warning(t('chat.mcp.warning.multiple_tools', { tool: tools[0].name }))
|
||||
}
|
||||
|
||||
if (!tool) {
|
||||
logger.warn('No MCP Tool found for tool call:', toolCall)
|
||||
if (tools.length === 0) {
|
||||
logger.warn(`No MCP Tool found for tool call: ${toolName}`)
|
||||
window.message.warning(t('chat.mcp.warning.no_tool', { tool: toolName }))
|
||||
return undefined
|
||||
}
|
||||
|
||||
return tool
|
||||
return tools[0]
|
||||
}
|
||||
|
||||
export async function callBuiltInTool(toolResponse: MCPToolResponse): Promise<MCPCallToolResponse | undefined> {
|
||||
@ -358,11 +372,17 @@ export function mcpToolsToAnthropicTools(mcpTools: MCPTool[]): Array<ToolUnion>
|
||||
|
||||
export function anthropicToolUseToMcpTool(mcpTools: MCPTool[] | undefined, toolUse: ToolUseBlock): MCPTool | undefined {
|
||||
if (!mcpTools) return undefined
|
||||
const tool = mcpTools.find((tool) => tool.id === toolUse.name)
|
||||
if (!tool) {
|
||||
const tools = mcpTools.filter((tool) => tool.id === toolUse.name)
|
||||
if (tools.length === 0) {
|
||||
logger.warn(`No MCP Tool found for tool call: ${toolUse.name}`)
|
||||
window.message.warning(t('chat.mcp.warning.no_tool', { tool: toolUse.name }))
|
||||
return undefined
|
||||
}
|
||||
return tool
|
||||
if (tools.length > 1) {
|
||||
logger.warn(`Multiple MCP Tools found for tool call: ${toolUse.name}`)
|
||||
window.message.warning(t('chat.mcp.warning.multiple_tools', { tool: tools[0].name }))
|
||||
}
|
||||
return tools[0]
|
||||
}
|
||||
|
||||
/**
|
||||
@ -424,9 +444,19 @@ export function geminiFunctionCallToMcpTool(
|
||||
const toolName = toolCall.name || toolCall.id
|
||||
if (!toolName) return undefined
|
||||
|
||||
const tool = mcpTools.find((tool) => tool.id.includes(toolName) || tool.name.includes(toolName))
|
||||
const tools = mcpTools.filter((tool) => tool.id.includes(toolName) || tool.name.includes(toolName))
|
||||
if (tools.length > 1) {
|
||||
logger.warn(`Multiple MCP Tools found for tool call: ${toolName}`)
|
||||
window.message.warning(t('chat.mcp.warning.multiple_tools', { tool: tools[0].name }))
|
||||
}
|
||||
|
||||
return tool
|
||||
if (tools.length === 0) {
|
||||
logger.warn(`No MCP Tool found for tool call: ${toolName}`)
|
||||
window.message.warning(t('chat.mcp.warning.no_tool', { tool: toolName }))
|
||||
return undefined
|
||||
}
|
||||
|
||||
return tools[0]
|
||||
}
|
||||
|
||||
export function upsertMCPToolResponse(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user