feat: add optional todos parameter to new_task tool with experimental setting (#6329) (#6775)

* feat: add optional todos parameter to new_task tool with experimental setting (#6329)

- Add optional todos parameter to new_task tool for hierarchical task planning
- Implement experimental setting to optionally require todos parameter
- Add clean state-based UI rendering to avoid spurious messages
- Export and reuse parseMarkdownChecklist function
- Add comprehensive test coverage for both optional and required modes
- Maintain full backward compatibility (todos optional by default)

* fix: update new_task tool example to include todos parameter

- Updated the example in tool-use.ts to show the todos parameter
- This prevents AI confusion about whether todos is a valid parameter
- The example now demonstrates the complete tool usage pattern

* fix: make new_task tool definition dynamic based on experimental setting

- Tool description now changes based on newTaskRequireTodos setting
- When disabled: shows todos as (optional)
- When enabled: shows todos as (required) with no mention of configuration
- Added tests to verify dynamic behavior
- Ensures AI models get unambiguous instructions based on current settings

* fix: add translations for newTaskRequireTodos experimental setting

- Added translations for all 17 supported languages
- Ensures consistent UI experience across all locales

* test: update snapshots for new_task tool example with todos parameter

- Updated 13 snapshot files to reflect the new tool-use example
- All tests now pass with the updated example format

* Update src/core/tools/newTaskTool.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: address PR review comments

- Replace any[] with TodoItem[] type in ExtensionStateContext.tsx for better type safety
- Remove redundant initialTodos parameter from startTask call in Task.ts (todos already set in constructor)
- Improve code clarity in newTaskTool.ts by checking provider reference early and reusing state

# Conflicts:
#	src/core/task/Task.ts
#	webview-ui/src/context/ExtensionStateContext.tsx

* fix: revert order of operations in startTask to fix integration test timeout

The change in order of operations (calling say() before postStateToWebview()) was causing the XML content file test to timeout. Reverting to the original order fixes the issue.

* fix: hide todos parameter from new_task tool prompt when experiment is disabled

- Modified getNewTaskDescription to completely omit todos parameter when experiment is off
- Updated tests to verify todos parameter is not shown at all when disabled
- Ensures tool prompt remains unchanged when experimental setting is disabled
- Maintains backward compatibility while providing cleaner prompt interface

* fix: update snapshots for new_task tool todos parameter

- Updated snapshots in add-custom-instructions.spec.ts
- Updated snapshots in system-prompt.spec.ts
- All tests now passing with the new todos parameter documentation

* feat: move newTaskRequireTodos from experimental to VSCode settings

- Added newTaskRequireTodos as a VSCode configuration property in src/package.json
- Added description in src/package.nls.json
- Updated newTaskTool.ts to read from VSCode configuration instead of experiments
- Removed NEW_TASK_REQUIRE_TODOS from experimental settings in src/shared/experiments.ts
- Removed newTaskRequireTodos from packages/types/src/experiment.ts
- Updated tests to use VSCode configuration mocking instead of experiments
- Removed references from experiments test file
- Maintains backward compatibility (defaults to false)

* fix: make new_task tool description dynamically reflect VSCode setting

- Updated new-task.ts to check args.settings instead of args.experiments
- Added newTaskRequireTodos to SystemPromptSettings interface
- Pass newTaskRequireTodos setting through Task.ts and generateSystemPrompt.ts
- Updated all related tests to use settings instead of experiments
- Fixed TypeScript errors in test files by adding newTaskRequireTodos property

This ensures the tool description correctly shows todos parameter as required/optional
based on the VSCode setting value, fixing the issue where Roo would try to use
new_task without the todos parameter when it was required.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Merge Resolver <merge-resolver@roo-code.com>
Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
Hannes Rudolph 2025-08-21 14:02:05 -06:00 committed by GitHub
parent ef340806c7
commit 4664955127
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
51 changed files with 929 additions and 28 deletions

View file

@ -6,7 +6,12 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js"
* ExperimentId
*/
export const experimentIds = ["powerSteering", "multiFileApplyDiff", "preventFocusDisruption", "assistantMessageParser"] as const
export const experimentIds = [
"powerSteering",
"multiFileApplyDiff",
"preventFocusDisruption",
"assistantMessageParser",
] as const
export const experimentIdsSchema = z.enum(experimentIds)

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -27,6 +27,12 @@ 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.

View file

@ -580,6 +580,7 @@ describe("SYSTEM_PROMPT", () => {
maxConcurrentFileReads: 5,
todoListEnabled: false,
useAgentRules: true,
newTaskRequireTodos: false,
}
const prompt = await SYSTEM_PROMPT(
@ -612,6 +613,7 @@ describe("SYSTEM_PROMPT", () => {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
}
const prompt = await SYSTEM_PROMPT(
@ -643,6 +645,7 @@ describe("SYSTEM_PROMPT", () => {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
}
const prompt = await SYSTEM_PROMPT(

View file

@ -535,7 +535,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: true } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
},
},
)
expect(result).toContain("# Agent Rules Standard (AGENTS.md):")
@ -560,7 +567,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: false } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: false,
newTaskRequireTodos: false,
},
},
)
expect(result).not.toContain("# Agent Rules Standard (AGENTS.md):")
@ -614,7 +628,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: true } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
},
},
)
expect(result).toContain("Global Instructions:\nglobal instructions")
@ -653,7 +674,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: true } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
},
},
)
// Should contain both AGENTS.md and .roorules content
@ -714,7 +742,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: true } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
},
},
)
expect(result).toContain("# Agent Rules Standard (AGENTS.md):")
@ -759,7 +794,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: true } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
},
},
)
expect(result).toContain("# Agent Rules Standard (AGENTS.md):")
@ -806,7 +848,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: true } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
},
},
)
expect(result).toContain("# Agent Rules Standard (AGENT.md):")
@ -845,7 +894,14 @@ describe("addCustomInstructions", () => {
"global instructions",
"/fake/path",
"test-mode",
{ settings: { maxConcurrentFileReads: 5, todoListEnabled: true, useAgentRules: true } },
{
settings: {
maxConcurrentFileReads: 5,
todoListEnabled: true,
useAgentRules: true,
newTaskRequireTodos: false,
},
},
)
// Should contain AGENTS.md content (preferred) and not AGENT.md

View file

@ -20,6 +20,12 @@ 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.`

View file

@ -0,0 +1,117 @@
import { describe, it, expect } from "vitest"
import { getNewTaskDescription } from "../new-task"
import { ToolArgs } from "../types"
describe("getNewTaskDescription", () => {
it("should not show todos parameter at all when setting is disabled", () => {
const args: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
settings: {
newTaskRequireTodos: false,
},
}
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>")
// Should have a simple example without todos
expect(description).toContain("Implement a new feature for the application")
// Should still have mode and message as required
expect(description).toContain("mode: (required)")
expect(description).toContain("message: (required)")
})
it("should show todos as required when setting is enabled", () => {
const args: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
settings: {
newTaskRequireTodos: true,
},
}
const description = getNewTaskDescription(args)
// Check that todos is marked as required
expect(description).toContain("todos: (required)")
expect(description).toContain("and initial todo list")
// Should not contain any mention of optional for todos
expect(description).not.toContain("todos: (optional)")
expect(description).not.toContain("optional initial todo list")
// Should include todos in the example
expect(description).toContain("<todos>")
expect(description).toContain("</todos>")
expect(description).toContain("Set up auth middleware")
})
it("should not show todos parameter when settings is undefined", () => {
const args: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
settings: undefined,
}
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>")
})
it("should not show todos parameter when newTaskRequireTodos is undefined", () => {
const args: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
settings: {},
}
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>")
})
it("should only include todos in example when setting is enabled", () => {
const argsWithSettingOff: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
settings: {
newTaskRequireTodos: false,
},
}
const argsWithSettingOn: ToolArgs = {
cwd: "/test",
supportsComputerUse: false,
settings: {
newTaskRequireTodos: true,
},
}
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 example
expect(descriptionOn).toMatch(todosPattern)
expect(descriptionOn).toContain("<todos>")
})
})

View file

@ -1,7 +1,11 @@
import { ToolArgs } from "./types"
export function getNewTaskDescription(_args: ToolArgs): string {
return `## new_task
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:
@ -19,5 +23,39 @@ Example:
<mode>code</mode>
<message>Implement a new feature for the application.</message>
</new_task>
`
}
// When setting is enabled, show todos as required
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.
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.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First task to complete
[ ] Second task to complete
[ ] Third task to complete
</todos>
</new_task>
Example:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up auth middleware
[ ] Create login endpoint
[ ] Add session management
[ ] Write tests
</todos>
</new_task>
`
}

