From 9b5eafa4a2147041ea20e4b93ba010d398b99521 Mon Sep 17 00:00:00 2001 From: weijihui Date: Mon, 1 Dec 2025 16:44:37 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=86=85=E7=BD=AE=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E5=92=8Cmcp=E5=B7=A5=E5=85=B7=E4=BD=BF=E7=94=A8=E5=86=B2?= =?UTF-8?q?=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presenter/builtInToolsPresenter/base.ts | 1 + .../executeCommandTool.ts | 1 + .../presenter/builtInToolsPresenter/index.ts | 12 +++++- .../builtInToolsPresenter/listFilesTool.ts | 1 + .../builtInToolsPresenter/readFileTool.ts | 1 + .../builtInToolsPresenter/writeFileTool.ts | 1 + .../presenter/llmProviderPresenter/index.ts | 43 ++++++++++++++----- 7 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/main/presenter/builtInToolsPresenter/base.ts b/src/main/presenter/builtInToolsPresenter/base.ts index 8b8973d..e990873 100644 --- a/src/main/presenter/builtInToolsPresenter/base.ts +++ b/src/main/presenter/builtInToolsPresenter/base.ts @@ -2,6 +2,7 @@ import { MCPToolResponse } from '@shared/presenter' export interface BuiltInToolDefinition { name: string + alisa: string[] description: string parameters: { type: string diff --git a/src/main/presenter/builtInToolsPresenter/executeCommandTool.ts b/src/main/presenter/builtInToolsPresenter/executeCommandTool.ts index 8ee5ffe..bd142d2 100644 --- a/src/main/presenter/builtInToolsPresenter/executeCommandTool.ts +++ b/src/main/presenter/builtInToolsPresenter/executeCommandTool.ts @@ -8,6 +8,7 @@ const execAsync = promisify(execCallback) export const executeCommandTool: BuiltInToolDefinition = { name: 'execute_command', + alisa: ['execute_shell'], description: "Requests the execution of a command line instruction and returns the standard output and standard error. Use this tool only when needing to run commands related to the system itself; it cannot be used for network requests or accessing external websites. That is, use it only when there is a clear need, and carefully evaluate the potential side effects of the command. You must tailor the command to the user's system and clearly explain its function. For command chaining, use the appropriate chaining syntax for the user's shell. By default, it runs in the current working directory; other directories or shells can be specified as needed.This tool can only be run on the local system where it is installed. When performing operations such as package installation and uninstallation, it is necessary to first determine the correct package management command.", parameters: { diff --git a/src/main/presenter/builtInToolsPresenter/index.ts b/src/main/presenter/builtInToolsPresenter/index.ts index 298b35a..4b1f824 100644 --- a/src/main/presenter/builtInToolsPresenter/index.ts +++ b/src/main/presenter/builtInToolsPresenter/index.ts @@ -14,7 +14,7 @@ import { listFilesTool, executeListFilesTool } from './listFilesTool' import { executeCommandTool, executeCommandToolHandler } from './executeCommandTool' import { useA2AServerTool, executeUseA2AServerToolHandler } from './useA2AServerTool' -export const BUILT_IN_TOOL_SERVER_NAME = 'polymind-builtin' +export const BUILT_IN_TOOL_SERVER_NAME = 'PolyMind-built-in' export const BUILT_IN_TOOL_SERVER_DESCRIPTION = 'PolyMind built-in tools' export const builtInTools: Record = { @@ -248,7 +248,10 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { required?: string[] } - return { + const aliases = + (builtInTools[tool.name as keyof typeof builtInTools]?.alisa as string[] | undefined) || [] + + const definition: MCPToolDefinition = { type: 'function', function: { name: tool.name, @@ -265,6 +268,11 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { description: BUILT_IN_TOOL_SERVER_DESCRIPTION } } + + // Attach optional alias list for downstream selection logic + ;(definition.function as any).alisa = aliases + + return definition } private parseToolArguments(argumentsText: string): Record { diff --git a/src/main/presenter/builtInToolsPresenter/listFilesTool.ts b/src/main/presenter/builtInToolsPresenter/listFilesTool.ts index 9a27dc3..4903c95 100644 --- a/src/main/presenter/builtInToolsPresenter/listFilesTool.ts +++ b/src/main/presenter/builtInToolsPresenter/listFilesTool.ts @@ -4,6 +4,7 @@ import { BuiltInToolDefinition, BuiltInToolResponse, buildRawData } from './base export const listFilesTool: BuiltInToolDefinition = { name: 'list_files', + alisa: ['list_directory'], description: 'equests to list the names of files and subdirectories in a specified directory. Use this tool when you need to understand the directory structure or confirm the existence of files. By default, it only lists the current level, recursion can be enabled if necessary.', parameters: { diff --git a/src/main/presenter/builtInToolsPresenter/readFileTool.ts b/src/main/presenter/builtInToolsPresenter/readFileTool.ts index 0d1df17..b39f4b3 100644 --- a/src/main/presenter/builtInToolsPresenter/readFileTool.ts +++ b/src/main/presenter/builtInToolsPresenter/readFileTool.ts @@ -4,6 +4,7 @@ import { BuiltInToolDefinition, BuiltInToolResponse, buildRawData } from './base export const readFileTool: BuiltInToolDefinition = { name: 'read_file', + alisa: [], description: 'Requests to read the content of a file at a specified path. Use this tool when you need to inspect an existing file whose content you are unaware of, such as analyzing code, viewing a text file, or extracting information from a configuration file.The output content will have line numbers prefixed to each line (e.g., "1 | const x = 1"), making it easier to reference specific lines when creating diffs or discussing code. It can automatically extract raw text from PDF and DOCX files. It might not work for other types of binary files as it returns the raw content as a string.', parameters: { diff --git a/src/main/presenter/builtInToolsPresenter/writeFileTool.ts b/src/main/presenter/builtInToolsPresenter/writeFileTool.ts index 18e7269..f8e97b3 100644 --- a/src/main/presenter/builtInToolsPresenter/writeFileTool.ts +++ b/src/main/presenter/builtInToolsPresenter/writeFileTool.ts @@ -4,6 +4,7 @@ import { BuiltInToolDefinition, BuiltInToolResponse, buildRawData } from './base export const writeFileTool: BuiltInToolDefinition = { name: 'write_file', + alisa: [], description: 'Requests to write the complete content to a file at a specified path. If the file already exists, it will be overwritten with the provided content. If the file does not exist, a new file will be created. This tool automatically creates all necessary directories required to write the file.', parameters: { diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index 8851e47..9a97d7d 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -801,17 +801,7 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { try { console.log(`[Agent Loop] Iteration ${toolCallCount + 1} for event: ${eventId}`) - let availableTools: MCPToolDefinition[] = [] - const useBuiltInToolsEnabled = this.configPresenter.getUseBuiltInToolsEnabled() - const [mcpTools, builtInTools] = await Promise.all([ - presenter.mcpPresenter.getAllToolDefinitions(enabledMcpTools), - presenter.builtInToolsPresenter.getBuiltInToolDefinitions( - useBuiltInToolsEnabled, - currentAgent - ) - ]) - availableTools = [...mcpTools, ...builtInTools] - + const availableTools = await this.getAvailableTools(enabledMcpTools, currentAgent) const canExecute = this.canExecuteImmediately(providerId) if (!canExecute) { const config = this.getProviderRateLimitConfig(providerId) @@ -1752,6 +1742,37 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { return state?.config || this.DEFAULT_RATE_LIMIT_CONFIG } + private async getAvailableTools( + enabledMcpTools: string[] | undefined, + currentAgent?: Agent | null + ): Promise { + const useBuiltInToolsEnabled = this.configPresenter.getUseBuiltInToolsEnabled() + const [mcpTools, builtInTools] = await Promise.all([ + presenter.mcpPresenter.getAllToolDefinitions(enabledMcpTools), + presenter.builtInToolsPresenter.getBuiltInToolDefinitions( + useBuiltInToolsEnabled, + currentAgent + ) + ]) + + // Collect built-in tool names and aliases to prefer them when functionality overlaps + const builtInNamesAndAliases = new Set() + for (const tool of builtInTools) { + builtInNamesAndAliases.add(tool.function.name) + const aliases = (tool.function as any).alisa + if (Array.isArray(aliases)) { + for (const alias of aliases) { + builtInNamesAndAliases.add(alias) + } + } + } + // Drop MCP tools whose names match any built-in name or alias + const filteredMcpTools = mcpTools.filter( + (tool) => !builtInNamesAndAliases.has(tool.function.name) + ) + return [...builtInTools, ...filteredMcpTools] + } + private canExecuteImmediately(providerId: string): boolean { const state = this.providerRateLimitStates.get(providerId) if (!state || !state.config.enabled) { -- Gitee