diff --git a/src/core/prompts/sections/capabilities.ts b/src/core/prompts/sections/capabilities.ts index 55c7c1f5c3..e718da0bfd 100644 --- a/src/core/prompts/sections/capabilities.ts +++ b/src/core/prompts/sections/capabilities.ts @@ -16,6 +16,18 @@ export function getCapabilitiesSection( codeIndexManager?: CodeIndexManager, settings?: SystemPromptSettings, ): string { + // Return simplified capabilities for lite mode + if (settings?.liteMode) { + return `==== + +CAPABILITIES + +- CLI commands, file operations (list/read/write), search, definitions +- Project structure in environment_details +- Each command runs in new terminal +${mcpHub ? "- MCP servers provide additional tools\n" : ""}` + } + // Get available tools from relevant groups const availableEditTools = getAvailableToolsInGroup( "edit", diff --git a/src/core/prompts/sections/rules.ts b/src/core/prompts/sections/rules.ts index 9e98773ed2..d22dc77db9 100644 --- a/src/core/prompts/sections/rules.ts +++ b/src/core/prompts/sections/rules.ts @@ -86,6 +86,20 @@ export function getRulesSection( codeIndexManager?: CodeIndexManager, settings?: SystemPromptSettings, ): string { + // Return simplified rules for lite mode + if (settings?.liteMode) { + return `==== + +RULES + +- Base directory: ${cwd.toPosix()} +- Use relative paths from base directory +- Read files before editing +- Wait for user confirmation after each tool use +- Use attempt_completion to present final results +- Be direct and technical, not conversational` + } + const isCodebaseSearchAvailable = codeIndexManager && codeIndexManager.isFeatureEnabled && @@ -132,6 +146,7 @@ export function getRulesSection( // Determine whether to use XML tool references based on protocol const effectiveProtocol = getEffectiveProtocol(settings?.toolProtocol) + // Full rules for regular mode return `==== RULES diff --git a/src/core/prompts/tools/index.ts b/src/core/prompts/tools/index.ts index f00666f38c..f2daf59182 100644 --- a/src/core/prompts/tools/index.ts +++ b/src/core/prompts/tools/index.ts @@ -28,10 +28,38 @@ import { getRunSlashCommandDescription } from "./run-slash-command" import { getGenerateImageDescription } from "./generate-image" import { CodeIndexManager } from "../../../services/code-index/manager" +// Import lite descriptions +import { + getLiteReadFileDescription, + getLiteWriteToFileDescription, + getLiteSearchFilesDescription, + getLiteListFilesDescription, + getLiteExecuteCommandDescription, + getLiteInsertContentDescription, + getLiteListCodeDefinitionNamesDescription, + getLiteAskFollowupQuestionDescription, + getLiteAttemptCompletionDescription, + getLiteBrowserActionDescription, + getLiteSwitchModeDescription, + getLiteNewTaskDescription, + getLiteUpdateTodoListDescription, + getLiteFetchInstructionsDescription, + getLiteApplyDiffDescription, + getLiteCodebaseSearchDescription, + getLiteUseMcpToolDescription, + getLiteAccessMcpResourceDescription, + getLiteGenerateImageDescription, + getLiteRunSlashCommandDescription, +} from "./lite-descriptions" + // Map of tool names to their description functions const toolDescriptionMap: Record string | undefined> = { - execute_command: (args) => getExecuteCommandDescription(args), + execute_command: (args) => { + if (args.settings?.liteMode) return getLiteExecuteCommandDescription() + return getExecuteCommandDescription(args) + }, read_file: (args) => { + if (args.settings?.liteMode) return getLiteReadFileDescription(args) // Check if the current model should use the simplified read_file tool const modelId = args.settings?.modelId if (modelId && shouldUseSingleFileRead(modelId)) { @@ -39,25 +67,80 @@ const toolDescriptionMap: Record string | undefined> } return getReadFileDescription(args) }, - fetch_instructions: (args) => getFetchInstructionsDescription(args.settings?.enableMcpServerCreation), - write_to_file: (args) => getWriteToFileDescription(args), - search_files: (args) => getSearchFilesDescription(args), - list_files: (args) => getListFilesDescription(args), - list_code_definition_names: (args) => getListCodeDefinitionNamesDescription(args), - browser_action: (args) => getBrowserActionDescription(args), - ask_followup_question: () => getAskFollowupQuestionDescription(), - attempt_completion: (args) => getAttemptCompletionDescription(args), - use_mcp_tool: (args) => getUseMcpToolDescription(args), - access_mcp_resource: (args) => getAccessMcpResourceDescription(args), - codebase_search: (args) => getCodebaseSearchDescription(args), - switch_mode: () => getSwitchModeDescription(), - new_task: (args) => getNewTaskDescription(args), - insert_content: (args) => getInsertContentDescription(args), - apply_diff: (args) => - args.diffStrategy ? args.diffStrategy.getToolDescription({ cwd: args.cwd, toolOptions: args.toolOptions }) : "", - update_todo_list: (args) => getUpdateTodoListDescription(args), - run_slash_command: () => getRunSlashCommandDescription(), - generate_image: (args) => getGenerateImageDescription(args), + fetch_instructions: (args) => { + if (args.settings?.liteMode) return getLiteFetchInstructionsDescription() + return getFetchInstructionsDescription(args.settings?.enableMcpServerCreation) + }, + write_to_file: (args) => { + if (args.settings?.liteMode) return getLiteWriteToFileDescription() + return getWriteToFileDescription(args) + }, + search_files: (args) => { + if (args.settings?.liteMode) return getLiteSearchFilesDescription() + return getSearchFilesDescription(args) + }, + list_files: (args) => { + if (args.settings?.liteMode) return getLiteListFilesDescription() + return getListFilesDescription(args) + }, + list_code_definition_names: (args) => { + if (args.settings?.liteMode) return getLiteListCodeDefinitionNamesDescription() + return getListCodeDefinitionNamesDescription(args) + }, + browser_action: (args) => { + if (args.settings?.liteMode) return getLiteBrowserActionDescription() + return getBrowserActionDescription(args) + }, + ask_followup_question: (args) => { + if (args.settings?.liteMode) return getLiteAskFollowupQuestionDescription() + return getAskFollowupQuestionDescription() + }, + attempt_completion: (args) => { + if (args.settings?.liteMode) return getLiteAttemptCompletionDescription() + return getAttemptCompletionDescription(args) + }, + use_mcp_tool: (args) => { + if (args.settings?.liteMode) return getLiteUseMcpToolDescription() + return getUseMcpToolDescription(args) + }, + access_mcp_resource: (args) => { + if (args.settings?.liteMode) return getLiteAccessMcpResourceDescription() + return getAccessMcpResourceDescription(args) + }, + codebase_search: (args) => { + if (args.settings?.liteMode) return getLiteCodebaseSearchDescription() + return getCodebaseSearchDescription(args) + }, + switch_mode: (args) => { + if (args.settings?.liteMode) return getLiteSwitchModeDescription() + return getSwitchModeDescription() + }, + new_task: (args) => { + if (args.settings?.liteMode) return getLiteNewTaskDescription() + return getNewTaskDescription(args) + }, + insert_content: (args) => { + if (args.settings?.liteMode) return getLiteInsertContentDescription() + return getInsertContentDescription(args) + }, + apply_diff: (args) => { + if (args.settings?.liteMode) return getLiteApplyDiffDescription(args.diffStrategy) + return args.diffStrategy + ? args.diffStrategy.getToolDescription({ cwd: args.cwd, toolOptions: args.toolOptions }) + : "" + }, + update_todo_list: (args) => { + if (args.settings?.liteMode) return getLiteUpdateTodoListDescription() + return getUpdateTodoListDescription(args) + }, + run_slash_command: (args) => { + if (args.settings?.liteMode) return getLiteRunSlashCommandDescription() + return getRunSlashCommandDescription() + }, + generate_image: (args) => { + if (args.settings?.liteMode) return getLiteGenerateImageDescription() + return getGenerateImageDescription(args) + }, } export function getToolDescriptionsForMode( diff --git a/src/core/prompts/tools/lite-descriptions.ts b/src/core/prompts/tools/lite-descriptions.ts new file mode 100644 index 0000000000..f39992ac92 --- /dev/null +++ b/src/core/prompts/tools/lite-descriptions.ts @@ -0,0 +1,127 @@ +import { ToolArgs } from "./types" +import { DiffStrategy } from "../../../shared/tools" + +/** + * Returns a compact tool description without examples for lite mode + */ +export function getLiteReadFileDescription(args: ToolArgs): string { + const maxReads = args.settings?.maxConcurrentFileReads ?? 5 + return `## read_file +Read file contents (max ${maxReads} files/request). Line-numbered output. +Params: path (required), line_range (optional)` +} + +export function getLiteWriteToFileDescription(): string { + return `## write_to_file +Create/overwrite file with content. +Params: path, content, line_count (required)` +} + +export function getLiteSearchFilesDescription(): string { + return `## search_files +Regex search in directory. +Params: path, regex (required), file_pattern (optional)` +} + +export function getLiteListFilesDescription(): string { + return `## list_files +List directory contents. +Params: path (required), recursive (optional)` +} + +export function getLiteExecuteCommandDescription(): string { + return `## execute_command +Execute CLI command. +Params: command (required), cwd (optional)` +} + +export function getLiteInsertContentDescription(): string { + return `## insert_content +Insert lines at specific position. +Params: path, line, content (required)` +} + +export function getLiteListCodeDefinitionNamesDescription(): string { + return `## list_code_definition_names +List code definitions (classes, functions, etc). +Params: path (required)` +} + +export function getLiteAskFollowupQuestionDescription(): string { + return `## ask_followup_question +Ask user for clarification. +Params: question, follow_up with 2-4 suggest tags` +} + +export function getLiteAttemptCompletionDescription(): string { + return `## attempt_completion +Present final result after task completion. +Params: result (required)` +} + +export function getLiteBrowserActionDescription(): string { + return `## browser_action +Browser interaction: screenshot, click, type, scroll. +Params: action (required), coordinate/text/direction/amount based on action` +} + +export function getLiteSwitchModeDescription(): string { + return `## switch_mode +Switch to different mode. +Params: mode_slug (required), reason (optional)` +} + +export function getLiteNewTaskDescription(): string { + return `## new_task +Create new task in specified mode. +Params: mode, message (required)` +} + +export function getLiteUpdateTodoListDescription(): string { + return `## update_todo_list +Update TODO checklist. +Format: [ ] pending, [x] completed, [-] in progress` +} + +export function getLiteFetchInstructionsDescription(): string { + return `## fetch_instructions +Get task instructions. +Params: task (required) - create_mcp_server or create_mode` +} + +export function getLiteApplyDiffDescription(diffStrategy?: DiffStrategy): string { + if (!diffStrategy) return "" + return `## apply_diff +Apply targeted edits to existing file. +Params: path, diff (SEARCH/REPLACE blocks with :start_line:)` +} + +export function getLiteCodebaseSearchDescription(): string { + return `## codebase_search +Semantic search for relevant code. +Params: query (required)` +} + +export function getLiteUseMcpToolDescription(): string { + return `## use_mcp_tool +Use MCP server tool. +Params: server_name, tool_name, arguments (required)` +} + +export function getLiteAccessMcpResourceDescription(): string { + return `## access_mcp_resource +Access MCP server resource. +Params: server_name, uri (required), arguments (optional)` +} + +export function getLiteGenerateImageDescription(): string { + return `## generate_image +Generate image using AI. +Params: prompt (required), size (optional)` +} + +export function getLiteRunSlashCommandDescription(): string { + return `## run_slash_command +Run a VS Code slash command. +Params: command, args (required)` +} diff --git a/src/core/prompts/types.ts b/src/core/prompts/types.ts index 7aea853410..0289af3c9b 100644 --- a/src/core/prompts/types.ts +++ b/src/core/prompts/types.ts @@ -10,4 +10,5 @@ export interface SystemPromptSettings { useAgentRules: boolean newTaskRequireTodos: boolean toolProtocol?: ToolProtocol + liteMode?: boolean } diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 5b575c1bb7..5ba0285c46 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -349,6 +349,7 @@ export type ExtensionState = Pick< remoteControlEnabled: boolean taskSyncEnabled: boolean featureRoomoteControlEnabled: boolean + liteMode?: boolean } export interface ClineSayTool { diff --git a/webview-ui/src/components/settings/ContextManagementSettings.tsx b/webview-ui/src/components/settings/ContextManagementSettings.tsx index fb2ca08b1b..3685ff5d7a 100644 --- a/webview-ui/src/components/settings/ContextManagementSettings.tsx +++ b/webview-ui/src/components/settings/ContextManagementSettings.tsx @@ -30,6 +30,7 @@ type ContextManagementSettingsProps = HTMLAttributes & { includeCurrentTime?: boolean includeCurrentCost?: boolean maxGitStatusFiles?: number + liteMode?: boolean setCachedStateField: SetCachedStateField< | "autoCondenseContext" | "autoCondenseContextPercent" @@ -47,6 +48,7 @@ type ContextManagementSettingsProps = HTMLAttributes & { | "includeCurrentTime" | "includeCurrentCost" | "maxGitStatusFiles" + | "liteMode" > } @@ -69,6 +71,7 @@ export const ContextManagementSettings = ({ includeCurrentTime, includeCurrentCost, maxGitStatusFiles, + liteMode, className, ...props }: ContextManagementSettingsProps) => { @@ -411,6 +414,20 @@ export const ContextManagementSettings = ({ {t("settings:contextManagement.includeCurrentCost.description")} + +
+ setCachedStateField("liteMode", e.target.checked)} + data-testid="lite-mode-checkbox"> + + +
+ {t("settings:contextManagement.liteMode.description")} +
+
(({ onDone, t includeCurrentTime, includeCurrentCost, maxGitStatusFiles, + liteMode, } = cachedState const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration]) @@ -767,6 +768,7 @@ const SettingsView = forwardRef(({ onDone, t includeCurrentTime={includeCurrentTime} includeCurrentCost={includeCurrentCost} maxGitStatusFiles={maxGitStatusFiles} + liteMode={liteMode} setCachedStateField={setCachedStateField} /> )} diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 6443ccad93..0d2d75ad10 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -165,6 +165,8 @@ export interface ExtensionStateContextType extends ExtensionState { setIncludeCurrentTime: (value: boolean) => void includeCurrentCost?: boolean setIncludeCurrentCost: (value: boolean) => void + liteMode?: boolean + setLiteMode: (value: boolean) => void } export const ExtensionStateContext = createContext(undefined) @@ -596,6 +598,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setIncludeCurrentTime, includeCurrentCost, setIncludeCurrentCost, + liteMode: state.liteMode, + setLiteMode: (value) => setState((prevState) => ({ ...prevState, liteMode: value })), } return {children}