Skip to content

feat: add individual tool controls to settings #5964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,27 @@ export const globalSettingsSchema = z.object({
mcpEnabled: z.boolean().optional(),
enableMcpServerCreation: z.boolean().optional(),

// Individual tool controls for prompt generation
enableToolExecuteCommand: z.boolean().optional(),
enableToolReadFile: z.boolean().optional(),
enableToolFetchInstructions: z.boolean().optional(),
enableToolWriteToFile: z.boolean().optional(),
enableToolApplyDiff: z.boolean().optional(),
enableToolInsertContent: z.boolean().optional(),
enableToolSearchAndReplace: z.boolean().optional(),
enableToolSearchFiles: z.boolean().optional(),
enableToolListFiles: z.boolean().optional(),
enableToolListCodeDefinitionNames: z.boolean().optional(),
enableToolBrowserAction: z.boolean().optional(),
enableToolUseMcpTool: z.boolean().optional(),
enableToolAccessMcpResource: z.boolean().optional(),
enableToolAskFollowupQuestion: z.boolean().optional(),
enableToolAttemptCompletion: z.boolean().optional(),
enableToolSwitchMode: z.boolean().optional(),
enableToolNewTask: z.boolean().optional(),
enableToolCodebaseSearch: z.boolean().optional(),
enableToolUpdateTodoList: z.boolean().optional(),

