Skip to content
13 changes: 0 additions & 13 deletions src/core/prompts/sections/tool-use.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,5 @@ Tool uses are formatted using XML-style tags. The tool name itself becomes the X
...
</actual_tool_name>

For example, to use the new_task tool:

<new_task>
<mode>code</mode>
<message>Implement a new feature for the application.</message>
<todos>
[ ] Design the feature architecture
[ ] Implement core functionality
[ ] Add error handling
[ ] Write tests
</todos>
</new_task>

Always use the actual tool name as the XML tag name for proper parsing and execution.`
}
57 changes: 30 additions & 27 deletions src/core/prompts/tools/__tests__/new-task.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getNewTaskDescription } from "../new-task"
import { ToolArgs } from "../types"

describe("getNewTaskDescription", () => {
it("should not show todos parameter at all when setting is disabled", () => {
it("should show todos parameter as optional when setting is disabled", () => {
const args: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
Expand All @@ -14,15 +14,16 @@ describe("getNewTaskDescription", () => {

const description = getNewTaskDescription(args)

// Check that todos parameter is not mentioned at all
expect(description).not.toContain("todos:")
expect(description).not.toContain("todo list")
expect(description).not.toContain("<todos>")
expect(description).not.toContain("</todos>")
// Check that todos parameter is shown as optional
expect(description).toContain("todos: (optional)")
expect(description).toContain("The initial todo list in markdown checklist format")

// Should have a simple example without todos
// Should have a simple example without todos in the main example
expect(description).toContain("Implement a new feature for the application")

// Should also have an example with optional todos
expect(description).toContain("Example with optional todos:")

// Should still have mode and message as required
expect(description).toContain("mode: (required)")
expect(description).toContain("message: (required)")
Expand Down Expand Up @@ -53,7 +54,7 @@ describe("getNewTaskDescription", () => {
expect(description).toContain("Set up auth middleware")
})

it("should not show todos parameter when settings is undefined", () => {
it("should show todos parameter as optional when settings is undefined", () => {
const args: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
Expand All @@ -62,14 +63,12 @@ describe("getNewTaskDescription", () => {

const description = getNewTaskDescription(args)

// Check that todos parameter is not shown by default
expect(description).not.toContain("todos:")
expect(description).not.toContain("todo list")
expect(description).not.toContain("<todos>")
expect(description).not.toContain("</todos>")
// Check that todos parameter is shown as optional by default
expect(description).toContain("todos: (optional)")
expect(description).toContain("The initial todo list in markdown checklist format")
})

it("should not show todos parameter when newTaskRequireTodos is undefined", () => {
it("should show todos parameter as optional when newTaskRequireTodos is undefined", () => {
const args: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
Expand All @@ -78,14 +77,12 @@ describe("getNewTaskDescription", () => {

const description = getNewTaskDescription(args)

// Check that todos parameter is not shown by default
expect(description).not.toContain("todos:")
expect(description).not.toContain("todo list")
expect(description).not.toContain("<todos>")
expect(description).not.toContain("</todos>")
// Check that todos parameter is shown as optional by default
expect(description).toContain("todos: (optional)")
expect(description).toContain("The initial todo list in markdown checklist format")
})

it("should only include todos in example when setting is enabled", () => {
it("should include todos in main example only when setting is enabled", () => {
const argsWithSettingOff: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
Expand All @@ -105,13 +102,19 @@ describe("getNewTaskDescription", () => {
const descriptionOff = getNewTaskDescription(argsWithSettingOff)
const descriptionOn = getNewTaskDescription(argsWithSettingOn)

// When setting is off, should NOT include todos in example
const todosPattern = /<todos>\s*\[\s*\]\s*Set up auth middleware/s
expect(descriptionOff).not.toMatch(todosPattern)
expect(descriptionOff).not.toContain("<todos>")
// When setting is on, should include todos in main example
expect(descriptionOn).toContain("Implement user authentication")
expect(descriptionOn).toContain("[ ] Set up auth middleware")

// When setting is on, should NOT have "Example with optional todos" section
expect(descriptionOn).not.toContain("Example with optional todos:")

// When setting is off, main example should NOT include todos in Usage section
const usagePattern = /<new_task>\s*<mode>.*<\/mode>\s*<message>.*<\/message>\s*<\/new_task>/s
expect(descriptionOff).toMatch(usagePattern)

// When setting is on, should include todos in example
expect(descriptionOn).toMatch(todosPattern)
expect(descriptionOn).toContain("<todos>")
// When setting is off, should have separate "Example with optional todos" section
expect(descriptionOff).toContain("Example with optional todos:")
expect(descriptionOff).toContain("[ ] Set up auth middleware")
})
})
57 changes: 29 additions & 28 deletions src/core/prompts/tools/new-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,51 @@ import { ToolArgs } from "./types"
export function getNewTaskDescription(args: ToolArgs): string {
const todosRequired = args.settings?.newTaskRequireTodos === true

// When setting is disabled, don't show todos parameter at all
if (!todosRequired) {
return `## new_task
Description: This will let you create a new task instance in the chosen mode using your provided message.

Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.

Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
</new_task>

