diff --git a/src/core/prompts/sections/modes.ts b/src/core/prompts/sections/modes.ts index f3863870db..d561e47a84 100644 --- a/src/core/prompts/sections/modes.ts +++ b/src/core/prompts/sections/modes.ts @@ -11,12 +11,21 @@ export async function getModesSection(context: vscode.ExtensionContext): Promise // Get all modes with their overrides from extension state const allModes = await getAllModesWithPrompts(context) - return `==== + // Get enableCustomModeCreation setting from extension state + const enableCustomModeCreation = await context.globalState.get("enableCustomModeCreation") + // Default to true if undefined + const shouldEnableCustomModeCreation = enableCustomModeCreation !== undefined ? enableCustomModeCreation : true + + let modesContent = `==== MODES - These are the currently available modes: -${allModes.map((mode: ModeConfig) => ` * "${mode.name}" mode (${mode.slug}) - ${mode.roleDefinition.split(".")[0]}`).join("\n")} +${allModes.map((mode: ModeConfig) => ` * "${mode.name}" mode (${mode.slug}) - ${mode.roleDefinition.split(".")[0]}`).join("\n")}` + + // Only include custom modes documentation if the feature is enabled + if (shouldEnableCustomModeCreation) { + modesContent += ` - Custom modes can be configured in two ways: 1. Globally via '${customModesPath}' (created automatically on startup) @@ -56,4 +65,7 @@ Both files should follow this structure: } ] }` + } + + return modesContent } diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index e1d67b5a28..75689e2450 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1476,6 +1476,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("enhancementApiConfigId", message.text) await this.postStateToWebview() break + case "enableCustomModeCreation": + await this.updateGlobalState("enableCustomModeCreation", message.bool ?? true) + await this.postStateToWebview() + break case "autoApprovalEnabled": await this.updateGlobalState("autoApprovalEnabled", message.bool ?? false) await this.postStateToWebview() diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 98ff9b36e1..78c60acc97 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -128,6 +128,7 @@ export interface ExtensionState { terminalOutputLimit?: number mcpEnabled: boolean enableMcpServerCreation: boolean + enableCustomModeCreation?: boolean mode: Mode modeApiConfigs?: Record enhancementApiConfigId?: string diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 10af6f7a94..37328cd95a 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -71,6 +71,7 @@ export interface WebviewMessage { | "terminalOutputLimit" | "mcpEnabled" | "enableMcpServerCreation" + | "enableCustomModeCreation" | "searchCommits" | "alwaysApproveResubmit" | "requestDelaySeconds" diff --git a/src/shared/globalState.ts b/src/shared/globalState.ts index bfd24f4298..579bf1df86 100644 --- a/src/shared/globalState.ts +++ b/src/shared/globalState.ts @@ -84,6 +84,7 @@ export const GLOBAL_STATE_KEYS = [ "enhancementApiConfigId", "experiments", // Map of experiment IDs to their enabled state "autoApprovalEnabled", + "enableCustomModeCreation", // Enable the ability to create custom modes "customModes", // Array of custom modes "unboundModelId", "requestyModelId", diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx index ccf1e6d700..e14ce8f939 100644 --- a/webview-ui/src/components/prompts/PromptsView.tsx +++ b/webview-ui/src/components/prompts/PromptsView.tsx @@ -71,6 +71,8 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { preferredLanguage, setPreferredLanguage, customModes, + enableCustomModeCreation, + setEnableCustomModeCreation, } = useExtensionState() // Memoize modes to preserve array order @@ -341,6 +343,17 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { return () => document.removeEventListener("click", handleClickOutside) }, [showConfigMenu]) + // Add effect to sync enableCustomModeCreation with backend + useEffect(() => { + if (enableCustomModeCreation !== undefined) { + // Send the value to the extension's global state + vscode.postMessage({ + type: "enableCustomModeCreation", // Using dedicated message type + bool: enableCustomModeCreation, + }) + } + }, [enableCustomModeCreation]) + useEffect(() => { const handler = (event: MessageEvent) => { const message = event.data @@ -541,8 +554,33 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { in your workspace. -
+ {/* + NOTE: This setting is placed in PromptsView rather than SettingsView since it + directly affects the functionality related to modes and custom mode creation, + which are managed in this component. This is an intentional deviation from + the standard pattern described in cline_docs/settings.md. + */} +
+ { + // Just update the local state through React context + // The React context will update the global state + setEnableCustomModeCreation(e.target.checked) + }}> + Enable Custom Mode Creation + +

+ When enabled, Roo can help you create project-level custom modes. You can disable this to + reduce Roo's token usage. +

+
e.stopPropagation()} className="flex justify-between items-center mb-3">

Modes

diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index c4daf426ca..3ed42b8586 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -52,6 +52,8 @@ export interface ExtensionStateContextType extends ExtensionState { setMcpEnabled: (value: boolean) => void enableMcpServerCreation: boolean setEnableMcpServerCreation: (value: boolean) => void + enableCustomModeCreation?: boolean + setEnableCustomModeCreation: (value: boolean) => void alwaysApproveResubmit?: boolean setAlwaysApproveResubmit: (value: boolean) => void requestDelaySeconds: number @@ -117,6 +119,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode checkpointStorage: "task", fuzzyMatchThreshold: 1.0, preferredLanguage: "English", + enableCustomModeCreation: true, writeDelayMs: 1000, browserViewportSize: "900x600", screenshotQuality: 75, @@ -273,6 +276,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setCustomSupportPrompts: (value) => setState((prevState) => ({ ...prevState, customSupportPrompts: value })), setEnhancementApiConfigId: (value) => setState((prevState) => ({ ...prevState, enhancementApiConfigId: value })), + setEnableCustomModeCreation: (value) => + setState((prevState) => ({ ...prevState, enableCustomModeCreation: value })), setAutoApprovalEnabled: (value) => setState((prevState) => ({ ...prevState, autoApprovalEnabled: value })), setCustomModes: (value) => setState((prevState) => ({ ...prevState, customModes: value })), setMaxOpenTabsContext: (value) => setState((prevState) => ({ ...prevState, maxOpenTabsContext: value })),