View file

@ -5,4 +5,5 @@ export interface SystemPromptSettings {
maxConcurrentFileReads: number
todoListEnabled: boolean
useAgentRules: boolean
newTaskRequireTodos: boolean
}

View file

@ -126,6 +126,7 @@ export type TaskOptions = {
parentTask?: Task
taskNumber?: number
onCreated?: (task: Task) => void
initialTodos?: TodoItem[]
}
export class Task extends EventEmitter<TaskEvents> implements TaskLike {
@ -290,6 +291,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
parentTask,
taskNumber = -1,
onCreated,
initialTodos,
}: TaskOptions) {
super()
@ -373,6 +375,11 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
this.toolRepetitionDetector = new ToolRepetitionDetector(this.consecutiveMistakeLimit)
// Initialize todo list if provided
if (initialTodos && initialTodos.length > 0) {
this.todoList = initialTodos
}
onCreated?.(this)
if (startTask) {
@ -1078,6 +1085,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// messages from previous session).
this.clineMessages = []
this.apiConversationHistory = []
// The todo list is already set in the constructor if initialTodos were provided
// No need to add any messages - the todoList property is already set
await this.providerRef.deref()?.postStateToWebview()
await this.say("text", task, images)
@ -2228,6 +2239,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
maxConcurrentFileReads: maxConcurrentFileReads ?? 5,
todoListEnabled: apiConfiguration?.todoListEnabled ?? true,
useAgentRules: vscode.workspace.getConfiguration("roo-cline").get<boolean>("useAgentRules") ?? true,
newTaskRequireTodos: vscode.workspace
.getConfiguration("roo-cline")
.get<boolean>("newTaskRequireTodos", false),
},
undefined, // todoList
this.api.getModel().id,

View file

@ -2,6 +2,15 @@
import type { AskApproval, HandleError } from "../../../shared/tools"
// Mock vscode module
vi.mock("vscode", () => ({
workspace: {
getConfiguration: vi.fn(() => ({
get: vi.fn(),
})),
},
}))
// Mock other modules first - these are hoisted to the top
vi.mock("../../../shared/modes", () => ({
getModeBySlug: vi.fn(),
@ -14,6 +23,33 @@ vi.mock("../../prompts/responses", () => ({
},
}))
vi.mock("../updateTodoListTool", () => ({
parseMarkdownChecklist: vi.fn((md: string) => {
// Simple mock implementation
const lines = md.split("\n").filter((line) => line.trim())
return lines.map((line, index) => {
let status = "pending"
let content = line
if (line.includes("[x]") || line.includes("[X]")) {
status = "completed"
content = line.replace(/^\[x\]\s*/i, "")
} else if (line.includes("[-]") || line.includes("[~]")) {
status = "in_progress"
content = line.replace(/^\[-\]\s*/, "").replace(/^\[~\]\s*/, "")
} else {
content = line.replace(/^\[\s*\]\s*/, "")
}
return {
id: `todo-${index}`,
content,
status,
}
})
}),
}))
// Define a minimal type for the resolved value
type MockClineInstance = { taskId: string }
@ -22,7 +58,9 @@ const mockAskApproval = vi.fn<AskApproval>()
const mockHandleError = vi.fn<HandleError>()
const mockPushToolResult = vi.fn()
const mockRemoveClosingTag = vi.fn((_name: string, value: string | undefined) => value ?? "")
const mockCreateTask = vi.fn<() => Promise<MockClineInstance>>().mockResolvedValue({ taskId: "mock-subtask-id" })
const mockCreateTask = vi
.fn<(text?: string, images?: string[], parentTask?: any, options?: any) => Promise<MockClineInstance>>()
.mockResolvedValue({ taskId: "mock-subtask-id" })
const mockEmit = vi.fn()
const mockRecordToolError = vi.fn()
const mockSayAndCreateMissingParamError = vi.fn()
@ -49,6 +87,7 @@ const mockCline = {
import { newTaskTool } from "../newTaskTool"
import type { ToolUse } from "../../../shared/tools"
import { getModeBySlug } from "../../../shared/modes"
import * as vscode from "vscode"
describe("newTaskTool", () => {
beforeEach(() => {
@ -63,6 +102,11 @@ describe("newTaskTool", () => {
}) // Default valid mode
mockCline.consecutiveMistakeCount = 0
mockCline.isPaused = false
// Default: VSCode setting is disabled
const mockGet = vi.fn().mockReturnValue(false)
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
get: mockGet,
} as any)
})
it("should correctly un-escape \\\\@ to \\@ in the message passed to the new task", async () => {
@ -72,6 +116,7 @@ describe("newTaskTool", () => {
params: {
mode: "code",
message: "Review this: \\\\@file1.txt and also \\\\\\\\@file2.txt", // Input with \\@ and \\\\@
todos: "[ ] First task\n[ ] Second task",
},
partial: false,
}
@ -93,6 +138,12 @@ describe("newTaskTool", () => {
"Review this: \\@file1.txt and also \\\\\\@file2.txt", // Unit Test Expectation: \\@ -> \@, \\\\@ -> \\\\@
undefined,
mockCline,
expect.objectContaining({
initialTodos: expect.arrayContaining([
expect.objectContaining({ content: "First task" }),
expect.objectContaining({ content: "Second task" }),
]),
}),
)
// Verify side effects
@ -109,6 +160,7 @@ describe("newTaskTool", () => {
params: {
mode: "code",
message: "This is already unescaped: \\@file1.txt",
todos: "[ ] Test todo",
},
partial: false,
}
@ -126,6 +178,9 @@ describe("newTaskTool", () => {
"This is already unescaped: \\@file1.txt", // Expected: \@ remains \@
undefined,
mockCline,
expect.objectContaining({
initialTodos: expect.any(Array),
}),
)
})
@ -136,6 +191,7 @@ describe("newTaskTool", () => {
params: {
mode: "code",
message: "A normal mention @file1.txt",
todos: "[ ] Test todo",
},
partial: false,
}
@ -153,6 +209,9 @@ describe("newTaskTool", () => {
"A normal mention @file1.txt", // Expected: @ remains @
undefined,
mockCline,
expect.objectContaining({
initialTodos: expect.any(Array),
}),
)
})
@ -163,6 +222,7 @@ describe("newTaskTool", () => {
params: {
mode: "code",
message: "Mix: @file0.txt, \\@file1.txt, \\\\@file2.txt, \\\\\\\\@file3.txt",
todos: "[ ] Test todo",
},
partial: false,
}
@ -180,8 +240,386 @@ describe("newTaskTool", () => {
"Mix: @file0.txt, \\@file1.txt, \\@file2.txt, \\\\\\@file3.txt", // Unit Test Expectation: @->@, \@->\@, \\@->\@, \\\\@->\\\\@
undefined,
mockCline,
expect.objectContaining({
initialTodos: expect.any(Array),
}),
)
})
// Add more tests for error handling (missing params, invalid mode, approval denied) if needed
it("should handle missing todos parameter gracefully (backward compatibility)", async () => {
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message",
// todos missing - should work for backward compatibility
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Should NOT error when todos is missing
expect(mockSayAndCreateMissingParamError).not.toHaveBeenCalledWith("new_task", "todos")
expect(mockCline.consecutiveMistakeCount).toBe(0)
expect(mockCline.recordToolError).not.toHaveBeenCalledWith("new_task")
// Should create task with empty todos array
expect(mockCreateTask).toHaveBeenCalledWith(
"Test message",
undefined,
mockCline,
expect.objectContaining({
initialTodos: [],
}),
)
// Should complete successfully
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Successfully created new task"))
})
it("should work with todos parameter when provided", async () => {
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message with todos",
todos: "[ ] First task\n[ ] Second task",
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Should parse and include todos when provided
expect(mockCreateTask).toHaveBeenCalledWith(
"Test message with todos",
undefined,
mockCline,
expect.objectContaining({
initialTodos: expect.arrayContaining([
expect.objectContaining({ content: "First task" }),
expect.objectContaining({ content: "Second task" }),
]),
}),
)
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Successfully created new task"))
})
it("should error when mode parameter is missing", async () => {
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
// mode missing
message: "Test message",
todos: "[ ] Test todo",
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
expect(mockSayAndCreateMissingParamError).toHaveBeenCalledWith("new_task", "mode")
expect(mockCline.consecutiveMistakeCount).toBe(1)
expect(mockCline.recordToolError).toHaveBeenCalledWith("new_task")
})
it("should error when message parameter is missing", async () => {
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
// message missing
todos: "[ ] Test todo",
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
expect(mockSayAndCreateMissingParamError).toHaveBeenCalledWith("new_task", "message")
expect(mockCline.consecutiveMistakeCount).toBe(1)
expect(mockCline.recordToolError).toHaveBeenCalledWith("new_task")
})
it("should parse todos with different statuses correctly", async () => {
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message",
todos: "[ ] Pending task\n[x] Completed task\n[-] In progress task",
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
expect(mockCreateTask).toHaveBeenCalledWith(
"Test message",
undefined,
mockCline,
expect.objectContaining({
initialTodos: expect.arrayContaining([
expect.objectContaining({ content: "Pending task", status: "pending" }),
expect.objectContaining({ content: "Completed task", status: "completed" }),
expect.objectContaining({ content: "In progress task", status: "in_progress" }),
]),
}),
)
})
describe("VSCode setting: newTaskRequireTodos", () => {
it("should NOT require todos when VSCode setting is disabled (default)", async () => {
// Ensure VSCode setting is disabled
const mockGet = vi.fn().mockReturnValue(false)
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
get: mockGet,
} as any)
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message",
// todos missing - should work when setting is disabled
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Should NOT error when todos is missing and setting is disabled
expect(mockSayAndCreateMissingParamError).not.toHaveBeenCalledWith("new_task", "todos")
expect(mockCline.consecutiveMistakeCount).toBe(0)
expect(mockCline.recordToolError).not.toHaveBeenCalledWith("new_task")
// Should create task with empty todos array
expect(mockCreateTask).toHaveBeenCalledWith(
"Test message",
undefined,
mockCline,
expect.objectContaining({
initialTodos: [],
}),
)
// Should complete successfully
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Successfully created new task"))
})
it("should REQUIRE todos when VSCode setting is enabled", async () => {
// Enable VSCode setting
const mockGet = vi.fn().mockReturnValue(true)
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
get: mockGet,
} as any)
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message",
// todos missing - should error when setting is enabled
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Should error when todos is missing and setting is enabled
expect(mockSayAndCreateMissingParamError).toHaveBeenCalledWith("new_task", "todos")
expect(mockCline.consecutiveMistakeCount).toBe(1)
expect(mockCline.recordToolError).toHaveBeenCalledWith("new_task")
// Should NOT create task
expect(mockCreateTask).not.toHaveBeenCalled()
expect(mockPushToolResult).not.toHaveBeenCalledWith(
expect.stringContaining("Successfully created new task"),
)
})
it("should work with todos when VSCode setting is enabled", async () => {
// Enable VSCode setting
const mockGet = vi.fn().mockReturnValue(true)
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
get: mockGet,
} as any)
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message",
todos: "[ ] First task\n[ ] Second task",
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Should NOT error when todos is provided and setting is enabled
expect(mockSayAndCreateMissingParamError).not.toHaveBeenCalledWith("new_task", "todos")
expect(mockCline.consecutiveMistakeCount).toBe(0)
// Should create task with parsed todos
expect(mockCreateTask).toHaveBeenCalledWith(
"Test message",
undefined,
mockCline,
expect.objectContaining({
initialTodos: expect.arrayContaining([
expect.objectContaining({ content: "First task" }),
expect.objectContaining({ content: "Second task" }),
]),
}),
)
// Should complete successfully
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Successfully created new task"))
})
it("should work with empty todos string when VSCode setting is enabled", async () => {
// Enable VSCode setting
const mockGet = vi.fn().mockReturnValue(true)
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
get: mockGet,
} as any)
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message",
todos: "", // Empty string should be accepted
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Should NOT error when todos is empty string and setting is enabled
expect(mockSayAndCreateMissingParamError).not.toHaveBeenCalledWith("new_task", "todos")
expect(mockCline.consecutiveMistakeCount).toBe(0)
// Should create task with empty todos array
expect(mockCreateTask).toHaveBeenCalledWith(
"Test message",
undefined,
mockCline,
expect.objectContaining({
initialTodos: [],
}),
)
// Should complete successfully
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Successfully created new task"))
})
it("should check VSCode setting with correct configuration key", async () => {
const mockGet = vi.fn().mockReturnValue(false)
const mockGetConfiguration = vi.fn().mockReturnValue({
get: mockGet,
} as any)
vi.mocked(vscode.workspace.getConfiguration).mockImplementation(mockGetConfiguration)
const block: ToolUse = {
type: "tool_use",
name: "new_task",
params: {
mode: "code",
message: "Test message",
},
partial: false,
}
await newTaskTool(
mockCline as any,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Verify that VSCode configuration was accessed correctly
expect(mockGetConfiguration).toHaveBeenCalledWith("roo-cline")
expect(mockGet).toHaveBeenCalledWith("newTaskRequireTodos", false)
})
})
// Add more tests for error handling (invalid mode, approval denied) if needed
})

