Skip to content

Commit 267ed33

Browse files
committed
feat: add disableTaskLists option to mode configuration
- Add optional disableTaskLists property to ModeConfig type schema - Update tool description generation to conditionally exclude update_todo_list tool - Modify isToolAllowedForMode to respect disableTaskLists setting - Add comprehensive tests for the new functionality Fixes #5693
1 parent a163053 commit 267ed33

File tree

5 files changed

+189
-3
lines changed

5 files changed

+189
-3
lines changed

packages/types/src/mode.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export const modeConfigSchema = z.object({
7070
customInstructions: z.string().optional(),
7171
groups: groupEntryArraySchema,
7272
source: z.enum(["global", "project"]).optional(),
73+
disableTaskLists: z.boolean().optional(),
7374
})
7475

7576
export type ModeConfig = z.infer<typeof modeConfigSchema>
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// npx vitest run src/core/prompts/tools/__tests__/index.spec.ts
2+
3+
import type { ModeConfig } from "@roo-code/types"
4+
5+
import { getToolDescriptionsForMode } from "../index"
6+
7+
describe("getToolDescriptionsForMode", () => {
8+
describe("disableTaskLists", () => {
9+
it("excludes update_todo_list from tool descriptions when disableTaskLists is true", () => {
10+
const customModes: ModeConfig[] = [
11+
{
12+
slug: "no-tasks-mode",
13+
name: "No Tasks Mode",
14+
roleDefinition: "A mode without task lists",
15+
groups: ["read"] as const,
16+
disableTaskLists: true,
17+
},
18+
]
19+
20+
const toolDescriptions = getToolDescriptionsForMode(
21+
"no-tasks-mode",
22+
"/test/cwd",
23+
false, // supportsComputerUse
24+
undefined, // codeIndexManager
25+
undefined, // diffStrategy
26+
undefined, // browserViewportSize
27+
undefined, // mcpHub
28+
customModes,
29+
{}, // experiments
30+
false, // partialReadsEnabled
31+
{}, // settings
32+
)
33+
34+
// Should not contain update_todo_list tool description
35+
expect(toolDescriptions).not.toContain("update_todo_list")
36+
expect(toolDescriptions).not.toContain("## update_todo_list")
37+
38+
// Should still contain other always available tools
39+
expect(toolDescriptions).toContain("ask_followup_question")
40+
expect(toolDescriptions).toContain("attempt_completion")
41+
})
42+
43+
it("includes update_todo_list in tool descriptions when disableTaskLists is false", () => {
44+
const customModes: ModeConfig[] = [
45+
{
46+
slug: "tasks-mode",
47+
name: "Tasks Mode",
48+
roleDefinition: "A mode with task lists",
49+
groups: ["read"] as const,
50+
disableTaskLists: false,
51+
},
52+
]
53+
54+
const toolDescriptions = getToolDescriptionsForMode(
55+
"tasks-mode",
56+
"/test/cwd",
57+
false, // supportsComputerUse
58+
undefined, // codeIndexManager
59+
undefined, // diffStrategy
60+
undefined, // browserViewportSize
61+
undefined, // mcpHub
62+
customModes,
63+
{}, // experiments
64+
false, // partialReadsEnabled
65+
{}, // settings
66+
)
67+
68+
// Should contain update_todo_list tool description
69+
expect(toolDescriptions).toContain("## update_todo_list")
70+
})
71+
72+
it("includes update_todo_list in tool descriptions when disableTaskLists is undefined", () => {
73+
const customModes: ModeConfig[] = [
74+
{
75+
slug: "default-mode",
76+
name: "Default Mode",
77+
roleDefinition: "A mode with default task list behavior",
78+
groups: ["read"] as const,
79+
},
80+
]
81+
82+
const toolDescriptions = getToolDescriptionsForMode(
83+
"default-mode",
84+
"/test/cwd",
85+
false, // supportsComputerUse
86+
undefined, // codeIndexManager
87+
undefined, // diffStrategy
88+
undefined, // browserViewportSize
89+
undefined, // mcpHub
90+
customModes,
91+
{}, // experiments
92+
false, // partialReadsEnabled
93+
{}, // settings
94+
)
95+
96+
// Should contain update_todo_list tool description by default
97+
expect(toolDescriptions).toContain("## update_todo_list")
98+
})
99+
100+
it("includes update_todo_list in built-in mode tool descriptions", () => {
101+
const toolDescriptions = getToolDescriptionsForMode(
102+
"code",
103+
"/test/cwd",
104+
false, // supportsComputerUse
105+
undefined, // codeIndexManager
106+
undefined, // diffStrategy
107+
undefined, // browserViewportSize
108+
undefined, // mcpHub
109+
[], // customModes
110+
{}, // experiments
111+
false, // partialReadsEnabled
112+
{}, // settings
113+
)
114+
115+
// Built-in modes should always include update_todo_list
116+
expect(toolDescriptions).toContain("## update_todo_list")
117+
})
118+
})
119+
})

