Matt Rubens 10 месяцев назад
Родитель
Сommit
df46f60117
3 измененных файлов с 72 добавлено и 4 удалено
  1. 24 4
      src/core/Cline.ts
  2. 7 0
      src/shared/experiments.ts
  3. 41 0
      src/shared/modes.ts

+ 24 - 4
src/core/Cline.ts

@@ -54,7 +54,7 @@ import { parseMentions } from "./mentions"
 import { AssistantMessageContent, parseAssistantMessage, ToolParamName, ToolUseName } from "./assistant-message"
 import { AssistantMessageContent, parseAssistantMessage, ToolParamName, ToolUseName } from "./assistant-message"
 import { formatResponse } from "./prompts/responses"
 import { formatResponse } from "./prompts/responses"
 import { SYSTEM_PROMPT } from "./prompts/system"
 import { SYSTEM_PROMPT } from "./prompts/system"
-import { modes, defaultModeSlug, getModeBySlug } from "../shared/modes"
+import { modes, defaultModeSlug, getModeBySlug, getFullModeDetails } from "../shared/modes"
 import { truncateConversationIfNeeded } from "./sliding-window"
 import { truncateConversationIfNeeded } from "./sliding-window"
 import { ClineProvider, GlobalFileNames } from "./webview/ClineProvider"
 import { ClineProvider, GlobalFileNames } from "./webview/ClineProvider"
 import { detectCodeOmission } from "../integrations/editor/detect-omission"
 import { detectCodeOmission } from "../integrations/editor/detect-omission"
@@ -63,7 +63,7 @@ import { OpenRouterHandler } from "../api/providers/openrouter"
 import { McpHub } from "../services/mcp/McpHub"
 import { McpHub } from "../services/mcp/McpHub"
 import crypto from "crypto"
 import crypto from "crypto"
 import { insertGroups } from "./diff/insert-groups"
 import { insertGroups } from "./diff/insert-groups"
-import { EXPERIMENT_IDS, experiments as Experiments } from "../shared/experiments"
+import { EXPERIMENT_IDS, experiments as Experiments, ExperimentId } from "../shared/experiments"
 
 
 const cwd =
 const cwd =
 	vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) ?? path.join(os.homedir(), "Desktop") // may or may not exist but fs checking existence would immediately ask for permission which would be bad UX, need to come up with a better solution
 	vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) ?? path.join(os.homedir(), "Desktop") // may or may not exist but fs checking existence would immediately ask for permission which would be bad UX, need to come up with a better solution