View file

@ -1,12 +1,14 @@
import delay from "delay"
import * as vscode from "vscode"
import { RooCodeEventName } from "@roo-code/types"
import { RooCodeEventName, TodoItem } from "@roo-code/types"
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
import { Task } from "../task/Task"
import { defaultModeSlug, getModeBySlug } from "../../shared/modes"
import { formatResponse } from "../prompts/responses"
import { t } from "../../i18n"
import { parseMarkdownChecklist } from "./updateTodoListTool"
export async function newTaskTool(
cline: Task,
@ -18,6 +20,7 @@ export async function newTaskTool(
) {
const mode: string | undefined = block.params.mode
const message: string | undefined = block.params.message
const todos: string | undefined = block.params.todos
try {
if (block.partial) {
@ -25,11 +28,13 @@ export async function newTaskTool(
tool: "newTask",
mode: removeClosingTag("mode", mode),
content: removeClosingTag("message", message),
todos: removeClosingTag("todos", todos),
})
await cline.ask("tool", partialMessage, block.partial).catch(() => {})
return
} else {
// Validate required parameters
if (!mode) {
cline.consecutiveMistakeCount++
cline.recordToolError("new_task")
@ -44,13 +49,46 @@ export async function newTaskTool(
return
}
// Get the VSCode setting for requiring todos
const provider = cline.providerRef.deref()
if (!provider) {
pushToolResult(formatResponse.toolError("Provider reference lost"))
return
}
const state = await provider.getState()
const requireTodos = vscode.workspace
.getConfiguration("roo-cline")
.get<boolean>("newTaskRequireTodos", false)
// Check if todos are required based on VSCode setting
// Note: undefined means not provided, empty string is valid
if (requireTodos && todos === undefined) {
cline.consecutiveMistakeCount++
cline.recordToolError("new_task")
pushToolResult(await cline.sayAndCreateMissingParamError("new_task", "todos"))
return
}
// Parse todos if provided, otherwise use empty array
let todoItems: TodoItem[] = []
if (todos) {
try {
todoItems = parseMarkdownChecklist(todos)
} catch (error) {
cline.consecutiveMistakeCount++
cline.recordToolError("new_task")
pushToolResult(formatResponse.toolError("Invalid todos format: must be a markdown checklist"))
return
}
}
cline.consecutiveMistakeCount = 0
// Un-escape one level of backslashes before '@' for hierarchical subtasks
// Un-escape one level: \\@ -> \@ (removes one backslash for hierarchical subtasks)
const unescapedMessage = message.replace(/\\\\@/g, "\\@")
// Verify the mode exists
const targetMode = getModeBySlug(mode, (await cline.providerRef.deref()?.getState())?.customModes)
const targetMode = getModeBySlug(mode, state?.customModes)
if (!targetMode) {
pushToolResult(formatResponse.toolError(`Invalid mode: ${mode}`))
@ -61,6 +99,7 @@ export async function newTaskTool(
tool: "newTask",
mode: targetMode.name,
content: message,
todos: todoItems,
})
const didApprove = await askApproval("tool", toolMessage)
@ -69,11 +108,7 @@ export async function newTaskTool(
return
}
const provider = cline.providerRef.deref()
if (!provider) {
return
}
// Provider is guaranteed to be defined here due to earlier check
if (cline.enableCheckpoints) {
cline.checkpointSave(true)
@ -83,8 +118,9 @@ export async function newTaskTool(
cline.pausedModeSlug = (await provider.getState()).mode ?? defaultModeSlug
// Create new task instance first (this preserves parent's current mode in its history)
const newCline = await provider.createTask(unescapedMessage, undefined, cline)
const newCline = await provider.createTask(unescapedMessage, undefined, cline, {
initialTodos: todoItems,
})
if (!newCline) {
pushToolResult(t("tools:newTask.errors.policy_restriction"))
return
@ -98,7 +134,9 @@ export async function newTaskTool(
cline.emit(RooCodeEventName.TaskSpawned, newCline.taskId)
pushToolResult(`Successfully created new task in ${targetMode.name} mode with message: ${unescapedMessage}`)
pushToolResult(
`Successfully created new task in ${targetMode.name} mode with message: ${unescapedMessage} and ${todoItems.length} todo items`,
)
// Set the isPaused flag to true so the parent
// task can wait for the sub-task to finish.

View file

@ -100,7 +100,7 @@ function normalizeStatus(status: string | undefined): TodoStatus {
return "pending"
}
function parseMarkdownChecklist(md: string): TodoItem[] {
export function parseMarkdownChecklist(md: string): TodoItem[] {
if (typeof md !== "string") return []
const lines = md
.split(/\r?\n/)

View file

@ -757,7 +757,12 @@ export class ClineProvider
options: Partial<
Pick<
TaskOptions,
"enableDiff" | "enableCheckpoints" | "fuzzyMatchThreshold" | "consecutiveMistakeLimit" | "experiments"
| "enableDiff"
| "enableCheckpoints"
| "fuzzyMatchThreshold"
| "consecutiveMistakeLimit"
| "experiments"
| "initialTodos"
>
> = {},
) {
@ -791,6 +796,7 @@ export class ClineProvider
taskNumber: this.clineStack.length + 1,
onCreated: this.taskCreationCallback,
enableTaskBridge: isRemoteControlEnabled(cloudUserInfo, remoteControlEnabled),
initialTodos: options.initialTodos,
...options,
})
@ -1791,6 +1797,7 @@ export class ClineProvider
? (taskHistory || []).find((item: HistoryItem) => item.id === this.getCurrentTask()?.taskId)
: undefined,
clineMessages: this.getCurrentTask()?.clineMessages || [],
currentTaskTodos: this.getCurrentTask()?.todoList || [],
taskHistory: (taskHistory || [])
.filter((item: HistoryItem) => item.ts && item.task)
.sort((a: HistoryItem, b: HistoryItem) => b.ts - a.ts),

View file

@ -85,6 +85,9 @@ export const generateSystemPrompt = async (provider: ClineProvider, message: Web
maxConcurrentFileReads: maxConcurrentFileReads ?? 5,
todoListEnabled: apiConfiguration?.todoListEnabled ?? true,
useAgentRules: vscode.workspace.getConfiguration("roo-cline").get<boolean>("useAgentRules") ?? true,
newTaskRequireTodos: vscode.workspace
.getConfiguration("roo-cline")
.get<boolean>("newTaskRequireTodos", false),
},
)

View file

@ -398,6 +398,11 @@
"minimum": 0,
"maximum": 3600,
"description": "%settings.apiRequestTimeout.description%"
},
"roo-cline.newTaskRequireTodos": {
"type": "boolean",
"default": false,
"description": "%settings.newTaskRequireTodos.description%"
}
}
}

View file

@ -39,5 +39,6 @@
"settings.enableCodeActions.description": "Enable Roo Code quick fixes",
"settings.autoImportSettingsPath.description": "Path to a RooCode configuration file to automatically import on extension startup. Supports absolute paths and paths relative to the home directory (e.g. '~/Documents/roo-code-settings.json'). Leave empty to disable auto-import.",
"settings.useAgentRules.description": "Enable loading of AGENTS.md files for agent-specific rules (see https://agent-rules.org/)",
"settings.apiRequestTimeout.description": "Maximum time in seconds to wait for API responses (0 = no timeout, 1-3600s, default: 600s). Higher values are recommended for local providers like LM Studio and Ollama that may need more processing time."
"settings.apiRequestTimeout.description": "Maximum time in seconds to wait for API responses (0 = no timeout, 1-3600s, default: 600s). Higher values are recommended for local providers like LM Studio and Ollama that may need more processing time.",
"settings.newTaskRequireTodos.description": "Require todos parameter when creating new tasks with the new_task tool"
}

View file

@ -8,6 +8,7 @@ import type {
Experiments,
ClineMessage,
MarketplaceItem,
TodoItem,
} from "@roo-code/types"
import type { CloudUserInfo, OrganizationAllowList, ShareVisibility } from "@roo-code/cloud"
@ -274,6 +275,7 @@ export type ExtensionState = Pick<
version: string
clineMessages: ClineMessage[]
currentTaskItem?: HistoryItem
currentTaskTodos?: TodoItem[] // Initial todos for the current task
apiConfiguration?: ProviderSettings
uriScheme?: string
shouldShowAnnouncement: boolean

View file

@ -155,7 +155,7 @@ export interface SwitchModeToolUse extends ToolUse {
export interface NewTaskToolUse extends ToolUse {
name: "new_task"
params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message">>
params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message" | "todos">>
}
export interface SearchAndReplaceToolUse extends ToolUse {

View file

@ -87,6 +87,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
const {
clineMessages: messages,
currentTaskItem,
currentTaskTodos,
taskHistory,
apiConfiguration,
organizationAllowList,
@ -144,8 +145,20 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
const task = useMemo(() => messages.at(0), [messages])
const latestTodos = useMemo(() => {
// First check if we have initial todos from the state (for new subtasks)
if (currentTaskTodos && currentTaskTodos.length > 0) {
// Check if there are any todo updates in messages
const messageBasedTodos = getLatestTodo(messages)
// If there are message-based todos, they take precedence (user has updated them)
if (messageBasedTodos && messageBasedTodos.length > 0) {
return messageBasedTodos
}
// Otherwise use the initial todos from state
return currentTaskTodos
}
// Fall back to extracting from messages
return getLatestTodo(messages)
}, [messages])
}, [messages, currentTaskTodos])
const modifiedMessages = useMemo(() => combineApiRequests(combineCommandSequences(messages.slice(1))), [messages])

View file

@ -6,6 +6,7 @@ import {
type CustomModePrompts,
type ModeConfig,
type ExperimentId,
type TodoItem,
} from "@roo-code/types"
import { type OrganizationAllowList, ORGANIZATION_ALLOW_ALL } from "@roo/cloud"
@ -31,6 +32,7 @@ export interface ExtensionStateContextType extends ExtensionState {
mcpServers: McpServer[]
hasSystemPromptOverride?: boolean
currentCheckpoint?: string
currentTaskTodos?: TodoItem[] // Initial todos for the current task
filePaths: string[]
openedTabs: Array<{ label: string; isActive: boolean; path?: string }>
commands: Command[]

View file

@ -230,6 +230,7 @@ describe("mergeExtensionState", () => {
multiFileApplyDiff: true,
preventFocusDisruption: false,
assistantMessageParser: false,
newTaskRequireTodos: false,
} as Record<ExperimentId, boolean>,
}
@ -248,6 +249,7 @@ describe("mergeExtensionState", () => {
multiFileApplyDiff: true,
preventFocusDisruption: false,
assistantMessageParser: false,
newTaskRequireTodos: false,
})
})
})

View file

@ -719,6 +719,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Utilitza el nou analitzador de missatges",
"description": "Activa l'analitzador de missatges en streaming experimental que millora el rendiment en respostes llargues processant els missatges de manera més eficient."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Requerir la llista 'todos' per a noves tasques",
"description": "Quan estigui activat, l'eina new_task requerirà que es proporcioni un paràmetre 'todos'. Això garanteix que totes les noves tasques comencin amb una llista clara d'objectius. Quan estigui desactivat (per defecte), el paràmetre 'todos' continua sent opcional per a la compatibilitat amb versions anteriors."
}
},
"promptCaching": {

View file

@ -719,6 +719,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Neuen Nachrichtenparser verwenden",
"description": "Aktiviere den experimentellen Streaming-Nachrichtenparser, der lange Antworten durch effizientere Verarbeitung spürbar schneller macht."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "'todos'-Liste für neue Aufgaben anfordern",
"description": "Wenn aktiviert, erfordert das new_task-Tool die Angabe eines todos-Parameters. Dies stellt sicher, dass alle neuen Aufgaben mit einer klaren Zielliste beginnen. Wenn deaktiviert (Standard), bleibt der todos-Parameter aus Gründen der Abwärtskompatibilität optional."
}
},
"promptCaching": {

View file

@ -718,6 +718,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Use new message parser",
"description": "Enable the experimental streaming message parser that provides significant performance improvements for long assistant responses by processing messages more efficiently."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Require 'todos' list for new tasks",
"description": "When enabled, the new_task tool will require a todos parameter to be provided. This ensures all new tasks start with a clear list of objectives. When disabled (default), the todos parameter remains optional for backward compatibility."
}
},
"promptCaching": {

View file

@ -719,6 +719,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Usar el nuevo analizador de mensajes",
"description": "Activa el analizador de mensajes en streaming experimental que mejora el rendimiento en respuestas largas procesando los mensajes de forma más eficiente."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Requerir lista de 'todos' para nuevas tareas",
"description": "Cuando está habilitado, la herramienta new_task requerirá que se proporcione un parámetro todos. Esto asegura que todas las nuevas tareas comiencen con una lista clara de objetivos. Cuando está deshabilitado (predeterminado), el parámetro todos permanece opcional por compatibilidad con versiones anteriores."
}
},
"promptCaching": {

View file

@ -719,6 +719,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Utiliser le nouveau parseur de messages",
"description": "Active le parseur de messages en streaming expérimental qui accélère nettement les longues réponses en traitant les messages plus efficacement."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Exiger la liste 'todos' pour les nouvelles tâches",
"description": "Lorsqu'il est activé, l'outil new_task exigera qu'un paramètre todos soit fourni. Cela garantit que toutes les nouvelles tâches commencent avec une liste claire d'objectifs. Lorsqu'il est désactivé (par défaut), le paramètre todos reste facultatif pour la compatibilité descendante."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "नए मैसेज पार्सर का उपयोग करें",
"description": "प्रायोगिक स्ट्रीमिंग मैसेज पार्सर सक्षम करें, जो लंबे उत्तरों के लिए संदेशों को अधिक कुशलता से प्रोसेस करके प्रदर्शन को बेहतर बनाता है।"
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "नए कार्यों के लिए 'todos' सूची की आवश्यकता है",
"description": "जब सक्षम किया जाता है, तो new_task टूल को todos पैरामीटर प्रदान करने की आवश्यकता होगी। यह सुनिश्चित करता है कि सभी नए कार्य स्पष्ट उद्देश्यों की सूची के साथ शुरू हों। जब अक्षम किया जाता है (डिफ़ॉल्ट), तो todos पैरामीटर पिछड़े संगतता के लिए वैकल्पिक रहता है।"
}
},
"promptCaching": {

View file

@ -749,6 +749,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Gunakan parser pesan baru",
"description": "Aktifkan parser pesan streaming eksperimental yang meningkatkan kinerja untuk respons panjang dengan memproses pesan lebih efisien."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Membutuhkan daftar 'todos' untuk tugas baru",
"description": "Ketika diaktifkan, alat new_task akan membutuhkan parameter todos untuk disediakan. Ini memastikan semua tugas baru dimulai dengan daftar tujuan yang jelas. Ketika dinonaktifkan (default), parameter todos tetap opsional untuk kompatibilitas mundur."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Usa il nuovo parser dei messaggi",
"description": "Abilita il parser di messaggi in streaming sperimentale che migliora nettamente le risposte lunghe elaborando i messaggi in modo più efficiente."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Richiedi elenco 'todos' per nuove attività",
"description": "Quando abilitato, lo strumento new_task richiederà la fornitura di un parametro todos. Ciò garantisce che tutte le nuove attività inizino con un elenco chiaro di obiettivi. Quando disabilitato (impostazione predefinita), il parametro todos rimane facoltativo per la compatibilità con le versioni precedenti."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "新しいメッセージパーサーを使う",
"description": "実験的なストリーミングメッセージパーサーを有効にします。長い回答をより効率的に処理し、遅延を減らします。"
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "新しいタスクには'todos'リストを必須にする",
"description": "有効にすると、new_taskツールはtodosパラメータの提供が必須になります。これにより、すべての新しいタスクが明確な目的のリストで開始されることが保証されます。無効デフォルトの場合、下位互換性のためにtodosパラメータはオプションのままです。"
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "새 메시지 파서 사용",
"description": "실험적 스트리밍 메시지 파서를 활성화합니다. 긴 응답을 더 효율적으로 처리해 지연을 줄입니다."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "새 작업에 'todos' 목록 필요",
"description": "활성화하면 new_task 도구에 todos 매개변수를 제공해야 합니다. 이렇게 하면 모든 새 작업이 명확한 목표 목록으로 시작됩니다. 비활성화하면(기본값) 이전 버전과의 호환성을 위해 todos 매개변수는 선택 사항으로 유지됩니다."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Nieuwe berichtparser gebruiken",
"description": "Schakel de experimentele streaming-berichtparser in die lange antwoorden sneller maakt door berichten efficiënter te verwerken."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "'todos'-lijst vereisen voor nieuwe taken",
"description": "Wanneer ingeschakeld, vereist de new_task-tool dat een todos-parameter wordt opgegeven. Dit zorgt ervoor dat alle nieuwe taken beginnen met een duidelijke lijst met doelstellingen. Wanneer uitgeschakeld (standaard), blijft de todos-parameter optioneel voor achterwaartse compatibiliteit."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Użyj nowego parsera wiadomości",
"description": "Włącz eksperymentalny parser wiadomości w strumieniu, który przyspiesza długie odpowiedzi dzięki bardziej wydajnemu przetwarzaniu wiadomości."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Wymagaj listy 'todos' dla nowych zadań",
"description": "Gdy włączone, narzędzie new_task będzie wymagało podania parametru todos. Zapewnia to, że wszystkie nowe zadania rozpoczynają się od jasnej listy celów. Gdy wyłączone (domyślnie), parametr todos pozostaje opcjonalny dla zachowania kompatybilności wstecznej."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Usar o novo parser de mensagens",
"description": "Ativa o parser de mensagens em streaming experimental que acelera respostas longas ao processar as mensagens de forma mais eficiente."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Exigir lista de 'todos' para novas tarefas",
"description": "Quando ativado, a ferramenta new_task exigirá que um parâmetro todos seja fornecido. Isso garante que todas as novas tarefas comecem com uma lista clara de objetivos. Quando desativado (padrão), o parâmetro todos permanece opcional para compatibilidade com versões anteriores."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Использовать новый парсер сообщений",
"description": "Включите экспериментальный потоковый парсер сообщений, который ускоряет длинные ответы благодаря более эффективной обработке сообщений."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Требовать список 'todos' для новых задач",
"description": "Если включено, инструмент new_task будет требовать предоставления параметра todos. Это гарантирует, что все новые задачи начинаются с четкого списка целей. Когда отключено (по умолчанию), параметр todos остается необязательным для обратной совместимости."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Yeni mesaj ayrıştırıcıyı kullan",
"description": "Uzun yanıtları daha verimli işleyerek hızlandıran deneysel akış mesaj ayrıştırıcısını etkinleştir."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Yeni görevler için 'todos' listesi gerektir",
"description": "Etkinleştirildiğinde, new_task aracı bir todos parametresi sağlanmasını gerektirir. Bu, tüm yeni görevlerin net bir hedef listesiyle başlamasını sağlar. Devre dışı bırakıldığında (varsayılan), todos parametresi geriye dönük uyumluluk için isteğe bağlı kalır."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "Dùng bộ phân tích tin nhắn mới",
"description": "Bật bộ phân tích tin nhắn streaming thử nghiệm. Tính năng này tăng tốc phản hồi dài bằng cách xử lý tin nhắn hiệu quả hơn."
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "Yêu cầu danh sách 'todos' cho các nhiệm vụ mới",
"description": "Khi được bật, công cụ new_task sẽ yêu cầu cung cấp tham số todos. Điều này đảm bảo tất cả các nhiệm vụ mới bắt đầu với một danh sách mục tiêu rõ ràng. Khi bị tắt (mặc định), tham số todos vẫn là tùy chọn để tương thích ngược."
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "使用新的消息解析器",
"description": "启用实验性的流式消息解析器。通过更高效地处理消息,可显著提升长回复的性能。"
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "要求新任务提供 'todos' 列表",
"description": "启用后new_task 工具将需要提供 todos 参数。这可以确保所有新任务都以明确的目标列表开始。禁用时默认todos 参数保持可选,以实现向后兼容。"
}
},
"promptCaching": {

View file

@ -720,6 +720,10 @@
"ASSISTANT_MESSAGE_PARSER": {
"name": "使用全新訊息解析器",
"description": "啟用實驗性的串流訊息解析器。透過更有效率地處理訊息,能顯著提升長回覆的效能。"
},
"NEW_TASK_REQUIRE_TODOS": {
"name": "要求新工作提供 'todos' 列表",
"description": "啟用後new_task 工具將需要提供 todos 參數。這可以確保所有新工作都以明確的目標列表開始。停用時預設todos 參數保持可選,以實現向後相容。"
}
},
"promptCaching": {