src/core/prompts/tools/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,14 @@ export function getToolDescriptionsForMode(
9898
}
9999
})
100100

101-
// Add always available tools
102-
ALWAYS_AVAILABLE_TOOLS.forEach((tool) => tools.add(tool))
101+
// Add always available tools, but check for mode-specific exclusions
102+
ALWAYS_AVAILABLE_TOOLS.forEach((tool) => {
103+
// Check if update_todo_list should be excluded for this mode
104+
if (tool === "update_todo_list" && config.disableTaskLists) {
105+
return // Skip adding this tool
106+
}
107+
tools.add(tool)
108+
})
103109

104110
// Conditionally exclude codebase_search if feature is disabled or not configured
105111
if (

src/core/tools/__tests__/validateToolUse.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,59 @@ describe("mode-validator", () => {
128128
expect(isToolAllowedForMode("apply_diff", codeMode, [], requirements)).toBe(false)
129129
})
130130
})
131+
132+
describe("disableTaskLists", () => {
133+
it("disallows update_todo_list when disableTaskLists is true", () => {
134+
const customModes: ModeConfig[] = [
135+
{
136+
slug: "no-tasks-mode",
137+
name: "No Tasks Mode",
138+
roleDefinition: "A mode without task lists",
139+
groups: ["read"] as const,
140+
disableTaskLists: true,
141+
},
142+
]
143+
// Should not allow update_todo_list tool
144+
expect(isToolAllowedForMode("update_todo_list", "no-tasks-mode", customModes)).toBe(false)
145+
// Should still allow other always available tools
146+
expect(isToolAllowedForMode("ask_followup_question", "no-tasks-mode", customModes)).toBe(true)
147+
expect(isToolAllowedForMode("attempt_completion", "no-tasks-mode", customModes)).toBe(true)
148+
})
149+
150+
it("allows update_todo_list when disableTaskLists is false", () => {
151+
const customModes: ModeConfig[] = [
152+
{
153+
slug: "tasks-mode",
154+
name: "Tasks Mode",
155+
roleDefinition: "A mode with task lists",
156+
groups: ["read"] as const,
157+
disableTaskLists: false,
158+
},
159+
]
160+
// Should allow update_todo_list tool
161+
expect(isToolAllowedForMode("update_todo_list", "tasks-mode", customModes)).toBe(true)
162+
})
163+
164+
it("allows update_todo_list when disableTaskLists is undefined", () => {
165+
const customModes: ModeConfig[] = [
166+
{
167+
slug: "default-mode",
168+
name: "Default Mode",
169+
roleDefinition: "A mode with default task list behavior",
170+
groups: ["read"] as const,
171+
},
172+
]
173+
// Should allow update_todo_list tool by default
174+
expect(isToolAllowedForMode("update_todo_list", "default-mode", customModes)).toBe(true)
175+
})
176+
177+
it("allows update_todo_list in built-in modes", () => {
178+
// Built-in modes should always allow update_todo_list
179+
expect(isToolAllowedForMode("update_todo_list", codeMode, [])).toBe(true)
180+
expect(isToolAllowedForMode("update_todo_list", architectMode, [])).toBe(true)
181+
expect(isToolAllowedForMode("update_todo_list", askMode, [])).toBe(true)
182+
})
183+
})
131184
})
132185

133186
describe("validateToolUse", () => {

src/shared/modes.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,15 @@ export function isToolAllowedForMode(
231231
toolParams?: Record<string, any>, // All tool parameters
232232
experiments?: Record<string, boolean>,
233233
): boolean {
234-
// Always allow these tools
234+
// Always allow these tools, but check for mode-specific exclusions
235235
if (ALWAYS_AVAILABLE_TOOLS.includes(tool as any)) {
236+
// Check if update_todo_list should be excluded for this mode
237+
if (tool === "update_todo_list") {
238+
const mode = getModeBySlug(modeSlug, customModes)
239+
if (mode?.disableTaskLists) {
240+
return false
241+
}
242+
}
236243
return true
237244
}
238245
if (experiments && Object.values(EXPERIMENT_IDS).includes(tool as ExperimentId)) {

0 commit comments

Comments
 (0)