Skip to content

Commit a18cf17

Browse files
committed
fix: address review comments for individual tool controls
- Filter tools at the very end of getToolDescriptionsForMode() - Use settings.disabledTools instead of separate parameter - Use translations for tool display names - Allow disabling all tools (not restricted to non-always-available) - Make tool list dynamic based on packages/types/src/tool.ts - Add tests to validate all tools are represented
1 parent 18fe0d7 commit a18cf17

File tree

6 files changed

+134
-159
lines changed

6 files changed

+134
-159
lines changed

src/core/prompts/system.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ ${getToolDescriptionsForMode(
9898
experiments,
9999
partialReadsEnabled,
100100
settings,
101-
settings?.disabledTools,
102101
)}
103102
104103
${getToolUseGuidelinesSection(codeIndexManager)}

src/core/prompts/tools/__tests__/index.spec.ts

Lines changed: 80 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import { describe, it, expect } from "vitest"
44
import { getToolDescriptionsForMode } from "../index"
55
import { defaultModeSlug } from "../../../../shared/modes"
6+
import { toolNames } from "@roo-code/types"
7+
import { TOOL_GROUPS, ALWAYS_AVAILABLE_TOOLS } from "../../../../shared/tools"
68

79
describe("getToolDescriptionsForMode", () => {
810
const mockCwd = "/test/path"
@@ -21,7 +23,6 @@ describe("getToolDescriptionsForMode", () => {
2123
undefined, // experiments
2224
undefined, // partialReadsEnabled
2325
undefined, // settings
24-
undefined, // disabledTools
2526
)
2627

2728
expect(result).toBeTruthy()
@@ -47,8 +48,7 @@ describe("getToolDescriptionsForMode", () => {
4748
undefined,
4849
undefined,
4950
undefined,
50-
undefined,
51-
disabledTools,
51+
{ disabledTools }, // settings object with disabledTools
5252
)
5353

5454
// Check that disabled tools are not included
@@ -60,7 +60,7 @@ describe("getToolDescriptionsForMode", () => {
6060
expect(result).toContain("## search_files")
6161
})
6262

63-
it("should not filter out always-available tools even if disabled", () => {
63+
it("should filter out all tools including always-available tools when disabled", () => {
6464
const disabledTools = ["ask_followup_question", "attempt_completion"]
6565
const result = getToolDescriptionsForMode(
6666
defaultModeSlug,
@@ -73,13 +73,12 @@ describe("getToolDescriptionsForMode", () => {
7373
undefined,
7474
undefined,
7575
undefined,
76-
undefined,
77-
disabledTools,
76+
{ disabledTools }, // settings object with disabledTools
7877
)
7978

80-
// These tools should always be available
81-
expect(result).toContain("## ask_followup_question")
82-
expect(result).toContain("## attempt_completion")
79+
// These tools should be filtered out since we now allow disabling all tools
80+
expect(result).not.toContain("## ask_followup_question")
81+
expect(result).not.toContain("## attempt_completion")
8382
})
8483

8584
it("should handle empty disabled tools array", () => {
@@ -95,8 +94,7 @@ describe("getToolDescriptionsForMode", () => {
9594
undefined,
9695
undefined,
9796
undefined,
98-
undefined,
99-
disabledTools,
97+
{ disabledTools }, // settings object with empty disabledTools
10098
)
10199
const resultWithoutDisabled = getToolDescriptionsForMode(
102100
defaultModeSlug,
@@ -109,8 +107,7 @@ describe("getToolDescriptionsForMode", () => {
109107
undefined,
110108
undefined,
111109
undefined,
112-
undefined,
113-
undefined,
110+
undefined, // no settings
114111
)
115112

116113
// Should return the same tools
@@ -129,8 +126,7 @@ describe("getToolDescriptionsForMode", () => {
129126
undefined,
130127
undefined,
131128
undefined,
132-
undefined,
133-
undefined,
129+
{ disabledTools: undefined }, // settings with undefined disabledTools
134130
)
135131
const resultWithoutDisabled = getToolDescriptionsForMode(
136132
defaultModeSlug,
@@ -143,8 +139,7 @@ describe("getToolDescriptionsForMode", () => {
143139
undefined,
144140
undefined,
145141
undefined,
146-
undefined,
147-
undefined,
142+
undefined, // no settings
148143
)
149144

150145
// Should return the same tools
@@ -164,8 +159,7 @@ describe("getToolDescriptionsForMode", () => {
164159
undefined,
165160
undefined,
166161
undefined,
167-
undefined,
168-
disabledTools,
162+
{ disabledTools }, // settings object with disabledTools
169163
)
170164

171165
// Check that all disabled tools are filtered out
@@ -175,8 +169,8 @@ describe("getToolDescriptionsForMode", () => {
175169

176170
// Check that some other tools are still included
177171
expect(result).toContain("# Tools")
178-
// Always available tools should still be there
179-
expect(result).toContain("## ask_followup_question")
172+
// Other tools that weren't disabled should still be there
173+
expect(result).toContain("## list_code_definition_names")
180174
})
181175

182176
it("should handle invalid tool names in disabled list", () => {
@@ -192,8 +186,7 @@ describe("getToolDescriptionsForMode", () => {
192186
undefined,
193187
undefined,
194188
undefined,
195-
undefined,
196-
disabledTools,
189+
{ disabledTools }, // settings object with disabledTools
197190
)
198191

199192
// Should still filter out valid disabled tools
@@ -217,8 +210,7 @@ describe("getToolDescriptionsForMode", () => {
217210
undefined,
218211
undefined,
219212
undefined,
220-
undefined,
221-
disabledTools,
213+
{ disabledTools }, // settings object with disabledTools
222214
)
223215

224216
// execute_command should be filtered out
@@ -228,4 +220,67 @@ describe("getToolDescriptionsForMode", () => {
228220
expect(result).toContain("## read_file")
229221
expect(result).toContain("## write_to_file")
230222
})
223+
224+
it("should have all tools from packages/types/src/tool.ts represented in TOOL_GROUPS or ALWAYS_AVAILABLE_TOOLS", () => {
225+
// Get all tools from TOOL_GROUPS
226+
const toolsInGroups = new Set<string>()
227+
Object.values(TOOL_GROUPS).forEach((group) => {
228+
group.tools.forEach((tool) => toolsInGroups.add(tool))
229+
})
230+
231+
// Get all tools from ALWAYS_AVAILABLE_TOOLS
232+
const alwaysAvailableSet = new Set(ALWAYS_AVAILABLE_TOOLS)
233+
234+
// Combine both sets
235+
const allRepresentedTools = new Set([...toolsInGroups, ...alwaysAvailableSet])
236+
237+
// Check that every tool from toolNames is represented
238+
const missingTools: string[] = []
239+
toolNames.forEach((toolName) => {
240+
if (!allRepresentedTools.has(toolName)) {
241+
missingTools.push(toolName)
242+
}
243+
})
244+
245+
// Assert that there are no missing tools
246+
expect(missingTools).toEqual([])
247+
})
248+
249+
it("should not have tools in TOOL_GROUPS that are not in packages/types/src/tool.ts", () => {
250+
// Get all tools from TOOL_GROUPS
251+
const toolsInGroups = new Set<string>()
252+
Object.values(TOOL_GROUPS).forEach((group) => {
253+
group.tools.forEach((tool) => toolsInGroups.add(tool))
254+
})
255+
256+
// Convert toolNames to a Set for easier lookup
257+
const validToolNames = new Set(toolNames)
258+
259+
// Check that every tool in TOOL_GROUPS exists in toolNames
260+
const invalidTools: string[] = []
261+
toolsInGroups.forEach((tool) => {
262+
if (!validToolNames.has(tool as any)) {
263+
invalidTools.push(tool)
264+
}
265+
})
266+
267+
// Assert that there are no invalid tools
268+
expect(invalidTools).toEqual([])
269+
})
270+
271+
it("should not have tools in ALWAYS_AVAILABLE_TOOLS that are not in packages/types/src/tool.ts", () => {
272+
// Convert toolNames to a Set for easier lookup
273+
const validToolNames = new Set(toolNames)
274+
275+
// Check that every tool in ALWAYS_AVAILABLE_TOOLS exists in toolNames
276+
const invalidTools: string[] = []
277+
ALWAYS_AVAILABLE_TOOLS.forEach((tool) => {
278+
if (!validToolNames.has(tool)) {
279+
invalidTools.push(tool)
280+
}
281+
})
282+
283+
// Assert that there are no invalid tools
284+
expect(invalidTools).toEqual([])
285+
})
231286
})

src/core/prompts/tools/index.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ export function getToolDescriptionsForMode(
6161
experiments?: Record<string, boolean>,
6262
partialReadsEnabled?: boolean,
6363
settings?: Record<string, any>,
64-
disabledTools?: string[],
6564
): string {
6665
const config = getModeConfig(mode, customModes)
6766
const args: ToolArgs = {
@@ -110,30 +109,31 @@ export function getToolDescriptionsForMode(
110109
tools.delete("codebase_search")
111110
}
112111

113-
// Filter out disabled tools (except always-available tools)
114-
if (disabledTools && disabledTools.length > 0) {
115-
disabledTools.forEach((tool) => {
116-
// Don't filter out always-available tools
117-
if (!ALWAYS_AVAILABLE_TOOLS.includes(tool as any)) {
118-
tools.delete(tool)
119-
}
120-
})
121-
}
122-
123112
// Map tool descriptions for allowed tools
124-
const descriptions = Array.from(tools).map((toolName) => {
125-
const descriptionFn = toolDescriptionMap[toolName]
126-
if (!descriptionFn) {
127-
return undefined
128-
}
113+
const toolsArray = Array.from(tools)
114+
const descriptions = toolsArray
115+
.map((toolName) => {
116+
const descriptionFn = toolDescriptionMap[toolName]
117+
if (!descriptionFn) {
118+
return undefined
119+
}
129120

130-
return descriptionFn({
131-
...args,
132-
toolOptions: undefined, // No tool options in group-based approach
121+
return {
122+
name: toolName,
123+
description: descriptionFn({
124+
...args,
125+
toolOptions: undefined, // No tool options in group-based approach
126+
}),
127+
}
133128
})
134-
})
129+
.filter((item) => item && item.description)
130+
131+
// Filter out disabled tools at the very end using the simplest possible implementation
132+
const enabledDescriptions = descriptions
133+
.filter((item) => !settings?.disabledTools?.includes(item!.name))
134+
.map((item) => item!.description)
135135

136-
return `# Tools\n\n${descriptions.filter(Boolean).join("\n\n")}`
136+
return `# Tools\n\n${enabledDescriptions.join("\n\n")}`
137137
}
138138

139139
// Export individual description functions for backward compatibility

src/core/webview/generateSystemPrompt.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export const generateSystemPrompt = async (provider: ClineProvider, message: Web
2424
language,
2525
maxReadFileLine,
2626
maxConcurrentFileReads,
27-
disabledTools,
2827
} = await provider.getState()
2928

3029
// Check experiment to determine which diff strategy to use
@@ -83,7 +82,7 @@ export const generateSystemPrompt = async (provider: ClineProvider, message: Web
8382
maxReadFileLine !== -1,
8483
{
8584
maxConcurrentFileReads,
86-
disabledTools,
85+
disabledTools: (await provider.getState()).disabledTools,
8786
},
8887
)
8988

0 commit comments

Comments
 (0)