Matt Rubens 11 месяцев назад
Родитель
Сommit
13de490c3b

+ 76 - 2
src/core/Cline.ts

@@ -631,7 +631,7 @@ export class Cline {
 
 		let newUserContent: UserContent = [...modifiedOldUserContent]
 
-		const agoText = (() => {
+		const agoText = ((): string => {
 			const timestamp = lastClineMessage?.ts ?? Date.now()
 			const now = Date.now()
 			const diff = now - timestamp
@@ -996,7 +996,7 @@ export class Cline {
 				break
 			}
 			case "tool_use":
-				const toolDescription = () => {
+				const toolDescription = (): string => {
 					switch (block.name) {
 						case "execute_command":
 							return `[${block.name} for '${block.params.command}']`
@@ -1030,6 +1030,12 @@ export class Cline {
 							return `[${block.name}]`
 						case "switch_mode":
 							return `[${block.name} to '${block.params.mode_slug}'${block.params.reason ? ` because: ${block.params.reason}` : ""}]`
+						case "new_task": {
+							const mode = block.params.mode ?? defaultModeSlug
+							const message = block.params.message ?? "(no message)"
+							const modeName = getModeBySlug(mode, customModes)?.name ?? mode
+							return `[${block.name} in ${modeName} mode: '${message}']`
+						}
 					}
 				}
 
@@ -2402,6 +2408,74 @@ export class Cline {
 						}
 					}
 
+					case "new_task": {
+						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 this.ask("tool", partialMessage, block.partial).catch(() => {})
+								break
+							} else {
+								if (!mode) {
+									this.consecutiveMistakeCount++
+									pushToolResult(await this.sayAndCreateMissingParamError("new_task", "mode"))
+									break
+								}
+								if (!message) {
+									this.consecutiveMistakeCount++
+									pushToolResult(await this.sayAndCreateMissingParamError("new_task", "message"))
+									break
+								}
+								this.consecutiveMistakeCount = 0
+
+								// Verify the mode exists
+								const targetMode = getModeBySlug(
+									mode,
+									(await this.providerRef.deref()?.getState())?.customModes,
+								)
+								if (!targetMode) {
+									pushToolResult(formatResponse.toolError(`Invalid mode: ${mode}`))
+									break
+								}
+
+								// Show what we're about to do
+								const toolMessage = JSON.stringify({
+									tool: "newTask",
+									mode: targetMode.name,
+									content: message,
+								})
+
+								const didApprove = await askApproval("tool", toolMessage)
+								if (!didApprove) {
+									break
+								}
+
+								// Switch mode first, then create new task instance
+								const provider = this.providerRef.deref()
+								if (provider) {
+									await provider.handleModeSwitch(mode)
+									await provider.initClineWithTask(message)
+									pushToolResult(
+										`Successfully created new task in ${targetMode.name} mode with message: ${message}`,
+									)
+								} else {
+									pushToolResult(
+										formatResponse.toolError("Failed to create new task: provider not available"),
+									)
+								}
+								break
+							}
+						} catch (error) {
+							await handleError("creating new task", error)
+							break
+						}
+					}
+
 					case "attempt_completion": {
 						/*
 						this.consecutiveMistakeCount = 0

+ 8 - 0
src/core/assistant-message/index.ts

@@ -24,6 +24,7 @@ export const toolUseNames = [
 	"ask_followup_question",
 	"attempt_completion",
 	"switch_mode",
+	"new_task",
 ] as const
 
 // Converts array of tool call names into a union type ("execute_command" | "read_file" | ...)
@@ -53,6 +54,8 @@ export const toolParamNames = [
 	"mode_slug",
 	"reason",
 	"operations",
+	"mode",
+	"message",
 ] as const
 
 export type ToolParamName = (typeof toolParamNames)[number]
@@ -130,3 +133,8 @@ export interface SwitchModeToolUse extends ToolUse {
 	name: "switch_mode"
 	params: Partial<Pick<Record<ToolParamName, string>, "mode_slug" | "reason">>
 }
+
+export interface NewTaskToolUse extends ToolUse {
+	name: "new_task"
+	params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message">>
+}

+ 200 - 0
src/core/prompts/__tests__/__snapshots__/system.test.ts.snap

@@ -198,6 +198,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -501,6 +521,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -804,6 +844,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -1153,6 +1213,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -1508,6 +1588,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -2221,6 +2321,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -2587,6 +2707,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -2892,6 +3032,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -3238,6 +3398,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
@@ -3527,6 +3707,26 @@ Example: Requesting to switch to code mode
 <reason>Need to make code changes</reason>
 </switch_mode>
 
+## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+
+
 # Tool Use Guidelines
 
 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.

+ 2 - 0
src/core/prompts/tools/index.ts

@@ -12,6 +12,7 @@ import { getAttemptCompletionDescription } from "./attempt-completion"
 import { getUseMcpToolDescription } from "./use-mcp-tool"
 import { getAccessMcpResourceDescription } from "./access-mcp-resource"
 import { getSwitchModeDescription } from "./switch-mode"
+import { getNewTaskDescription } from "./new-task"
 import { DiffStrategy } from "../../diff/DiffStrategy"
 import { McpHub } from "../../../services/mcp/McpHub"
 import { Mode, ModeConfig, getModeConfig, isToolAllowedForMode, getGroupName } from "../../../shared/modes"
@@ -32,6 +33,7 @@ const toolDescriptionMap: Record<string, (args: ToolArgs) => string | undefined>
 	use_mcp_tool: (args) => getUseMcpToolDescription(args),
 	access_mcp_resource: (args) => getAccessMcpResourceDescription(args),
 	switch_mode: () => getSwitchModeDescription(),
+	new_task: (args) => getNewTaskDescription(args),
 	insert_content: (args) => getInsertContentDescription(args),
 	search_and_replace: (args) => getSearchAndReplaceDescription(args),
 	apply_diff: (args) =>

+ 23 - 0
src/core/prompts/tools/new-task.ts

@@ -0,0 +1,23 @@
+import { ToolArgs } from "./types"
+
+export function getNewTaskDescription(args: ToolArgs): string {
+	return `## new_task
+Description: Create a new task with a specified starting mode and initial message. This tool instructs the system to create a new Cline instance in the given mode with the provided message.
+
+Parameters:
+- mode: (required) The slug of the mode to start the new task in (e.g., "code", "ask", "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>
+`
+}

+ 1 - 1
src/core/webview/ClineProvider.ts

@@ -2180,7 +2180,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 			this.getGlobalState("autoApprovalEnabled") as Promise<boolean | undefined>,
 			this.customModesManager.getCustomModes(),
 			this.getGlobalState("experiments") as Promise<Record<ExperimentId, boolean> | undefined>,
-      this.getSecret("unboundApiKey") as Promise<string | undefined>,
+			this.getSecret("unboundApiKey") as Promise<string | undefined>,
 			this.getGlobalState("unboundModelId") as Promise<string | undefined>,
 		])
 

+ 3 - 0
src/shared/ExtensionMessage.ts

@@ -159,6 +159,8 @@ export type ClineSay =
 	| "command"
 	| "mcp_server_request_started"
 	| "mcp_server_response"
+	| "new_task_started"
+	| "new_task"
 
 export interface ClineSayTool {
 	tool:
@@ -171,6 +173,7 @@ export interface ClineSayTool {
 		| "listCodeDefinitionNames"
 		| "searchFiles"
 		| "switchMode"
+		| "newTask"
 	path?: string
 	diff?: string
 	content?: string

+ 8 - 1
src/shared/tool-groups.ts

@@ -16,6 +16,7 @@ export const TOOL_DISPLAY_NAMES = {
 	ask_followup_question: "ask questions",
 	attempt_completion: "complete tasks",
 	switch_mode: "switch modes",
+	new_task: "create new task",
 } as const
 
 // Define available tool groups
@@ -25,12 +26,18 @@ export const TOOL_GROUPS: Record<string, ToolGroupValues> = {
 	browser: ["browser_action"],
 	command: ["execute_command"],
 	mcp: ["use_mcp_tool", "access_mcp_resource"],
+	modes: ["switch_mode", "new_task"],
 }
 
 export type ToolGroup = keyof typeof TOOL_GROUPS
 
 // Tools that are always available to all modes
-export const ALWAYS_AVAILABLE_TOOLS = ["ask_followup_question", "attempt_completion", "switch_mode"] as const
+export const ALWAYS_AVAILABLE_TOOLS = [
+	"ask_followup_question",
+	"attempt_completion",
+	"switch_mode",
+	"new_task",
+] as const
 
 // Tool name types for type safety
 export type ToolName = keyof typeof TOOL_DISPLAY_NAMES

+ 3 - 2
webview-ui/src/components/chat/AutoApproveMenu.tsx

@@ -75,10 +75,11 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
 		},
 		{
 			id: "switchModes",
-			label: "Switch between modes",
+			label: "Switch modes & create tasks",
 			shortName: "Modes",
 			enabled: alwaysAllowModeSwitch ?? false,
-			description: "Allows automatic switching between different AI modes without requiring approval.",
+			description:
+				"Allows automatic switching between different AI modes and creating new tasks without requiring approval.",
 		},
 		{
 			id: "retryRequests",

+ 14 - 0
webview-ui/src/components/chat/ChatRow.tsx

@@ -473,6 +473,20 @@ export const ChatRowContent = ({
 						</div>
 					</>
 				)
+			case "newTask":
+				return (
+					<>
+						<div style={headerStyle}>
+							{toolIcon("new-file")}
+							<span style={{ fontWeight: "bold" }}>
+								Roo wants to create a new task in <code>{tool.mode}</code> mode:
+							</span>
+						</div>
+						<div style={{ paddingLeft: "26px", marginTop: "4px" }}>
+							<code>{tool.content}</code>
+						</div>
+					</>
+				)
 			default:
 				return null
 		}

+ 2 - 1
webview-ui/src/components/chat/ChatView.tsx

@@ -569,7 +569,8 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
 				(alwaysAllowMcp && message.ask === "use_mcp_server" && isMcpToolAlwaysAllowed(message)) ||
 				(alwaysAllowModeSwitch &&
 					message.ask === "tool" &&
-					JSON.parse(message.text || "{}")?.tool === "switchMode")
+					(JSON.parse(message.text || "{}")?.tool === "switchMode" ||
+						JSON.parse(message.text || "{}")?.tool === "newTask"))
 			)
 		},
 		[

+ 3 - 2
webview-ui/src/components/settings/SettingsView.tsx

@@ -344,10 +344,11 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
 						<VSCodeCheckbox
 							checked={alwaysAllowModeSwitch}
 							onChange={(e: any) => setAlwaysAllowModeSwitch(e.target.checked)}>
-							<span style={{ fontWeight: "500" }}>Always approve mode switching</span>
+							<span style={{ fontWeight: "500" }}>Always approve mode switching & task creation</span>
 						</VSCodeCheckbox>
 						<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
-							Automatically switch between different AI modes without requiring approval
+							Automatically switch between different AI modes and create new tasks without requiring
+							approval
 						</p>
 					</div>