Skip to content

Commit ae9e734

Browse files
committed
Add a 'when to use' section to mode definitions
1 parent 836bbf7 commit ae9e734

File tree

26 files changed

+433
-152
lines changed

26 files changed

+433
-152
lines changed

.changeset/dark-swans-marry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"roo-cline": patch
3+
---
4+
5+
Add a 'when to use' section to mode definitions

src/core/prompts/instructions/create-mode.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ If asked to create a project mode, create it in .roomodes in the workspace root.
2525
* roleDefinition: A detailed description of the mode's role and capabilities
2626
* groups: Array of allowed tool groups (can be empty). Each group can be specified either as a string (e.g., "edit" to allow editing any file) or with file restrictions (e.g., ["edit", { fileRegex: "\\.md$", description: "Markdown files only" }] to only allow editing markdown files)
2727
28-
- The customInstructions field is optional.
28+
- The following fields are optional but highly recommended:
29+
* whenToUse: A clear description of when this mode should be selected and what types of tasks it's best suited for. This helps the Orchestrator mode make better decisions.
30+
* customInstructions: Additional instructions for how the mode should operate
2931
3032
- For multi-line text, include newline characters in the string like "This is the first line.\\nThis is the next line.\\n\\nThis is a double line break."
3133
@@ -36,6 +38,7 @@ Both files should follow this structure:
3638
"slug": "designer", // Required: unique slug with lowercase letters, numbers, and hyphens
3739
"name": "Designer", // Required: mode display name
3840
"roleDefinition": "You are Roo, a UI/UX expert specializing in design systems and frontend development. Your expertise includes:\\n- Creating and maintaining design systems\\n- Implementing responsive and accessible web interfaces\\n- Working with CSS, HTML, and modern frontend frameworks\\n- Ensuring consistent user experiences across platforms", // Required: non-empty
41+
"whenToUse": "Use this mode when creating or modifying UI components, implementing design systems, or ensuring responsive web interfaces. This mode is especially effective with CSS, HTML, and modern frontend frameworks.", // Optional but recommended
3942
"groups": [ // Required: array of tool groups (can be empty)
4043
"read", // Read files group (read_file, fetch_instructions, search_files, list_files, list_code_definition_names)
4144
"edit", // Edit files group (apply_diff, write_to_file) - allows editing any file

src/core/prompts/sections/modes.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,19 @@ export async function getModesSection(context: vscode.ExtensionContext): Promise
1616
MODES
1717
1818
- These are the currently available modes:
19-
${allModes.map((mode: ModeConfig) => ` * "${mode.name}" mode (${mode.slug}) - ${mode.roleDefinition.split(".")[0]}`).join("\n")}`
19+
${allModes
20+
.map((mode: ModeConfig) => {
21+
let description: string
22+
if (mode.whenToUse && mode.whenToUse.trim() !== "") {
23+
// Use whenToUse as the primary description, indenting subsequent lines for readability
24+
description = mode.whenToUse.replace(/\n/g, "\n ")
25+
} else {
26+
// Fallback to the first sentence of roleDefinition if whenToUse is not available
27+
description = mode.roleDefinition.split(".")[0]
28+
}
29+
return ` * "${mode.name}" mode (${mode.slug}) - ${description}`
30+
})
31+
.join("\n")}`
2032

2133
modesContent += `
2234
If the user asks you to create or edit a new mode for this project, you should read the instructions by using the fetch_instructions tool, like this:

src/exports/roo-code.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ type GlobalSettings = {
137137
slug: string
138138
name: string
139139
roleDefinition: string
140+
whenToUse?: string | undefined
140141
customInstructions?: string | undefined
141142
groups: (
142143
| ("read" | "edit" | "browser" | "command" | "mcp" | "modes")
@@ -156,6 +157,7 @@ type GlobalSettings = {
156157
[x: string]:
157158
| {
158159
roleDefinition?: string | undefined
160+
whenToUse?: string | undefined
159161
customInstructions?: string | undefined
160162
}
161163
| undefined

src/exports/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ type GlobalSettings = {
138138
slug: string
139139
name: string
140140
roleDefinition: string
141+
whenToUse?: string | undefined
141142
customInstructions?: string | undefined
142143
groups: (
143144
| ("read" | "edit" | "browser" | "command" | "mcp" | "modes")
@@ -157,6 +158,7 @@ type GlobalSettings = {
157158
[x: string]:
158159
| {
159160
roleDefinition?: string | undefined
161+
whenToUse?: string | undefined
160162
customInstructions?: string | undefined
161163
}
162164
| undefined

src/schemas/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ export const modeConfigSchema = z.object({
217217
slug: z.string().regex(/^[a-zA-Z0-9-]+$/, "Slug must contain only letters numbers and dashes"),
218218
name: z.string().min(1, "Name is required"),
219219
roleDefinition: z.string().min(1, "Role definition is required"),
220+
whenToUse: z.string().optional(),
220221
customInstructions: z.string().optional(),
221222
groups: groupEntryArraySchema,
222223
source: z.enum(["global", "project"]).optional(),
@@ -256,6 +257,7 @@ export type CustomModesSettings = z.infer<typeof customModesSettingsSchema>
256257

257258
export const promptComponentSchema = z.object({
258259
roleDefinition: z.string().optional(),
260+
whenToUse: z.string().optional(),
259261
customInstructions: z.string().optional(),
260262
})
261263

src/shared/modes.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,17 @@ export const modes: readonly ModeConfig[] = [
5757
name: "💻 Code",
5858
roleDefinition:
5959
"You are Roo, a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.",
60+
whenToUse:
61+
"Use this mode when implementing new features, debugging issues, refactoring code, or working with existing codebases. This mode has full access to read and write files, execute commands, and use browser tools.",
6062
groups: ["read", "edit", "browser", "command", "mcp"],
6163
},
6264
{
6365
slug: "architect",
6466
name: "🏗️ Architect",
6567
roleDefinition:
6668
"You are Roo, an experienced technical leader who is inquisitive and an excellent planner. Your goal is to gather information and get context to create a detailed plan for accomplishing the user's task, which the user will review and approve before they switch into another mode to implement the solution.",
69+
whenToUse:
70+
"Use this mode when planning projects, designing system architecture, creating technical specifications, or establishing development standards. This mode excels at analyzing requirements, creating detailed plans, and breaking down complex tasks.",
6771
groups: ["read", ["edit", { fileRegex: "\\.md$", description: "Markdown files only" }], "browser", "mcp"],
6872
customInstructions:
6973
"1. Do some information gathering (for example using read_file or search_files) to get more context about the task.\n\n2. You should also ask the user clarifying questions to get a better understanding of the task.\n\n3. Once you've gained more context about the user's request, you should create a detailed plan for how to accomplish the task. Include Mermaid diagrams if they help make your plan clearer.\n\n4. Ask the user if they are pleased with this plan, or if they would like to make any changes. Think of this as a brainstorming session where you can discuss the task and plan the best way to accomplish it.\n\n5. Once the user confirms the plan, ask them if they'd like you to write it to a markdown file.\n\n6. Use the switch_mode tool to request that the user switch to another mode to implement the solution.",
@@ -73,6 +77,8 @@ export const modes: readonly ModeConfig[] = [
7377
name: "❓ Ask",
7478
roleDefinition:
7579
"You are Roo, a knowledgeable technical assistant focused on answering questions and providing information about software development, technology, and related topics.",
80+
whenToUse:
81+
"Use this mode when you need to understand a concept, get an explanation of a piece of code, or learn about a specific technology. This mode can access external resources to provide comprehensive answers.",
7682
groups: ["read", "browser", "mcp"],
7783
customInstructions:
7884
"You can analyze code, explain concepts, and access external resources. Make sure to answer the user's questions and don't rush to switch to implementing code. Include Mermaid diagrams if they help make your response clearer.",
@@ -82,6 +88,8 @@ export const modes: readonly ModeConfig[] = [
8288
name: "🪲 Debug",
8389
roleDefinition:
8490
"You are Roo, an expert software debugger specializing in systematic problem diagnosis and resolution.",
91+
whenToUse:
92+
"Use this mode when you encounter an error, unexpected behavior, or need to troubleshoot an issue in your code. This mode focuses on identifying the root cause of problems and suggesting solutions.",
8593
groups: ["read", "edit", "browser", "command", "mcp"],
8694
customInstructions:
8795
"Reflect on 5-7 different possible sources of the problem, distill those down to 1-2 most likely sources, and then add logs to validate your assumptions. Explicitly ask the user to confirm the diagnosis before fixing the problem.",
@@ -91,6 +99,8 @@ export const modes: readonly ModeConfig[] = [
9199
name: "🪃 Orchestrator",
92100
roleDefinition:
93101
"You are Roo, a strategic workflow orchestrator who coordinates complex tasks by delegating them to appropriate specialized modes. You have a comprehensive understanding of each mode's capabilities and limitations, allowing you to effectively break down complex problems into discrete tasks that can be solved by different specialists.",
102+
whenToUse:
103+
"Use this mode when managing complex tasks that require different specialist capabilities, coordinating multiple workstreams, or handling projects with many interdependent components. The orchestrator excels at task decomposition, specialist selection, and overall project coordination.",
94104
groups: [],
95105
customInstructions:
96106
"Your role is to coordinate complex workflows by delegating tasks to specialized modes. As an orchestrator, you should:\n\n1. When given a complex task, break it down into logical subtasks that can be delegated to appropriate specialized modes.\n\n2. For each subtask, use the `new_task` tool to delegate. Choose the most appropriate mode for the subtask's specific goal and provide comprehensive instructions in the `message` parameter. These instructions must include:\n * All necessary context from the parent task or previous subtasks required to complete the work.\n * A clearly defined scope, specifying exactly what the subtask should accomplish.\n * An explicit statement that the subtask should *only* perform the work outlined in these instructions and not deviate.\n * An instruction for the subtask to signal completion by using the `attempt_completion` tool, providing a concise yet thorough summary of the outcome in the `result` parameter, keeping in mind that this summary will be the source of truth used to keep track of what was completed on this project.\n * A statement that these specific instructions supersede any conflicting general instructions the subtask's mode might have.\n\n3. Track and manage the progress of all subtasks. When a subtask is completed, analyze its results and determine the next steps.\n\n4. Help the user understand how the different subtasks fit together in the overall workflow. Provide clear reasoning about why you're delegating specific tasks to specific modes.\n\n5. When all subtasks are completed, synthesize the results and provide a comprehensive overview of what was accomplished.\n\n6. Ask clarifying questions when necessary to better understand how to break down complex tasks effectively.\n\n7. Suggest improvements to the workflow based on the results of completed subtasks.\n\nUse subtasks to maintain clarity. If a request significantly shifts focus or requires a different expertise (mode), consider creating a subtask rather than overloading the current one.",
@@ -233,6 +243,7 @@ export const defaultPrompts: Readonly<CustomModePrompts> = Object.freeze(
233243
mode.slug,
234244
{
235245
roleDefinition: mode.roleDefinition,
246+
whenToUse: mode.whenToUse,
236247
customInstructions: mode.customInstructions,
237248
},
238249
]),
@@ -248,6 +259,7 @@ export async function getAllModesWithPrompts(context: vscode.ExtensionContext):
248259
return allModes.map((mode) => ({
249260
...mode,
250261
roleDefinition: customModePrompts[mode.slug]?.roleDefinition ?? mode.roleDefinition,
262+
whenToUse: customModePrompts[mode.slug]?.whenToUse ?? mode.whenToUse,
251263
customInstructions: customModePrompts[mode.slug]?.customInstructions ?? mode.customInstructions,
252264
}))
253265
}
@@ -271,6 +283,7 @@ export async function getFullModeDetails(
271283

272284
// Get the base custom instructions
273285
const baseCustomInstructions = promptComponent?.customInstructions || baseMode.customInstructions || ""
286+
const baseWhenToUse = promptComponent?.whenToUse || baseMode.whenToUse || ""
274287

275288
// If we have cwd, load and combine all custom instructions
276289
let fullCustomInstructions = baseCustomInstructions
@@ -288,6 +301,7 @@ export async function getFullModeDetails(
288301
return {
289302
...baseMode,
290303
roleDefinition: promptComponent?.roleDefinition || baseMode.roleDefinition,
304+
whenToUse: baseWhenToUse,
291305
customInstructions: fullCustomInstructions,
292306
}
293307
}
@@ -302,6 +316,16 @@ export function getRoleDefinition(modeSlug: string, customModes?: ModeConfig[]):
302316
return mode.roleDefinition
303317
}
304318

319+
// Helper function to safely get whenToUse
320+
export function getWhenToUse(modeSlug: string, customModes?: ModeConfig[]): string {
321+
const mode = getModeBySlug(modeSlug, customModes)
322+
if (!mode) {
323+
console.warn(`No mode found for slug: ${modeSlug}`)
324+
return ""
325+
}
326+
return mode.whenToUse ?? ""
327+
}
328+
305329
// Helper function to safely get custom instructions
306330
export function getCustomInstructions(modeSlug: string, customModes?: ModeConfig[]): string {
307331
const mode = getModeBySlug(modeSlug, customModes)

webview-ui/src/components/prompts/PromptsView.tsx

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Mode,
88
PromptComponent,
99
getRoleDefinition,
10+
getWhenToUse,
1011
getCustomInstructions,
1112
getAllModes,
1213
ModeConfig,
@@ -106,6 +107,9 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
106107
if (updatedPrompt.roleDefinition === getRoleDefinition(mode)) {
107108
delete updatedPrompt.roleDefinition
108109
}
110+
if (updatedPrompt.whenToUse === getWhenToUse(mode)) {
111+
delete updatedPrompt.whenToUse
112+
}
109113

110114
vscode.postMessage({
111115
type: "updatePrompt",
@@ -195,6 +199,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
195199
const [newModeName, setNewModeName] = useState("")
196200
const [newModeSlug, setNewModeSlug] = useState("")
197201
const [newModeRoleDefinition, setNewModeRoleDefinition] = useState("")
202+
const [newModeWhenToUse, setNewModeWhenToUse] = useState("")
198203
const [newModeCustomInstructions, setNewModeCustomInstructions] = useState("")
199204
const [newModeGroups, setNewModeGroups] = useState<GroupEntry[]>(availableGroups)
200205
const [newModeSource, setNewModeSource] = useState<ModeSource>("global")
@@ -212,6 +217,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
212217
setNewModeSlug("")
213218
setNewModeGroups(availableGroups)
214219
setNewModeRoleDefinition("")
220+
setNewModeWhenToUse("")
215221
setNewModeCustomInstructions("")
216222
setNewModeSource("global")
217223
// Reset error states
@@ -258,6 +264,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
258264
slug: newModeSlug,
259265
name: newModeName,
260266
roleDefinition: newModeRoleDefinition.trim(),
267+
whenToUse: newModeWhenToUse.trim() || undefined,
261268
customInstructions: newModeCustomInstructions.trim() || undefined,
262269
groups: newModeGroups,
263270
source,
@@ -299,6 +306,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
299306
newModeName,
300307
newModeSlug,
301308
newModeRoleDefinition,
309+
newModeWhenToUse, // Add whenToUse dependency
302310
newModeCustomInstructions,
303311
newModeGroups,
304312
newModeSource,
@@ -396,7 +404,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
396404
})
397405
}
398406

399-
const handleAgentReset = (modeSlug: string, type: "roleDefinition" | "customInstructions") => {
407+
const handleAgentReset = (modeSlug: string, type: "roleDefinition" | "whenToUse" | "customInstructions") => {
400408
// Only reset for built-in modes
401409
const existingPrompt = customModePrompts?.[modeSlug] as PromptComponent
402410
const updatedPrompt = { ...existingPrompt }
@@ -699,6 +707,61 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
699707
data-testid={`${getCurrentMode()?.slug || "code"}-prompt-textarea`}
700708
/>
701709
</div>
710+
711+
{/* When to Use section */}
712+
<div className="mb-4">
713+
<div className="flex justify-between items-center mb-1">
714+
<div className="font-bold">{t("prompts:whenToUse.title")}</div>
715+
{!findModeBySlug(visualMode, customModes) && (
716+
<Button
717+
variant="ghost"
718+
size="icon"
719+
onClick={() => {
720+
const currentMode = getCurrentMode()
721+
if (currentMode?.slug) {
722+
handleAgentReset(currentMode.slug, "whenToUse")
723+
}
724+
}}
725+
title={t("prompts:whenToUse.resetToDefault")}
726+
data-testid="when-to-use-reset">
727+
<span className="codicon codicon-discard"></span>
728+
</Button>
729+
)}
730+
</div>
731+
<div className="text-sm text-vscode-descriptionForeground mb-2">
732+
{t("prompts:whenToUse.description")}
733+
</div>
734+
<VSCodeTextArea
735+
value={(() => {
736+
const customMode = findModeBySlug(visualMode, customModes)
737+
const prompt = customModePrompts?.[visualMode] as PromptComponent
738+
return customMode?.whenToUse ?? prompt?.whenToUse ?? getWhenToUse(visualMode)
739+
})()}
740+
onChange={(e) => {
741+
const value =
742+
(e as unknown as CustomEvent)?.detail?.target?.value ||
743+
((e as any).target as HTMLTextAreaElement).value
744+
const customMode = findModeBySlug(visualMode, customModes)
745+
if (customMode) {
746+
// For custom modes, update the JSON file
747+
updateCustomMode(visualMode, {
748+
...customMode,
749+
whenToUse: value.trim() || undefined,
750+
source: customMode.source || "global",
751+
})
752+
} else {
753+
// For built-in modes, update the prompts
754+
updateAgentPrompt(visualMode, {
755+
whenToUse: value.trim() || undefined,
756+
})
757+
}
758+
}}
759+
className="resize-y w-full"
760+
rows={3}
761+
data-testid={`${getCurrentMode()?.slug || "code"}-when-to-use-textarea`}
762+
/>
763+
</div>
764+
702765
{/* Mode settings */}
703766
<>
704767
<div className="mb-3">
@@ -1258,6 +1321,21 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
12581321
</div>
12591322
)}
12601323
</div>
1324+
1325+
<div className="mb-4">
1326+
<div className="font-bold mb-1">{t("prompts:createModeDialog.whenToUse.label")}</div>
1327+
<div className="text-[13px] text-vscode-descriptionForeground mb-2">
1328+
{t("prompts:createModeDialog.whenToUse.description")}
1329+
</div>
1330+
<VSCodeTextArea
1331+
value={newModeWhenToUse}
1332+
onChange={(e) => {
1333+
setNewModeWhenToUse((e.target as HTMLTextAreaElement).value)
1334+
}}
1335+
rows={3}
1336+
className="w-full resize-y"
1337+
/>
1338+
</div>
12611339
<div className="mb-4">
12621340
<div className="font-bold mb-1">{t("prompts:createModeDialog.tools.label")}</div>
12631341
<div className="text-[13px] text-vscode-descriptionForeground mb-2">

webview-ui/src/i18n/locales/ca/prompts.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
"resetToDefault": "Restablir a valors predeterminats",
3535
"description": "Definiu l'experiència i personalitat de Roo per a aquest mode. Aquesta descripció determina com Roo es presenta i aborda les tasques."
3636
},
37+
"whenToUse": {
38+
"title": "Quan utilitzar (opcional)",
39+
"description": "Descriviu quan s'hauria d'utilitzar aquest mode. Això ajuda l'Orchestrator a escollir el mode correcte per a una tasca.",
40+
"resetToDefault": "Restablir la descripció 'Quan utilitzar' a valors predeterminats"
41+
},
3742
"customInstructions": {
3843
"title": "Instruccions personalitzades específiques del mode (opcional)",
3944
"resetToDefault": "Restablir a valors predeterminats",
@@ -131,6 +136,10 @@
131136
"label": "Definició de rol",
132137
"description": "Definiu l'experiència i personalitat de Roo per a aquest mode."
133138
},
139+
"whenToUse": {
140+
"label": "Quan utilitzar (opcional)",
141+
"description": "Proporcioneu una descripció clara de quan aquest mode és més efectiu i per a quins tipus de tasques excel·leix."
142+
},
134143
"tools": {
135144
"label": "Eines disponibles",
136145
"description": "Seleccioneu quines eines pot utilitzar aquest mode."

0 commit comments

Comments
 (0)