mode: z.string().optional(),
modeApiConfigs: z.record(z.string(), z.string()).optional(),
customModes: z.array(modeConfigSchema).optional(),
Expand Down Expand Up @@ -240,6 +261,27 @@ export const EVALS_SETTINGS: RooCodeSettings = {

mcpEnabled: false,

// Individual tool controls - default to enabled for backward compatibility
enableToolExecuteCommand: true,
enableToolReadFile: true,
enableToolFetchInstructions: true,
enableToolWriteToFile: true,
enableToolApplyDiff: true,
enableToolInsertContent: true,
enableToolSearchAndReplace: true,
enableToolSearchFiles: true,
enableToolListFiles: true,
enableToolListCodeDefinitionNames: true,
enableToolBrowserAction: true,
enableToolUseMcpTool: true,
enableToolAccessMcpResource: true,
enableToolAskFollowupQuestion: true,
enableToolAttemptCompletion: true,
enableToolSwitchMode: true,
enableToolNewTask: true,
enableToolCodebaseSearch: true,
enableToolUpdateTodoList: true,

mode: "code",

customModes: [],
Expand Down
20 changes: 12 additions & 8 deletions src/core/prompts/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,20 @@ import {
markdownFormattingSection,
} from "./sections"

// Helper function to get prompt component, filtering out empty objects
export function getPromptComponent(
customModePrompts: CustomModePrompts | undefined,
mode: string,
): PromptComponent | undefined {
const component = customModePrompts?.[mode]
// Return undefined if component is empty
if (isEmpty(component)) {
/**
* Extracts a prompt component from customModePrompts for a given mode.
* Returns undefined if the mode doesn't exist or has no properties.
*/
export function getPromptComponent(customModePrompts?: CustomModePrompts, mode?: string): PromptComponent | undefined {
if (!customModePrompts || !mode) {
return undefined
}

const component = customModePrompts[mode]
if (!component || isEmpty(component)) {
return undefined
}

return component
}

Expand Down
19 changes: 19 additions & 0 deletions src/core/prompts/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,25 @@ export function getToolDescriptionsForMode(
tools.delete("codebase_search")
}

// Filter tools based on individual tool settings
if (settings) {
const toolsToRemove: string[] = []
tools.forEach((toolName) => {
// Convert tool_name to enableToolToolName format
const camelCase = toolName.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
const pascalCase = camelCase.charAt(0).toUpperCase() + camelCase.slice(1)
const settingKey = `enableTool${pascalCase}`

// If the setting exists and is false, mark tool for removal
if (settings[settingKey] === false) {
toolsToRemove.push(toolName)
}
})

// Remove disabled tools
toolsToRemove.forEach((toolName) => tools.delete(toolName))
}

// Map tool descriptions for allowed tools
const descriptions = Array.from(tools).map((toolName) => {
const descriptionFn = toolDescriptionMap[toolName]
Expand Down
40 changes: 40 additions & 0 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,26 @@ export class Task extends EventEmitter<ClineEvents> {
language,
maxConcurrentFileReads,
maxReadFileLine,
// Tool settings
enableToolExecuteCommand,
enableToolReadFile,
enableToolFetchInstructions,
enableToolWriteToFile,
enableToolApplyDiff,
enableToolInsertContent,
enableToolSearchAndReplace,
enableToolSearchFiles,
enableToolListFiles,
enableToolListCodeDefinitionNames,
enableToolBrowserAction,
enableToolUseMcpTool,
enableToolAccessMcpResource,
enableToolAskFollowupQuestion,
enableToolAttemptCompletion,
enableToolSwitchMode,
enableToolNewTask,
enableToolCodebaseSearch,
enableToolUpdateTodoList,
} = state ?? {}

return await (async () => {
Expand Down Expand Up @@ -1650,6 +1670,26 @@ export class Task extends EventEmitter<ClineEvents> {
maxReadFileLine !== -1,
{
maxConcurrentFileReads,
// Tool settings
enableToolExecuteCommand,
enableToolReadFile,
enableToolFetchInstructions,
enableToolWriteToFile,
enableToolApplyDiff,
enableToolInsertContent,
enableToolSearchAndReplace,
enableToolSearchFiles,
enableToolListFiles,
enableToolListCodeDefinitionNames,
enableToolBrowserAction,
enableToolUseMcpTool,
enableToolAccessMcpResource,
enableToolAskFollowupQuestion,
enableToolAttemptCompletion,
enableToolSwitchMode,
enableToolNewTask,
enableToolCodebaseSearch,
enableToolUpdateTodoList,
},
)
})()
Expand Down
60 changes: 60 additions & 0 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,26 @@ export class ClineProvider
profileThresholds,
alwaysAllowFollowupQuestions,
followupAutoApproveTimeoutMs,
// Tool settings
enableToolExecuteCommand,
enableToolReadFile,
enableToolFetchInstructions,
enableToolWriteToFile,
enableToolApplyDiff,
enableToolInsertContent,
enableToolSearchAndReplace,
enableToolSearchFiles,
enableToolListFiles,
enableToolListCodeDefinitionNames,
enableToolBrowserAction,
enableToolUseMcpTool,
enableToolAccessMcpResource,
enableToolAskFollowupQuestion,
enableToolAttemptCompletion,
enableToolSwitchMode,
enableToolNewTask,
enableToolCodebaseSearch,
enableToolUpdateTodoList,
} = await this.getState()

const telemetryKey = process.env.POSTHOG_API_KEY
Expand Down Expand Up @@ -1555,6 +1575,26 @@ export class ClineProvider
hasOpenedModeSelector: this.getGlobalState("hasOpenedModeSelector") ?? false,
alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false,
followupAutoApproveTimeoutMs: followupAutoApproveTimeoutMs ?? 60000,
// Tool settings
enableToolExecuteCommand: enableToolExecuteCommand ?? true,
enableToolReadFile: enableToolReadFile ?? true,
enableToolFetchInstructions: enableToolFetchInstructions ?? true,
enableToolWriteToFile: enableToolWriteToFile ?? true,
enableToolApplyDiff: enableToolApplyDiff ?? true,
enableToolInsertContent: enableToolInsertContent ?? true,
enableToolSearchAndReplace: enableToolSearchAndReplace ?? true,
enableToolSearchFiles: enableToolSearchFiles ?? true,
enableToolListFiles: enableToolListFiles ?? true,
enableToolListCodeDefinitionNames: enableToolListCodeDefinitionNames ?? true,
enableToolBrowserAction: enableToolBrowserAction ?? true,
enableToolUseMcpTool: enableToolUseMcpTool ?? true,
enableToolAccessMcpResource: enableToolAccessMcpResource ?? true,
enableToolAskFollowupQuestion: enableToolAskFollowupQuestion ?? true,
enableToolAttemptCompletion: enableToolAttemptCompletion ?? true,
enableToolSwitchMode: enableToolSwitchMode ?? true,
enableToolNewTask: enableToolNewTask ?? true,
enableToolCodebaseSearch: enableToolCodebaseSearch ?? true,
enableToolUpdateTodoList: enableToolUpdateTodoList ?? true,
}
}

Expand Down Expand Up @@ -1717,6 +1757,26 @@ export class ClineProvider
codebaseIndexSearchMinScore: stateValues.codebaseIndexConfig?.codebaseIndexSearchMinScore,
},
profileThresholds: stateValues.profileThresholds ?? {},
// Tool settings
enableToolExecuteCommand: stateValues.enableToolExecuteCommand ?? true,
enableToolReadFile: stateValues.enableToolReadFile ?? true,
enableToolFetchInstructions: stateValues.enableToolFetchInstructions ?? true,
enableToolWriteToFile: stateValues.enableToolWriteToFile ?? true,
enableToolApplyDiff: stateValues.enableToolApplyDiff ?? true,
enableToolInsertContent: stateValues.enableToolInsertContent ?? true,
enableToolSearchAndReplace: stateValues.enableToolSearchAndReplace ?? true,
enableToolSearchFiles: stateValues.enableToolSearchFiles ?? true,
enableToolListFiles: stateValues.enableToolListFiles ?? true,
enableToolListCodeDefinitionNames: stateValues.enableToolListCodeDefinitionNames ?? true,
enableToolBrowserAction: stateValues.enableToolBrowserAction ?? true,
enableToolUseMcpTool: stateValues.enableToolUseMcpTool ?? true,
enableToolAccessMcpResource: stateValues.enableToolAccessMcpResource ?? true,
enableToolAskFollowupQuestion: stateValues.enableToolAskFollowupQuestion ?? true,
enableToolAttemptCompletion: stateValues.enableToolAttemptCompletion ?? true,
enableToolSwitchMode: stateValues.enableToolSwitchMode ?? true,
enableToolNewTask: stateValues.enableToolNewTask ?? true,
enableToolCodebaseSearch: stateValues.enableToolCodebaseSearch ?? true,
enableToolUpdateTodoList: stateValues.enableToolUpdateTodoList ?? true,
}
}

