Skip to content

Commit ed34c2b

Browse files
committed
fix: tool name in agent builder
1 parent 06e8275 commit ed34c2b

6 files changed

Lines changed: 54 additions & 7 deletions

File tree

application/api/user/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ def resolve_tool_details(tool_ids):
152152
{
153153
"id": str(tool["_id"]),
154154
"name": tool.get("name", ""),
155-
"display_name": tool.get("displayName", tool.get("name", "")),
155+
"display_name": tool.get("customName")
156+
or tool.get("displayName")
157+
or tool.get("name", ""),
156158
}
157159
for tool in tools
158160
]

frontend/src/agents/NewAgent.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
import PromptsModal from '../preferences/PromptsModal';
2929
import Prompts from '../settings/Prompts';
3030
import { UserToolType } from '../settings/types';
31+
import { getToolDisplayName } from '../utils/toolUtils';
3132
import AgentPreview from './AgentPreview';
3233
import { Agent, ToolSummary } from './types';
3334
import WorkflowBuilder from './workflow/WorkflowBuilder';
@@ -428,8 +429,9 @@ export default function NewAgent({ mode }: { mode: 'new' | 'edit' | 'draft' }) {
428429
const data = await response.json();
429430
const tools: OptionType[] = data.tools.map((tool: UserToolType) => ({
430431
id: tool.id,
431-
label: tool.customName ? tool.customName : tool.displayName,
432+
label: getToolDisplayName(tool),
432433
icon: `/toolIcons/tool_${tool.name}.svg`,
434+
name: tool.name,
433435
}));
434436
setUserTools(tools);
435437
};
@@ -956,7 +958,7 @@ export default function NewAgent({ mode }: { mode: 'new' | 'edit' | 'draft' }) {
956958
>
957959
{selectedTools.length > 0
958960
? selectedTools
959-
.map((tool) => tool.display_name || tool.name)
961+
.map((tool) => getToolDisplayName(tool))
960962
.filter(Boolean)
961963
.join(', ')
962964
: t('agents.form.placeholders.selectTools')}
@@ -973,7 +975,10 @@ export default function NewAgent({ mode }: { mode: 'new' | 'edit' | 'draft' }) {
973975
.filter((tool) => newSelectedIds.has(tool.id))
974976
.map((tool) => ({
975977
id: String(tool.id),
976-
name: tool.label,
978+
name:
979+
typeof tool.name === 'string'
980+
? tool.name
981+
: tool.label,
977982
display_name: tool.label,
978983
})),
979984
)

frontend/src/agents/SharedAgentCard.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import AgentImage from '../components/AgentImage';
2+
import { getToolDisplayName } from '../utils/toolUtils';
23
import { Agent } from './types';
34

45
export default function SharedAgentCard({ agent }: { agent: Agent }) {
@@ -64,10 +65,10 @@ export default function SharedAgentCard({ agent }: { agent: Agent }) {
6465
>
6566
<img
6667
src={`/toolIcons/tool_${tool.name}.svg`}
67-
alt={`${tool.name} icon`}
68+
alt={`${getToolDisplayName(tool)} icon`}
6869
className="h-3 w-3"
6970
/>{' '}
70-
{tool.name}
71+
{getToolDisplayName(tool)}
7172
</span>
7273
))}
7374
</div>

frontend/src/agents/workflow/WorkflowBuilder.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import AgentDetailsModal from '../../modals/AgentDetailsModal';
5555
import ConfirmationModal from '../../modals/ConfirmationModal';
5656
import { ActiveState } from '../../models/misc';
5757
import { selectToken } from '../../preferences/preferenceSlice';
58+
import { getToolDisplayName } from '../../utils/toolUtils';
5859
import { Agent } from '../types';
5960
import { ConditionCase, WorkflowNode } from '../types/workflow';
6061
import MobileBlocker from './components/MobileBlocker';
@@ -92,6 +93,7 @@ interface UserTool {
9293
id: string;
9394
name: string;
9495
displayName: string;
96+
customName?: string;
9597
}
9698

9799
function validateJsonSchemaConfig(schema: unknown): string | null {
@@ -1887,7 +1889,7 @@ function WorkflowBuilderInner() {
18871889
<MultiSelect
18881890
options={availableTools.map((tool) => ({
18891891
value: tool.id,
1890-
label: tool.displayName,
1892+
label: getToolDisplayName(tool),
18911893
}))}
18921894
selected={
18931895
selectedNode.data.config?.tools || []

frontend/src/utils/toolUtils.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
type ToolLabelSource = {
2+
customName?: string | null;
3+
displayName?: string | null;
4+
display_name?: string | null;
5+
name?: string | null;
6+
};
7+
8+
const isNonEmptyString = (value: unknown): value is string =>
9+
typeof value === 'string' && value.trim().length > 0;
10+
11+
export function getToolDisplayName(tool: ToolLabelSource): string {
12+
if (isNonEmptyString(tool.customName)) return tool.customName.trim();
13+
if (isNonEmptyString(tool.displayName)) return tool.displayName.trim();
14+
if (isNonEmptyString(tool.display_name)) return tool.display_name.trim();
15+
if (isNonEmptyString(tool.name)) return tool.name.trim();
16+
return '';
17+
}

tests/api/user/test_base.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,26 @@ def test_handles_missing_display_name(self, mock_mongo_db):
150150

151151
assert result[0]["display_name"] == "test_tool"
152152

153+
def test_prefers_custom_name_when_present(self, mock_mongo_db):
154+
from application.api.user.base import resolve_tool_details
155+
from application.core.settings import settings
156+
157+
user_tools = mock_mongo_db[settings.MONGO_DB_NAME]["user_tools"]
158+
tool_id = ObjectId()
159+
160+
user_tools.insert_one(
161+
{
162+
"_id": tool_id,
163+
"name": "calculator",
164+
"displayName": "Calculator Tool",
165+
"customName": "Math Wizard",
166+
}
167+
)
168+
169+
result = resolve_tool_details([str(tool_id)])
170+
171+
assert result[0]["display_name"] == "Math Wizard"
172+
153173
def test_empty_tool_ids_list(self, mock_mongo_db):
154174
from application.api.user.base import resolve_tool_details
155175

0 commit comments

Comments
 (0)