Example:
<new_task>
<mode>code</mode>
<message>Implement a new feature for the application.</message>
</new_task>
`
}

// When setting is enabled, show todos as required
// Always show the todos parameter, but mark it as optional or required based on setting
return `## new_task
Description: This will let you create a new task instance in the chosen mode using your provided message and initial todo list.
Description: This will let you create a new task instance in the chosen mode using your provided message${todosRequired ? " and initial todo list" : ""}.

Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (required) The initial todo list in markdown checklist format for the new task.
- todos: (${todosRequired ? "required" : "optional"}) The initial todo list in markdown checklist format for the new task.

Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<message>Your initial instructions here</message>${
todosRequired
? `
<todos>
[ ] First task to complete
[ ] Second task to complete
[ ] Third task to complete
</todos>
</todos>`
: ""
}
</new_task>

Example:
<new_task>
<mode>code</mode>
<message>${todosRequired ? "Implement user authentication" : "Implement a new feature for the application"}</message>${
todosRequired
? `
<todos>
[ ] Set up auth middleware
[ ] Create login endpoint
[ ] Add session management
[ ] Write tests
</todos>`
: ""
}
</new_task>

${
!todosRequired
? `Example with optional todos:
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The conditional logic for the example message and todos section creates complex template literal nesting that's difficult to read and maintain. Consider extracting the example generation into separate helper functions or variables to improve readability.

Copilot uses AI. Check for mistakes.
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up auth middleware
Expand All @@ -58,4 +57,6 @@ Example:
</todos>
</new_task>
`
: ""
}`
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The additional conditional example section further complicates the template literal structure. This nested conditional logic makes the function harder to understand and maintain. Consider restructuring to use a more straightforward approach with separate string building or helper functions.

Suggested change
: ""
}`
}
const description = [
"## new_task",
`Description: This will let you create a new task instance in the chosen mode using your provided message${todosRequired ? " and initial todo list" : ""}.`,
"",
"Parameters:",
"- mode: (required) The slug of the mode to start the new task in (e.g., \"code\", \"debug\", \"architect\").",
"- message: (required) The initial user message or instructions for this new task.",
getTodosParamDescription(todosRequired),
"",
"Usage:",
"<new_task>",
"<mode>your-mode-slug-here</mode>",
"<message>Your initial instructions here</message>" + getTodosUsageBlock(todosRequired),
"</new_task>",
"",
"Example:",
"<new_task>",
"<mode>code</mode>",
`<message>${todosRequired ? "Implement user authentication" : "Implement a new feature for the application"}</message>` + getTodosExampleBlock(todosRequired),
"</new_task>",
"",
getOptionalTodosExampleBlock(todosRequired)
].join("\n");
return description;

Copilot uses AI. Check for mistakes.
}
14 changes: 12 additions & 2 deletions src/core/tools/__tests__/newTaskTool.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ vi.mock("vscode", () => ({
},
}))

// Mock Package module
vi.mock("../../../shared/package", () => ({
Package: {
name: "roo-cline",
publisher: "RooVeterinaryInc",
version: "1.0.0",
outputChannel: "Roo-Code",
},
}))

// Mock other modules first - these are hoisted to the top
vi.mock("../../../shared/modes", () => ({
getModeBySlug: vi.fn(),
Expand Down Expand Up @@ -589,7 +599,7 @@ describe("newTaskTool", () => {
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Successfully created new task"))
})

it("should check VSCode setting with correct configuration key", async () => {
it("should check VSCode setting with Package.name configuration key", async () => {
const mockGet = vi.fn().mockReturnValue(false)
const mockGetConfiguration = vi.fn().mockReturnValue({
get: mockGet,
Expand All @@ -615,7 +625,7 @@ describe("newTaskTool", () => {
mockRemoveClosingTag,
)

// Verify that VSCode configuration was accessed correctly
// Verify that VSCode configuration was accessed with Package.name
expect(mockGetConfiguration).toHaveBeenCalledWith("roo-cline")
expect(mockGet).toHaveBeenCalledWith("newTaskRequireTodos", false)
})
Expand Down
5 changes: 4 additions & 1 deletion src/core/tools/newTaskTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { defaultModeSlug, getModeBySlug } from "../../shared/modes"
import { formatResponse } from "../prompts/responses"
import { t } from "../../i18n"
import { parseMarkdownChecklist } from "./updateTodoListTool"
import { Package } from "../../shared/package"

export async function newTaskTool(
cline: Task,
Expand Down Expand Up @@ -56,8 +57,10 @@ export async function newTaskTool(
return
}
const state = await provider.getState()

// Use Package.name to get the correct configuration namespace
const requireTodos = vscode.workspace
.getConfiguration("roo-cline")
.getConfiguration(Package.name)
.get<boolean>("newTaskRequireTodos", false)

// Check if todos are required based on VSCode setting
Expand Down
Loading