Expand Down
40 changes: 40 additions & 0 deletions src/core/webview/generateSystemPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,26 @@ export const generateSystemPrompt = async (provider: ClineProvider, message: Web
language,
maxReadFileLine,
maxConcurrentFileReads,
// Tool settings
enableToolExecuteCommand,
enableToolReadFile,
enableToolFetchInstructions,
enableToolWriteToFile,
enableToolApplyDiff,
enableToolInsertContent,
enableToolSearchAndReplace,
enableToolSearchFiles,
enableToolListFiles,
enableToolListCodeDefinitionNames,
enableToolBrowserAction,
enableToolUseMcpTool,
enableToolAccessMcpResource,
enableToolAskFollowupQuestion,
enableToolAttemptCompletion,
enableToolSwitchMode,
enableToolNewTask,
enableToolCodebaseSearch,
enableToolUpdateTodoList,
} = await provider.getState()

// Check experiment to determine which diff strategy to use
Expand Down Expand Up @@ -82,6 +102,26 @@ export const generateSystemPrompt = async (provider: ClineProvider, message: Web
maxReadFileLine !== -1,
{
maxConcurrentFileReads,
// Tool settings
enableToolExecuteCommand,
enableToolReadFile,
enableToolFetchInstructions,
enableToolWriteToFile,
enableToolApplyDiff,
enableToolInsertContent,
enableToolSearchAndReplace,
enableToolSearchFiles,
enableToolListFiles,
enableToolListCodeDefinitionNames,
enableToolBrowserAction,
enableToolUseMcpTool,
enableToolAccessMcpResource,
enableToolAskFollowupQuestion,
enableToolAttemptCompletion,
enableToolSwitchMode,
enableToolNewTask,
enableToolCodebaseSearch,
enableToolUpdateTodoList,
},
)

Expand Down
76 changes: 76 additions & 0 deletions src/core/webview/webviewMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,82 @@ export const webviewMessageHandler = async (
await updateGlobalState("browserToolEnabled", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolExecuteCommand":
await updateGlobalState("enableToolExecuteCommand", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolReadFile":
await updateGlobalState("enableToolReadFile", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolFetchInstructions":
await updateGlobalState("enableToolFetchInstructions", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolWriteToFile":
await updateGlobalState("enableToolWriteToFile", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolApplyDiff":
await updateGlobalState("enableToolApplyDiff", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolInsertContent":
await updateGlobalState("enableToolInsertContent", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolSearchAndReplace":
await updateGlobalState("enableToolSearchAndReplace", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolSearchFiles":
await updateGlobalState("enableToolSearchFiles", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolListFiles":
await updateGlobalState("enableToolListFiles", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolListCodeDefinitionNames":
await updateGlobalState("enableToolListCodeDefinitionNames", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolBrowserAction":
await updateGlobalState("enableToolBrowserAction", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolUseMcpTool":
await updateGlobalState("enableToolUseMcpTool", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolAccessMcpResource":
await updateGlobalState("enableToolAccessMcpResource", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolAskFollowupQuestion":
await updateGlobalState("enableToolAskFollowupQuestion", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolAttemptCompletion":
await updateGlobalState("enableToolAttemptCompletion", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolSwitchMode":
await updateGlobalState("enableToolSwitchMode", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolNewTask":
await updateGlobalState("enableToolNewTask", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolCodebaseSearch":
await updateGlobalState("enableToolCodebaseSearch", message.bool ?? true)
await provider.postStateToWebview()
break
case "enableToolUpdateTodoList":
await updateGlobalState("enableToolUpdateTodoList", message.bool ?? true)
await provider.postStateToWebview()
break
case "language":
changeLanguage(message.text ?? "en")
await updateGlobalState("language", message.text as Language)
Expand Down
Loading