@@ -3235,9 +3235,29 @@ export class Cline {
 		details += `\n\n# Current Context Size (Tokens)\n${contextTokens ? `${contextTokens.toLocaleString()} (${contextPercentage}%)` : "(Not available)"}`
 		details += `\n\n# Current Context Size (Tokens)\n${contextTokens ? `${contextTokens.toLocaleString()} (${contextPercentage}%)` : "(Not available)"}`
 
 
 		// Add current mode and any mode-specific warnings
 		// Add current mode and any mode-specific warnings
-		const { mode, customModes } = (await this.providerRef.deref()?.getState()) ?? {}
+		const {
+			mode,
+			customModes,
+			customModePrompts,
+			experiments = {} as Record<ExperimentId, boolean>,
+			customInstructions: globalCustomInstructions,
+			preferredLanguage,
+		} = (await this.providerRef.deref()?.getState()) ?? {}
 		const currentMode = mode ?? defaultModeSlug
 		const currentMode = mode ?? defaultModeSlug
-		details += `\n\n# Current Mode\n${currentMode}`
+		const modeDetails = await getFullModeDetails(currentMode, customModes, customModePrompts, {
+			cwd,
+			globalCustomInstructions,
+			preferredLanguage,
+		})
+		details += `\n\n# Current Mode\n`
+		details += `<slug>${currentMode}</slug>\n`
+		details += `<name>${modeDetails.name}</name>\n`
+		if (Experiments.isEnabled(experiments ?? {}, EXPERIMENT_IDS.POWER_STEERING)) {
+			details += `<role>${modeDetails.roleDefinition}</role>\n`
+			if (modeDetails.customInstructions) {
+				details += `<custom_instructions>${modeDetails.customInstructions}</custom_instructions>\n`
+			}
+		}
 
 
 		// Add warning if not in code mode
 		// Add warning if not in code mode
 		if (
 		if (

+ 7 - 0
src/shared/experiments.ts

@@ -2,6 +2,7 @@ export const EXPERIMENT_IDS = {
 	DIFF_STRATEGY: "experimentalDiffStrategy",
 	DIFF_STRATEGY: "experimentalDiffStrategy",
 	SEARCH_AND_REPLACE: "search_and_replace",
 	SEARCH_AND_REPLACE: "search_and_replace",
 	INSERT_BLOCK: "insert_content",
 	INSERT_BLOCK: "insert_content",
+	POWER_STEERING: "powerSteering",
 } as const
 } as const
 
 
 export type ExperimentKey = keyof typeof EXPERIMENT_IDS
 export type ExperimentKey = keyof typeof EXPERIMENT_IDS
@@ -35,6 +36,12 @@ export const experimentConfigsMap: Record<ExperimentKey, ExperimentConfig> = {
 			"Enable the experimental insert content tool, allowing Roo to insert content at specific line numbers without needing to create a diff.",
 			"Enable the experimental insert content tool, allowing Roo to insert content at specific line numbers without needing to create a diff.",
 		enabled: false,
 		enabled: false,
 	},
 	},
+	POWER_STEERING: {
+		name: 'Use experimental "power steering" mode',
+		description:
+			"When enabled, Roo will remind the model about the details of its current mode definition more frequently. This will lead to stronger adherence to role definitions and custom instructions, but will use additional tokens.",
+		enabled: false,
+	},
 }
 }
 
 
 export const experimentDefault = Object.fromEntries(
 export const experimentDefault = Object.fromEntries(

+ 41 - 0
src/shared/modes.ts

@@ -1,5 +1,6 @@
 import * as vscode from "vscode"
 import * as vscode from "vscode"
 import { TOOL_GROUPS, ToolGroup, ALWAYS_AVAILABLE_TOOLS } from "./tool-groups"
 import { TOOL_GROUPS, ToolGroup, ALWAYS_AVAILABLE_TOOLS } from "./tool-groups"
+import { addCustomInstructions } from "../core/prompts/sections/custom-instructions"
 
 
 // Mode types
 // Mode types
 export type Mode = string
 export type Mode = string
@@ -262,6 +263,46 @@ export async function getAllModesWithPrompts(context: vscode.ExtensionContext):
 	}))
 	}))
 }
 }
 
 
+// Helper function to get complete mode details with all overrides
+export async function getFullModeDetails(
+	modeSlug: string,
+	customModes?: ModeConfig[],
+	customModePrompts?: CustomModePrompts,
+	options?: {
+		cwd?: string
+		globalCustomInstructions?: string
+		preferredLanguage?: string
+	},
+): Promise<ModeConfig> {
+	// First get the base mode config from custom modes or built-in modes
+	const baseMode = getModeBySlug(modeSlug, customModes) || modes.find((m) => m.slug === modeSlug) || modes[0]
+
+	// Check for any prompt component overrides
+	const promptComponent = customModePrompts?.[modeSlug]
+
+	// Get the base custom instructions
+	const baseCustomInstructions = promptComponent?.customInstructions || baseMode.customInstructions || ""
+
+	// If we have cwd, load and combine all custom instructions
+	let fullCustomInstructions = baseCustomInstructions
+	if (options?.cwd) {
+		fullCustomInstructions = await addCustomInstructions(
+			baseCustomInstructions,
+			options.globalCustomInstructions || "",
+			options.cwd,
+			modeSlug,
+			{ preferredLanguage: options.preferredLanguage },
+		)
+	}
+
+	// Return mode with any overrides applied
+	return {
+		...baseMode,
+		roleDefinition: promptComponent?.roleDefinition || baseMode.roleDefinition,
+		customInstructions: fullCustomInstructions,
+	}
+}
+
 // Helper function to safely get role definition
 // Helper function to safely get role definition
 export function getRoleDefinition(modeSlug: string, customModes?: ModeConfig[]): string {
 export function getRoleDefinition(modeSlug: string, customModes?: ModeConfig[]): string {
 	const mode = getModeBySlug(modeSlug, customModes)
 	const mode = getModeBySlug(modeSlug, customModes)