mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix: rename new_task mode param to mode_slug for consistency with switch_mode
The new_task tool used "mode" as its parameter name while switch_mode used "mode_slug" for the same concept (a mode slug). This inconsistency caused LLMs to confuse the parameter names between the two tools, leading to errors like "Missing value for required parameter mode_slug" when using new_task. Renamed the new_task parameter from "mode" to "mode_slug" to match switch_mode, eliminating the source of LLM confusion. Fixes #11861
This commit is contained in:
parent
44fd975b17
commit
6d8d4dd7f6
8 changed files with 48 additions and 48 deletions
|
|
@ -241,7 +241,7 @@ describe("History resume delegation - parent metadata transitions", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
id: "toolu_abc123",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
],
|
||||
ts: 50,
|
||||
|
|
|
|||
|
|
@ -628,9 +628,9 @@ export class NativeToolCallParser {
|
|||
break
|
||||
|
||||
case "new_task":
|
||||
if (partialArgs.mode !== undefined || partialArgs.message !== undefined) {
|
||||
if (partialArgs.mode_slug !== undefined || partialArgs.message !== undefined) {
|
||||
nativeArgs = {
|
||||
mode: partialArgs.mode,
|
||||
mode_slug: partialArgs.mode_slug,
|
||||
message: partialArgs.message,
|
||||
todos: partialArgs.todos,
|
||||
}
|
||||
|
|
@ -977,9 +977,9 @@ export class NativeToolCallParser {
|
|||
break
|
||||
|
||||
case "new_task":
|
||||
if (args.mode !== undefined && args.message !== undefined) {
|
||||
if (args.mode_slug !== undefined && args.message !== undefined) {
|
||||
nativeArgs = {
|
||||
mode: args.mode,
|
||||
mode_slug: args.mode_slug,
|
||||
message: args.message,
|
||||
todos: args.todos,
|
||||
} as NativeArgsFor<TName>
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
case "update_todo_list":
|
||||
return `[${block.name}]`
|
||||
case "new_task": {
|
||||
const mode = block.params.mode ?? defaultModeSlug
|
||||
const mode = block.params.mode_slug ?? defaultModeSlug
|
||||
const message = block.params.message ?? "(no message)"
|
||||
const modeName = getModeBySlug(mode, customModes)?.name ?? mode
|
||||
return `[${block.name} in ${modeName} mode: '${message}']`
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export default {
|
|||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
mode_slug: {
|
||||
type: "string",
|
||||
description: MODE_PARAMETER_DESCRIPTION,
|
||||
},
|
||||
|
|
@ -32,7 +32,7 @@ export default {
|
|||
description: TODOS_PARAMETER_DESCRIPTION,
|
||||
},
|
||||
},
|
||||
required: ["mode", "message", "todos"],
|
||||
required: ["mode_slug", "message", "todos"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
|
|
@ -146,7 +146,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
|
|
@ -173,7 +173,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
|
|
@ -219,7 +219,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
|
|
@ -253,7 +253,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
|
|
@ -284,7 +284,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
|
|
@ -316,7 +316,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
// Simulating a malformed tool without ID (shouldn't happen, but defensive)
|
||||
{
|
||||
|
|
@ -345,13 +345,13 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "First task" },
|
||||
input: { mode_slug: "code", message: "First task" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
id: "toolu_new_task_2",
|
||||
name: "new_task",
|
||||
input: { mode: "debug", message: "Second task" },
|
||||
input: { mode_slug: "debug", message: "Second task" },
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -375,7 +375,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
|
|
@ -397,7 +397,7 @@ describe("new_task Tool Isolation Enforcement", () => {
|
|||
type: "tool_use",
|
||||
id: "toolu_new_task_1",
|
||||
name: "new_task",
|
||||
input: { mode: "code", message: "Do something" },
|
||||
input: { mode_slug: "code", message: "Do something" },
|
||||
},
|
||||
{
|
||||
type: "tool_use",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { BaseTool, ToolCallbacks } from "./BaseTool"
|
|||
import type { ToolUse } from "../../shared/tools"
|
||||
|
||||
interface NewTaskParams {
|
||||
mode: string
|
||||
mode_slug: string
|
||||
message: string
|
||||
todos?: string
|
||||
}
|
||||
|
|
@ -21,16 +21,16 @@ export class NewTaskTool extends BaseTool<"new_task"> {
|
|||
readonly name = "new_task" as const
|
||||
|
||||
async execute(params: NewTaskParams, task: Task, callbacks: ToolCallbacks): Promise<void> {
|
||||
const { mode, message, todos } = params
|
||||
const { mode_slug, message, todos } = params
|
||||
const { askApproval, handleError, pushToolResult } = callbacks
|
||||
|
||||
try {
|
||||
// Validate required parameters.
|
||||
if (!mode) {
|
||||
if (!mode_slug) {
|
||||
task.consecutiveMistakeCount++
|
||||
task.recordToolError("new_task")
|
||||
task.didToolFailInCurrentTurn = true
|
||||
pushToolResult(await task.sayAndCreateMissingParamError("new_task", "mode"))
|
||||
pushToolResult(await task.sayAndCreateMissingParamError("new_task", "mode_slug"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -89,10 +89,10 @@ export class NewTaskTool extends BaseTool<"new_task"> {
|
|||
const unescapedMessage = message.replace(/\\\\@/g, "\\@")
|
||||
|
||||
// Verify the mode exists
|
||||
const targetMode = getModeBySlug(mode, state?.customModes)
|
||||
const targetMode = getModeBySlug(mode_slug, state?.customModes)
|
||||
|
||||
if (!targetMode) {
|
||||
pushToolResult(formatResponse.toolError(`Invalid mode: ${mode}`))
|
||||
pushToolResult(formatResponse.toolError(`Invalid mode: ${mode_slug}`))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ export class NewTaskTool extends BaseTool<"new_task"> {
|
|||
parentTaskId: task.taskId,
|
||||
message: unescapedMessage,
|
||||
initialTodos: todoItems,
|
||||
mode,
|
||||
mode: mode_slug,
|
||||
})
|
||||
|
||||
// Reflect delegation in tool result (no pause/unpause, no wait)
|
||||
|
|
@ -127,7 +127,7 @@ export class NewTaskTool extends BaseTool<"new_task"> {
|
|||
}
|
||||
|
||||
override async handlePartial(task: Task, block: ToolUse<"new_task">): Promise<void> {
|
||||
const mode: string | undefined = block.params.mode
|
||||
const mode: string | undefined = block.params.mode_slug
|
||||
const message: string | undefined = block.params.message
|
||||
const todos: string | undefined = block.params.todos
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ const withNativeArgs = (block: ToolUse<"new_task">): ToolUse<"new_task"> => ({
|
|||
// These tests intentionally exercise missing-param behavior, so we allow undefined
|
||||
// values and let the tool's runtime validation handle it.
|
||||
nativeArgs: {
|
||||
mode: block.params.mode,
|
||||
mode_slug: block.params.mode_slug,
|
||||
message: block.params.message,
|
||||
todos: block.params.todos,
|
||||
} as unknown as NativeToolArgs["new_task"],
|
||||
|
|
@ -148,7 +148,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Review this: \\\\@file1.txt and also \\\\\\\\@file2.txt", // Input with \\@ and \\\\@
|
||||
todos: "[ ] First task\n[ ] Second task",
|
||||
},
|
||||
|
|
@ -183,7 +183,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "This is already unescaped: \\@file1.txt",
|
||||
todos: "[ ] Test todo",
|
||||
},
|
||||
|
|
@ -208,7 +208,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "A normal mention @file1.txt",
|
||||
todos: "[ ] Test todo",
|
||||
},
|
||||
|
|
@ -233,7 +233,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Mix: @file0.txt, \\@file1.txt, \\\\@file2.txt, \\\\\\\\@file3.txt",
|
||||
todos: "[ ] Test todo",
|
||||
},
|
||||
|
|
@ -258,7 +258,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
// todos missing - should work for backward compatibility
|
||||
},
|
||||
|
|
@ -288,7 +288,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message with todos",
|
||||
todos: "[ ] First task\n[ ] Second task",
|
||||
},
|
||||
|
|
@ -332,7 +332,7 @@ describe("newTaskTool", () => {
|
|||
pushToolResult: mockPushToolResult,
|
||||
})
|
||||
|
||||
expect(mockSayAndCreateMissingParamError).toHaveBeenCalledWith("new_task", "mode")
|
||||
expect(mockSayAndCreateMissingParamError).toHaveBeenCalledWith("new_task", "mode_slug")
|
||||
expect(mockCline.consecutiveMistakeCount).toBe(1)
|
||||
expect(mockCline.recordToolError).toHaveBeenCalledWith("new_task")
|
||||
})
|
||||
|
|
@ -342,7 +342,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
// message missing
|
||||
todos: "[ ] Test todo",
|
||||
},
|
||||
|
|
@ -365,7 +365,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
todos: "[ ] Pending task\n[x] Completed task\n[-] In progress task",
|
||||
},
|
||||
|
|
@ -401,7 +401,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
// todos missing - should work when setting is disabled
|
||||
},
|
||||
|
|
@ -437,7 +437,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
// todos missing - should error when setting is enabled
|
||||
},
|
||||
|
|
@ -473,7 +473,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
todos: "[ ] First task\n[ ] Second task",
|
||||
},
|
||||
|
|
@ -515,7 +515,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
todos: "", // Empty string should be accepted
|
||||
},
|
||||
|
|
@ -550,7 +550,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
},
|
||||
partial: false,
|
||||
|
|
@ -583,7 +583,7 @@ describe("newTaskTool", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Test message",
|
||||
},
|
||||
partial: false,
|
||||
|
|
@ -640,7 +640,7 @@ describe("newTaskTool delegation flow", () => {
|
|||
type: "tool_use",
|
||||
name: "new_task",
|
||||
params: {
|
||||
mode: "code",
|
||||
mode_slug: "code",
|
||||
message: "Do something",
|
||||
// no todos -> should default to []
|
||||
},
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export type NativeToolArgs = {
|
|||
edit_file: { file_path: string; old_string: string; new_string: string; expected_replacements?: number }
|
||||
apply_patch: { patch: string }
|
||||
list_files: { path: string; recursive?: boolean }
|
||||
new_task: { mode: string; message: string; todos?: string }
|
||||
new_task: { mode_slug: string; message: string; todos?: string }
|
||||
ask_followup_question: {
|
||||
question: string
|
||||
follow_up: Array<{ text: string; mode?: string }>
|
||||
|
|
@ -240,7 +240,7 @@ export interface SwitchModeToolUse extends ToolUse<"switch_mode"> {
|
|||
|
||||
export interface NewTaskToolUse extends ToolUse<"new_task"> {
|
||||
name: "new_task"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message" | "todos">>
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "mode_slug" | "message" | "todos">>
|
||||
}
|
||||
|
||||
export interface RunSlashCommandToolUse extends ToolUse<"run_slash_command"> {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue