Procházet zdrojové kódy

Merge pull request #1505 from RooVetGit/v3.8.2

V3.8.2
Matt Rubens před 9 měsíci
rodič
revize
c992552241

+ 5 - 0
.changeset/modern-pillows-visit.md

@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+v3.8.2

+ 1 - 1
src/core/Cline.ts

@@ -1431,7 +1431,7 @@ export class Cline {
 					const toolMessage = JSON.stringify({
 						tool: "finishTask",
 						content:
-							"Task completed! You can review the results and suggest any corrections or next steps. If everything looks good, confirm to continue with the next task.",
+							"Subtask completed! You can review the results and suggest any corrections or next steps. If everything looks good, confirm to return the result to the parent task.",
 					})
 
 					return await askApproval("tool", toolMessage)

+ 7 - 5
src/core/diff/strategies/multi-search-replace.ts

@@ -368,18 +368,20 @@ Only use a single line of '=======' between search and replacement content, beca
 	getProgressStatus(toolUse: ToolUse, result?: DiffResult): ToolProgressStatus {
 		const diffContent = toolUse.params.diff
 		if (diffContent) {
+			const icon = "diff-multiple"
+			const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
 			if (toolUse.partial) {
 				if (diffContent.length < 1000 || (diffContent.length / 50) % 10 === 0) {
-					return { text: `progressing ${(diffContent.match(/SEARCH/g) || []).length} blocks...` }
+					return { icon, text: `${searchBlockCount}` }
 				}
 			} else if (result) {
-				const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
-				if (result.failParts) {
+				if (result.failParts?.length) {
 					return {
-						text: `progressed ${searchBlockCount - result.failParts.length}/${searchBlockCount} blocks.`,
+						icon,
+						text: `${searchBlockCount - result.failParts.length}/${searchBlockCount}`,
 					}
 				} else {
-					return { text: `progressed ${searchBlockCount} blocks.` }
+					return { icon, text: `${searchBlockCount}` }
 				}
 			}
 		}

+ 6 - 8
src/core/webview/ClineProvider.ts

@@ -984,8 +984,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 						await this.updateGlobalState("alwaysAllowModeSwitch", message.bool)
 						await this.postStateToWebview()
 						break
-					case "alwaysAllowFinishTask":
-						await this.updateGlobalState("alwaysAllowFinishTask", message.bool)
+					case "alwaysAllowSubtasks":
+						await this.updateGlobalState("alwaysAllowSubtasks", message.bool)
 						await this.postStateToWebview()
 						break
 					case "askResponse":
@@ -997,9 +997,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 						break
 					case "clearTask":
 						// clear task resets the current session and allows for a new task to be started, if this session is a subtask - it allows the parent task to be resumed
-						await this.finishSubTask(
-							`new_task finished with an error!, it was stopped and canceled by the user.`,
-						)
+						await this.finishSubTask(`Task error: It was stopped and canceled by the user.`)
 						await this.postStateToWebview()
 						break
 					case "didShowAnnouncement":
@@ -2181,7 +2179,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 			alwaysAllowBrowser,
 			alwaysAllowMcp,
 			alwaysAllowModeSwitch,
-			alwaysAllowFinishTask,
+			alwaysAllowSubtasks,
 			soundEnabled,
 			diffEnabled,
 			enableCheckpoints,
@@ -2229,7 +2227,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 			alwaysAllowBrowser: alwaysAllowBrowser ?? false,
 			alwaysAllowMcp: alwaysAllowMcp ?? false,
 			alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false,
-			alwaysAllowFinishTask: alwaysAllowFinishTask ?? false,
+			alwaysAllowSubtasks: alwaysAllowSubtasks ?? false,
 			uriScheme: vscode.env.uriScheme,
 			currentTaskItem: this.getCurrentCline()?.taskId
 				? (taskHistory || []).find((item: HistoryItem) => item.id === this.getCurrentCline()?.taskId)
@@ -2391,7 +2389,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 			alwaysAllowBrowser: stateValues.alwaysAllowBrowser ?? false,
 			alwaysAllowMcp: stateValues.alwaysAllowMcp ?? false,
 			alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false,
-			alwaysAllowFinishTask: stateValues.alwaysAllowFinishTask ?? false,
+			alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? false,
 			taskHistory: stateValues.taskHistory,
 			allowedCommands: stateValues.allowedCommands,
 			soundEnabled: stateValues.soundEnabled ?? false,

+ 2 - 1
src/shared/ExtensionMessage.ts

@@ -109,7 +109,7 @@ export interface ExtensionState {
 	alwaysAllowMcp?: boolean
 	alwaysApproveResubmit?: boolean
 	alwaysAllowModeSwitch?: boolean
-	alwaysAllowFinishTask?: boolean
+	alwaysAllowSubtasks?: boolean
 	browserToolEnabled?: boolean
 	requestDelaySeconds: number
 	rateLimitSeconds: number // Minimum time between successive requests (0 = disabled)
@@ -277,5 +277,6 @@ export interface HumanRelayCancelMessage {
 export type ClineApiReqCancelReason = "streaming_failed" | "user_cancelled"
 
 export type ToolProgressStatus = {
+	icon?: string
 	text?: string
 }

+ 1 - 1
src/shared/WebviewMessage.ts

@@ -48,7 +48,7 @@ export interface WebviewMessage {
 		| "alwaysAllowBrowser"
 		| "alwaysAllowMcp"
 		| "alwaysAllowModeSwitch"
-		| "alwaysAllowFinishTask"
+		| "alwaysAllowSubtasks"
 		| "playSound"
 		| "soundEnabled"
 		| "soundVolume"

+ 1 - 1
src/shared/globalState.ts

@@ -40,7 +40,7 @@ export const GLOBAL_STATE_KEYS = [
 	"alwaysAllowBrowser",
 	"alwaysAllowMcp",
 	"alwaysAllowModeSwitch",
-	"alwaysAllowFinishTask",
+	"alwaysAllowSubtasks",
 	"taskHistory",
 	"openAiBaseUrl",
 	"openAiModelId",

+ 15 - 16
webview-ui/src/components/chat/AutoApproveMenu.tsx

@@ -30,8 +30,8 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
 		setAlwaysAllowMcp,
 		alwaysAllowModeSwitch,
 		setAlwaysAllowModeSwitch,
-		alwaysAllowFinishTask,
-		setAlwaysAllowFinishTask,
+		alwaysAllowSubtasks,
+		setAlwaysAllowSubtasks,
 		alwaysApproveResubmit,
 		setAlwaysApproveResubmit,
 		autoApprovalEnabled,
@@ -77,18 +77,17 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
 		},
 		{
 			id: "switchModes",
-			label: "Switch modes & create tasks",
+			label: "Switch modes",
 			shortName: "Modes",
 			enabled: alwaysAllowModeSwitch ?? false,
-			description:
-				"Allows automatic switching between different AI modes and creating new tasks without requiring approval.",
+			description: "Allows automatic switching between different modes without requiring approval.",
 		},
 		{
-			id: "finishTask",
-			label: "Continue to next task",
-			shortName: "Continue",
-			enabled: alwaysAllowFinishTask ?? false,
-			description: "Allow tasks to end execution and continue to the next task, without user review or approval.",
+			id: "subtasks",
+			label: "Create & complete subtasks",
+			shortName: "Subtasks",
+			enabled: alwaysAllowSubtasks ?? false,
+			description: "Allow creation and completion of subtasks without requiring approval.",
 		},
 		{
 			id: "retryRequests",
@@ -145,11 +144,11 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
 		vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: newValue })
 	}, [alwaysAllowModeSwitch, setAlwaysAllowModeSwitch])
 
-	const handleFinishTaskChange = useCallback(() => {
-		const newValue = !(alwaysAllowFinishTask ?? false)
-		setAlwaysAllowFinishTask(newValue)
-		vscode.postMessage({ type: "alwaysAllowFinishTask", bool: newValue })
-	}, [alwaysAllowFinishTask, setAlwaysAllowFinishTask])
+	const handleSubtasksChange = useCallback(() => {
+		const newValue = !(alwaysAllowSubtasks ?? false)
+		setAlwaysAllowSubtasks(newValue)
+		vscode.postMessage({ type: "alwaysAllowSubtasks", bool: newValue })
+	}, [alwaysAllowSubtasks, setAlwaysAllowSubtasks])
 
 	const handleRetryChange = useCallback(() => {
 		const newValue = !(alwaysApproveResubmit ?? false)
@@ -165,7 +164,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
 		useBrowser: handleBrowserChange,
 		useMcp: handleMcpChange,
 		switchModes: handleModeSwitchChange,
-		finishTask: handleFinishTaskChange,
+		subtasks: handleSubtasksChange,
 		retryRequests: handleRetryChange,
 	}
 

+ 3 - 3
webview-ui/src/components/chat/ChatRow.tsx

@@ -452,7 +452,7 @@ export const ChatRowContent = ({
 						<div style={headerStyle}>
 							{toolIcon("new-file")}
 							<span style={{ fontWeight: "bold" }}>
-								Roo wants to create a new task in <code>{tool.mode}</code> mode:
+								Roo wants to create a new subtask in <code>{tool.mode}</code> mode:
 							</span>
 						</div>
 						<div style={{ paddingLeft: "26px", marginTop: "4px" }}>
@@ -464,8 +464,8 @@ export const ChatRowContent = ({
 				return (
 					<>
 						<div style={headerStyle}>
-							{toolIcon("new-file")}
-							<span style={{ fontWeight: "bold" }}>Roo wants to finish this task</span>
+							{toolIcon("checklist")}
+							<span style={{ fontWeight: "bold" }}>Roo wants to finish this subtask</span>
 						</div>
 						<div style={{ paddingLeft: "26px", marginTop: "4px" }}>
 							<code>{tool.content}</code>

+ 6 - 7
webview-ui/src/components/chat/ChatView.tsx

@@ -61,7 +61,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
 		setMode,
 		autoApprovalEnabled,
 		alwaysAllowModeSwitch,
-		alwaysAllowFinishTask,
+		alwaysAllowSubtasks,
 		customModes,
 		telemetrySetting,
 	} = useExtensionState()
@@ -150,7 +150,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
 									setSecondaryButtonText("Reject")
 									break
 								case "finishTask":
-									setPrimaryButtonText("Approve & Continue to the next Task")
+									setPrimaryButtonText("Complete Subtask and Return")
 									setSecondaryButtonText(undefined)
 									break
 								default:
@@ -646,11 +646,10 @@ 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 === "newTask")) ||
-				(alwaysAllowFinishTask &&
+					JSON.parse(message.text || "{}")?.tool === "switchMode") ||
+				(alwaysAllowSubtasks &&
 					message.ask === "tool" &&
-					JSON.parse(message.text || "{}")?.tool === "finishTask")
+					["newTask", "finishTask"].includes(JSON.parse(message.text || "{}")?.tool))
 			)
 		},
 		[
@@ -665,7 +664,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
 			alwaysAllowMcp,
 			isMcpToolAlwaysAllowed,
 			alwaysAllowModeSwitch,
-			alwaysAllowFinishTask,
+			alwaysAllowSubtasks,
 		],
 	)
 

+ 6 - 8
webview-ui/src/components/common/CodeAccordian.tsx

@@ -99,14 +99,12 @@ const CodeAccordian = ({
 					)}
 					<div style={{ flexGrow: 1 }}></div>
 					{progressStatus && progressStatus.text && (
-						<span
-							style={{
-								color: "var(--vscode-descriptionForeground)",
-								borderTop: isExpanded ? "1px solid var(--vscode-editorGroup-border)" : "none",
-								marginLeft: "auto", // Right-align the text
-							}}>
-							{progressStatus.text}
-						</span>
+						<>
+							{progressStatus.icon && <span className={`codicon codicon-${progressStatus.icon} mr-1`} />}
+							<span className="mr-1 ml-auto text-vscode-descriptionForeground">
+								{progressStatus.text}
+							</span>
+						</>
 					)}
 					<span className={`codicon codicon-chevron-${isExpanded ? "up" : "down"}`}></span>
 				</div>

+ 8 - 9
webview-ui/src/components/settings/AutoApproveSettings.tsx

@@ -18,7 +18,7 @@ type AutoApproveSettingsProps = HTMLAttributes<HTMLDivElement> & {
 	requestDelaySeconds: number
 	alwaysAllowMcp?: boolean
 	alwaysAllowModeSwitch?: boolean
-	alwaysAllowFinishTask?: boolean
+	alwaysAllowSubtasks?: boolean
 	alwaysAllowExecute?: boolean
 	allowedCommands?: string[]
 	setCachedStateField: SetCachedStateField<keyof ExtensionStateContextType>
@@ -33,7 +33,7 @@ export const AutoApproveSettings = ({
 	requestDelaySeconds,
 	alwaysAllowMcp,
 	alwaysAllowModeSwitch,
-	alwaysAllowFinishTask,
+	alwaysAllowSubtasks,
 	alwaysAllowExecute,
 	allowedCommands,
 	setCachedStateField,
@@ -175,22 +175,21 @@ export const AutoApproveSettings = ({
 					<VSCodeCheckbox
 						checked={alwaysAllowModeSwitch}
 						onChange={(e: any) => setCachedStateField("alwaysAllowModeSwitch", e.target.checked)}>
-						<span className="font-medium">Always approve mode switching & task creation</span>
+						<span className="font-medium">Always approve mode switching</span>
 					</VSCodeCheckbox>
 					<p className="text-vscode-descriptionForeground text-sm mt-0">
-						Automatically switch between different AI modes and create new tasks without requiring approval
+						Automatically switch between different modes without requiring approval
 					</p>
 				</div>
 
 				<div>
 					<VSCodeCheckbox
-						checked={alwaysAllowFinishTask}
-						onChange={(e: any) => setCachedStateField("alwaysAllowFinishTask", e.target.checked)}>
-						<span className="font-medium">Always approve finish & continue to next task</span>
+						checked={alwaysAllowSubtasks}
+						onChange={(e: any) => setCachedStateField("alwaysAllowSubtasks", e.target.checked)}>
+						<span className="font-medium">Always approve creation & completion of subtasks</span>
 					</VSCodeCheckbox>
 					<p className="text-vscode-descriptionForeground text-sm mt-0">
-						Automatically approve tasks to finish execution and continue to the next task, without user
-						review or approval
+						Allow creation and completion of subtasks without requiring approval
 					</p>
 				</div>
 

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

@@ -63,7 +63,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
 		alwaysAllowExecute,
 		alwaysAllowMcp,
 		alwaysAllowModeSwitch,
-		alwaysAllowFinishTask,
+		alwaysAllowSubtasks,
 		alwaysAllowWrite,
 		alwaysApproveResubmit,
 		browserToolEnabled,
@@ -185,7 +185,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
 			vscode.postMessage({ type: "currentApiConfigName", text: currentApiConfigName })
 			vscode.postMessage({ type: "updateExperimental", values: experiments })
 			vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: alwaysAllowModeSwitch })
-			vscode.postMessage({ type: "alwaysAllowFinishTask", bool: alwaysAllowFinishTask })
+			vscode.postMessage({ type: "alwaysAllowSubtasks", bool: alwaysAllowSubtasks })
 			vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration })
 			vscode.postMessage({ type: "telemetrySetting", text: telemetrySetting })
 			setChangeDetected(false)
@@ -366,7 +366,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
 						requestDelaySeconds={requestDelaySeconds}
 						alwaysAllowMcp={alwaysAllowMcp}
 						alwaysAllowModeSwitch={alwaysAllowModeSwitch}
-						alwaysAllowFinishTask={alwaysAllowFinishTask}
+						alwaysAllowSubtasks={alwaysAllowSubtasks}
 						alwaysAllowExecute={alwaysAllowExecute}
 						allowedCommands={allowedCommands}
 						setCachedStateField={setCachedStateField}

+ 2 - 2
webview-ui/src/context/ExtensionStateContext.tsx

@@ -31,7 +31,7 @@ export interface ExtensionStateContextType extends ExtensionState {
 	setAlwaysAllowBrowser: (value: boolean) => void
 	setAlwaysAllowMcp: (value: boolean) => void
 	setAlwaysAllowModeSwitch: (value: boolean) => void
-	setAlwaysAllowFinishTask: (value: boolean) => void
+	setAlwaysAllowSubtasks: (value: boolean) => void
 	setBrowserToolEnabled: (value: boolean) => void
 	setShowRooIgnoredFiles: (value: boolean) => void
 	setShowAnnouncement: (value: boolean) => void
@@ -248,7 +248,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
 		setAlwaysAllowBrowser: (value) => setState((prevState) => ({ ...prevState, alwaysAllowBrowser: value })),
 		setAlwaysAllowMcp: (value) => setState((prevState) => ({ ...prevState, alwaysAllowMcp: value })),
 		setAlwaysAllowModeSwitch: (value) => setState((prevState) => ({ ...prevState, alwaysAllowModeSwitch: value })),
-		setAlwaysAllowFinishTask: (value) => setState((prevState) => ({ ...prevState, alwaysAllowFinishTask: value })),
+		setAlwaysAllowSubtasks: (value) => setState((prevState) => ({ ...prevState, alwaysAllowSubtasks: value })),
 		setShowAnnouncement: (value) => setState((prevState) => ({ ...prevState, shouldShowAnnouncement: value })),
 		setAllowedCommands: (value) => setState((prevState) => ({ ...prevState, allowedCommands: value })),
 		setSoundEnabled: (value) => setState((prevState) => ({ ...prevState, soundEnabled: value })),