From ed34c2b929f02d801be9efdf2ae597537b89d902 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 25 Mar 2026 11:29:31 +0000 Subject: [PATCH] fix: tool name in agent builder --- application/api/user/base.py | 4 +++- frontend/src/agents/NewAgent.tsx | 11 +++++++--- frontend/src/agents/SharedAgentCard.tsx | 5 +++-- .../src/agents/workflow/WorkflowBuilder.tsx | 4 +++- frontend/src/utils/toolUtils.ts | 17 ++++++++++++++++ tests/api/user/test_base.py | 20 +++++++++++++++++++ 6 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 frontend/src/utils/toolUtils.ts diff --git a/application/api/user/base.py b/application/api/user/base.py index d4f70aa6..920af776 100644 --- a/application/api/user/base.py +++ b/application/api/user/base.py @@ -152,7 +152,9 @@ def resolve_tool_details(tool_ids): { "id": str(tool["_id"]), "name": tool.get("name", ""), - "display_name": tool.get("displayName", tool.get("name", "")), + "display_name": tool.get("customName") + or tool.get("displayName") + or tool.get("name", ""), } for tool in tools ] diff --git a/frontend/src/agents/NewAgent.tsx b/frontend/src/agents/NewAgent.tsx index af77f6a9..c9a5e55d 100644 --- a/frontend/src/agents/NewAgent.tsx +++ b/frontend/src/agents/NewAgent.tsx @@ -28,6 +28,7 @@ import { import PromptsModal from '../preferences/PromptsModal'; import Prompts from '../settings/Prompts'; import { UserToolType } from '../settings/types'; +import { getToolDisplayName } from '../utils/toolUtils'; import AgentPreview from './AgentPreview'; import { Agent, ToolSummary } from './types'; import WorkflowBuilder from './workflow/WorkflowBuilder'; @@ -428,8 +429,9 @@ export default function NewAgent({ mode }: { mode: 'new' | 'edit' | 'draft' }) { const data = await response.json(); const tools: OptionType[] = data.tools.map((tool: UserToolType) => ({ id: tool.id, - label: tool.customName ? tool.customName : tool.displayName, + label: getToolDisplayName(tool), icon: `/toolIcons/tool_${tool.name}.svg`, + name: tool.name, })); setUserTools(tools); }; @@ -956,7 +958,7 @@ export default function NewAgent({ mode }: { mode: 'new' | 'edit' | 'draft' }) { > {selectedTools.length > 0 ? selectedTools - .map((tool) => tool.display_name || tool.name) + .map((tool) => getToolDisplayName(tool)) .filter(Boolean) .join(', ') : t('agents.form.placeholders.selectTools')} @@ -973,7 +975,10 @@ export default function NewAgent({ mode }: { mode: 'new' | 'edit' | 'draft' }) { .filter((tool) => newSelectedIds.has(tool.id)) .map((tool) => ({ id: String(tool.id), - name: tool.label, + name: + typeof tool.name === 'string' + ? tool.name + : tool.label, display_name: tool.label, })), ) diff --git a/frontend/src/agents/SharedAgentCard.tsx b/frontend/src/agents/SharedAgentCard.tsx index a2b02c87..412750fa 100644 --- a/frontend/src/agents/SharedAgentCard.tsx +++ b/frontend/src/agents/SharedAgentCard.tsx @@ -1,4 +1,5 @@ import AgentImage from '../components/AgentImage'; +import { getToolDisplayName } from '../utils/toolUtils'; import { Agent } from './types'; export default function SharedAgentCard({ agent }: { agent: Agent }) { @@ -64,10 +65,10 @@ export default function SharedAgentCard({ agent }: { agent: Agent }) { > {`${tool.name}{' '} - {tool.name} + {getToolDisplayName(tool)} ))} diff --git a/frontend/src/agents/workflow/WorkflowBuilder.tsx b/frontend/src/agents/workflow/WorkflowBuilder.tsx index b1b5faf6..12c9a070 100644 --- a/frontend/src/agents/workflow/WorkflowBuilder.tsx +++ b/frontend/src/agents/workflow/WorkflowBuilder.tsx @@ -55,6 +55,7 @@ import AgentDetailsModal from '../../modals/AgentDetailsModal'; import ConfirmationModal from '../../modals/ConfirmationModal'; import { ActiveState } from '../../models/misc'; import { selectToken } from '../../preferences/preferenceSlice'; +import { getToolDisplayName } from '../../utils/toolUtils'; import { Agent } from '../types'; import { ConditionCase, WorkflowNode } from '../types/workflow'; import MobileBlocker from './components/MobileBlocker'; @@ -92,6 +93,7 @@ interface UserTool { id: string; name: string; displayName: string; + customName?: string; } function validateJsonSchemaConfig(schema: unknown): string | null { @@ -1887,7 +1889,7 @@ function WorkflowBuilderInner() { ({ value: tool.id, - label: tool.displayName, + label: getToolDisplayName(tool), }))} selected={ selectedNode.data.config?.tools || [] diff --git a/frontend/src/utils/toolUtils.ts b/frontend/src/utils/toolUtils.ts new file mode 100644 index 00000000..e97b3429 --- /dev/null +++ b/frontend/src/utils/toolUtils.ts @@ -0,0 +1,17 @@ +type ToolLabelSource = { + customName?: string | null; + displayName?: string | null; + display_name?: string | null; + name?: string | null; +}; + +const isNonEmptyString = (value: unknown): value is string => + typeof value === 'string' && value.trim().length > 0; + +export function getToolDisplayName(tool: ToolLabelSource): string { + if (isNonEmptyString(tool.customName)) return tool.customName.trim(); + if (isNonEmptyString(tool.displayName)) return tool.displayName.trim(); + if (isNonEmptyString(tool.display_name)) return tool.display_name.trim(); + if (isNonEmptyString(tool.name)) return tool.name.trim(); + return ''; +} diff --git a/tests/api/user/test_base.py b/tests/api/user/test_base.py index 0190ac46..d0843750 100644 --- a/tests/api/user/test_base.py +++ b/tests/api/user/test_base.py @@ -150,6 +150,26 @@ class TestResolveToolDetails: assert result[0]["display_name"] == "test_tool" + def test_prefers_custom_name_when_present(self, mock_mongo_db): + from application.api.user.base import resolve_tool_details + from application.core.settings import settings + + user_tools = mock_mongo_db[settings.MONGO_DB_NAME]["user_tools"] + tool_id = ObjectId() + + user_tools.insert_one( + { + "_id": tool_id, + "name": "calculator", + "displayName": "Calculator Tool", + "customName": "Math Wizard", + } + ) + + result = resolve_tool_details([str(tool_id)]) + + assert result[0]["display_name"] == "Math Wizard" + def test_empty_tool_ids_list(self, mock_mongo_db): from application.api.user.base import resolve_tool_details