Roo-Code/src/core/tools/newTaskTool.ts

90 lines
2.6 KiB
TypeScript

import { ToolUse } from "../assistant-message"
import { HandleError, PushToolResult, RemoveClosingTag } from "./types"
import { Cline } from "../Cline"
import { AskApproval } from "./types"
import { defaultModeSlug, getModeBySlug } from "../../shared/modes"
import { formatResponse } from "../prompts/responses"
import delay from "delay"
export async function newTaskTool(
cline: Cline,
block: ToolUse,
askApproval: AskApproval,
handleError: HandleError,
pushToolResult: PushToolResult,
removeClosingTag: RemoveClosingTag,
) {
const mode: string | undefined = block.params.mode
const message: string | undefined = block.params.message
try {
if (block.partial) {
const partialMessage = JSON.stringify({
tool: "newTask",
mode: removeClosingTag("mode", mode),
message: removeClosingTag("message", message),
})
await cline.ask("tool", partialMessage, block.partial).catch(() => {})
return
} else {
if (!mode) {
cline.consecutiveMistakeCount++
pushToolResult(await cline.sayAndCreateMissingParamError("new_task", "mode"))
return
}
if (!message) {
cline.consecutiveMistakeCount++
pushToolResult(await cline.sayAndCreateMissingParamError("new_task", "message"))
return
}
cline.consecutiveMistakeCount = 0
// Verify the mode exists
const targetMode = getModeBySlug(mode, (await cline.providerRef.deref()?.getState())?.customModes)
if (!targetMode) {
pushToolResult(formatResponse.toolError(`Invalid mode: ${mode}`))
return
}
const toolMessage = JSON.stringify({
tool: "newTask",
mode: targetMode.name,
content: message,
})
const didApprove = await askApproval("tool", toolMessage)
if (!didApprove) {
return
}
const provider = cline.providerRef.deref()
if (!provider) {
return
}
// Preserve the current mode so we can resume with it later.
cline.pausedModeSlug = (await provider.getState()).mode ?? defaultModeSlug
// Switch mode first, then create new task instance.
await provider.handleModeSwitch(mode)
// Delay to allow mode change to take effect before next tool is executed.
await delay(500)
const newCline = await provider.initClineWithTask(message, undefined, cline)
cline.emit("taskSpawned", newCline.taskId)
pushToolResult(`Successfully created new task in ${targetMode.name} mode with message: ${message}`)
// Set the isPaused flag to true so the parent
// task can wait for the sub-task to finish.
cline.isPaused = true
cline.emit("taskPaused")
return
}
} catch (error) {
await handleError("creating new task", error)
return
}
}