diff --git a/src/__tests__/history-resume-delegation.spec.ts b/src/__tests__/history-resume-delegation.spec.ts index a78c41b7c06..2436b6e9d24 100644 --- a/src/__tests__/history-resume-delegation.spec.ts +++ b/src/__tests__/history-resume-delegation.spec.ts @@ -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, diff --git a/src/core/assistant-message/NativeToolCallParser.ts b/src/core/assistant-message/NativeToolCallParser.ts index bda7c71eb8d..35db134d669 100644 --- a/src/core/assistant-message/NativeToolCallParser.ts +++ b/src/core/assistant-message/NativeToolCallParser.ts @@ -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 diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index 7f5862be154..b060d0e3b05 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -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}']` diff --git a/src/core/prompts/tools/native-tools/new_task.ts b/src/core/prompts/tools/native-tools/new_task.ts index f8e29e549d9..e75c416cf70 100644 --- a/src/core/prompts/tools/native-tools/new_task.ts +++ b/src/core/prompts/tools/native-tools/new_task.ts @@ -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, }, }, diff --git a/src/core/task/__tests__/new-task-isolation.spec.ts b/src/core/task/__tests__/new-task-isolation.spec.ts index 9100fb33993..0c3db509020 100644 --- a/src/core/task/__tests__/new-task-isolation.spec.ts +++ b/src/core/task/__tests__/new-task-isolation.spec.ts @@ -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", diff --git a/src/core/tools/NewTaskTool.ts b/src/core/tools/NewTaskTool.ts index f36d8e1e379..acc80ab082c 100644 --- a/src/core/tools/NewTaskTool.ts +++ b/src/core/tools/NewTaskTool.ts @@ -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 { - 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 { - 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 diff --git a/src/core/tools/__tests__/newTaskTool.spec.ts b/src/core/tools/__tests__/newTaskTool.spec.ts index fc383c13eef..6396def511f 100644 --- a/src/core/tools/__tests__/newTaskTool.spec.ts +++ b/src/core/tools/__tests__/newTaskTool.spec.ts @@ -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 [] }, diff --git a/src/shared/tools.ts b/src/shared/tools.ts index d2dd9907b17..52980e681fe 100644 --- a/src/shared/tools.ts +++ b/src/shared/tools.ts @@ -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, "mode" | "message" | "todos">> + params: Partial, "mode_slug" | "message" | "todos">> } export interface RunSlashCommandToolUse extends ToolUse<"run_slash_command"> {