Skip to content

Commit 1c01c77

Browse files
committed
fix: tool call error response
1 parent e5ee35c commit 1c01c77

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

src/tools/services/tool-executor.service.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,104 @@ interface ToolContext {
3838
export class ToolExecutorService {
3939
constructor(private iotApiService: IotApiService) { }
4040

41+
/**
42+
* Validate parameters for a tool
43+
* @param toolName - Name of the tool
44+
* @param params - Parameters to validate
45+
* @returns Error message if validation fails, otherwise null
46+
*/
47+
private validateParams(toolName: string, params: Record<string, unknown>): string | null {
48+
switch (toolName) {
49+
case FETCH_USER_TOOL.name:
50+
// No parameters required for fetchUser
51+
if (Object.keys(params).length > 0) {
52+
return 'fetchUser tool does not accept any parameters.';
53+
}
54+
break;
55+
case SEARCH_TOOL.name:
56+
if (!params.query || typeof params.query !== 'string') {
57+
return 'search tool requires a "query" parameter of type string.';
58+
}
59+
break;
60+
case FETCH_TOOL.name:
61+
if (!params.id || typeof params.id !== 'string') {
62+
return 'fetch tool requires an "id" parameter of type string.';
63+
}
64+
break;
65+
case LIST_DEVICES_TOOL.name:
66+
if (params.locationId && typeof params.locationId !== 'string') {
67+
return 'listDevices tool accepts an optional "locationId" parameter of type string.';
68+
}
69+
break;
70+
case LIST_LOCATIONS_TOOL.name:
71+
// No parameters required for listLocations
72+
if (Object.keys(params).length > 0) {
73+
return 'listLocations tool does not accept any parameters.';
74+
}
75+
break;
76+
case LIST_GROUPS_TOOL.name:
77+
if (params.locationId && typeof params.locationId !== 'string') {
78+
return 'listGroups tool accepts an optional "locationId" parameter of type string.';
79+
}
80+
break;
81+
case GET_DEVICE_TOOL.name:
82+
if (!params.uuid || typeof params.uuid !== 'string') {
83+
return 'getDevice tool requires a "uuid" parameter of type string.';
84+
}
85+
break;
86+
case UPDATE_DEVICE_TOOL.name:
87+
if (!params.uuid || typeof params.uuid !== 'string') {
88+
return 'updateDevice tool requires a "uuid" parameter of type string.';
89+
}
90+
if (Object.keys(params).length <= 1) {
91+
return 'updateDevice tool requires at least one field to update.';
92+
}
93+
break;
94+
case DELETE_DEVICE_TOOL.name:
95+
if (!params.uuid || typeof params.uuid !== 'string') {
96+
return 'deleteDevice tool requires a "uuid" parameter of type string.';
97+
}
98+
break;
99+
case GET_DEVICE_STATE_TOOL.name:
100+
if (!params.deviceUuid || typeof params.deviceUuid !== 'string') {
101+
return 'getDeviceState tool requires a "deviceUuid" parameter of type string.';
102+
}
103+
break;
104+
case GET_LOCATION_STATE_TOOL.name:
105+
if (!params.locationUuid || typeof params.locationUuid !== 'string') {
106+
return 'getLocationState tool requires a "locationUuid" parameter of type string.';
107+
}
108+
break;
109+
case GET_DEVICE_STATE_BY_MAC_TOOL.name:
110+
if (!params.locationUuid || typeof params.locationUuid !== 'string') {
111+
return 'getDeviceStateByMac tool requires a "locationUuid" parameter of type string.';
112+
}
113+
if (!params.macAddress || typeof params.macAddress !== 'string') {
114+
return 'getDeviceStateByMac tool requires a "macAddress" parameter of type string.';
115+
}
116+
break;
117+
case CONTROL_DEVICE_TOOL.name:
118+
if (!params.uuid || typeof params.uuid !== 'string') {
119+
return 'controlDevice tool requires a "uuid" parameter of type string.';
120+
}
121+
if (!params.command || !Array.isArray(params.command)) {
122+
return 'controlDevice tool requires a "command" parameter of type array.';
123+
}
124+
break;
125+
case CONTROL_DEVICE_SIMPLE_TOOL.name:
126+
if (!params.uuid || typeof params.uuid !== 'string') {
127+
return 'controlDeviceSimple tool requires a "uuid" parameter of type string.';
128+
}
129+
if (!params.action || typeof params.action !== 'string') {
130+
return 'controlDeviceSimple tool requires an "action" parameter of type string.';
131+
}
132+
break;
133+
default:
134+
return `Unknown tool: ${toolName}`;
135+
}
136+
return null;
137+
}
138+
41139
/**
42140
* Execute a tool with given parameters and context
43141
* Handles authentication, service delegation, and response formatting
@@ -52,6 +150,22 @@ export class ToolExecutorService {
52150
params: Record<string, unknown>,
53151
context: ToolContext,
54152
): Promise<CallToolResult> {
153+
// Validate parameters before executing the tool
154+
const validationError = this.validateParams(toolName, params);
155+
if (validationError) {
156+
return {
157+
content: [
158+
{
159+
type: 'text' as const,
160+
text: JSON.stringify({
161+
isError: true,
162+
error: validationError,
163+
}),
164+
},
165+
],
166+
};
167+
}
168+
55169
if (toolName === FETCH_USER_TOOL.name) {
56170
return this.executeFetchUser(params as FetchUserParams, context);
57171
}

0 commit comments

Comments
 (0)