Skip to content

Commit 1456db9

Browse files
author
ShayBC
committed
added approve finish task button and auto approve button for subtasks
1 parent b761c24 commit 1456db9

File tree

7 files changed

+62
-3
lines changed

7 files changed

+62
-3
lines changed

src/core/Cline.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,18 @@ export class Cline {
14141414
return true
14151415
}
14161416

1417+
const askFinishSubTaskApproval = async () => {
1418+
// ask the user to approve this task has completed, and he has reviewd it, and we can declare task is finished
1419+
// and return control to the parent task to continue running the rest of the sub-tasks
1420+
const toolMessage = JSON.stringify({
1421+
tool: "finishTask",
1422+
content:
1423+
"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.",
1424+
})
1425+
1426+
return await askApproval("tool", toolMessage)
1427+
}
1428+
14171429
const handleError = async (action: string, error: Error) => {
14181430
const errorString = `Error ${action}: ${JSON.stringify(serializeError(error))}`
14191431
await this.say(
@@ -2941,8 +2953,13 @@ export class Cline {
29412953
if (lastMessage && lastMessage.ask !== "command") {
29422954
// havent sent a command message yet so first send completion_result then command
29432955
await this.say("completion_result", result, undefined, false)
2944-
telemetryService.captureTaskCompleted(this.taskId)
2956+
// telemetryService.captureTaskCompleted(this.taskId)
29452957
if (this.isSubTask) {
2958+
const didApprove = await askFinishSubTaskApproval()
2959+
if (!didApprove) {
2960+
break
2961+
}
2962+
29462963
// tell the provider to remove the current subtask and resume the previous task in the stack
29472964
await this.providerRef
29482965
.deref()
@@ -2966,8 +2983,13 @@ export class Cline {
29662983
commandResult = execCommandResult
29672984
} else {
29682985
await this.say("completion_result", result, undefined, false)
2969-
telemetryService.captureTaskCompleted(this.taskId)
2986+
// telemetryService.captureTaskCompleted(this.taskId)
29702987
if (this.isSubTask) {
2988+
const didApprove = await askFinishSubTaskApproval()
2989+
if (!didApprove) {
2990+
break
2991+
}
2992+
29712993
// tell the provider to remove the current subtask and resume the previous task in the stack
29722994
await this.providerRef
29732995
.deref()

src/shared/ExtensionMessage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export interface ExtensionState {
109109
alwaysAllowMcp?: boolean
110110
alwaysApproveResubmit?: boolean
111111
alwaysAllowModeSwitch?: boolean
112+
alwaysAllowFinishTask?: boolean
112113
browserToolEnabled?: boolean
113114
requestDelaySeconds: number
114115
rateLimitSeconds: number // Minimum time between successive requests (0 = disabled)
@@ -168,6 +169,7 @@ export type ClineAsk =
168169
| "mistake_limit_reached"
169170
| "browser_action_launch"
170171
| "use_mcp_server"
172+
| "finishTask"
171173

172174
export type ClineSay =
173175
| "task"
@@ -207,6 +209,7 @@ export interface ClineSayTool {
207209
| "searchFiles"
208210
| "switchMode"
209211
| "newTask"
212+
| "finishTask"
210213
path?: string
211214
diff?: string
212215
content?: string

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface WebviewMessage {
4848
| "alwaysAllowBrowser"
4949
| "alwaysAllowMcp"
5050
| "alwaysAllowModeSwitch"
51+
| "alwaysAllowFinishTask"
5152
| "playSound"
5253
| "soundEnabled"
5354
| "soundVolume"

webview-ui/src/components/chat/AutoApproveMenu.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
3030
setAlwaysAllowMcp,
3131
alwaysAllowModeSwitch,
3232
setAlwaysAllowModeSwitch,
33+
alwaysAllowFinishTask,
34+
setAlwaysAllowFinishTask,
3335
alwaysApproveResubmit,
3436
setAlwaysApproveResubmit,
3537
autoApprovalEnabled,
@@ -81,6 +83,13 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
8183
description:
8284
"Allows automatic switching between different AI modes and creating new tasks without requiring approval.",
8385
},
86+
{
87+
id: "finishTask",
88+
label: "Finish subtasks tasks",
89+
shortName: "Finish",
90+
enabled: alwaysAllowFinishTask ?? false,
91+
description: "Allows automatic completeing a sub-task without requiring user review or approval.",
92+
},
8493
{
8594
id: "retryRequests",
8695
label: "Retry failed requests",
@@ -136,6 +145,12 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
136145
vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: newValue })
137146
}, [alwaysAllowModeSwitch, setAlwaysAllowModeSwitch])
138147

148+
const handleFinishTaskChange = useCallback(() => {
149+
const newValue = !(alwaysAllowFinishTask ?? false)
150+
setAlwaysAllowFinishTask(newValue)
151+
vscode.postMessage({ type: "alwaysAllowFinishTask", bool: newValue })
152+
}, [alwaysAllowFinishTask, setAlwaysAllowFinishTask])
153+
139154
const handleRetryChange = useCallback(() => {
140155
const newValue = !(alwaysApproveResubmit ?? false)
141156
setAlwaysApproveResubmit(newValue)
@@ -150,6 +165,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
150165
useBrowser: handleBrowserChange,
151166
useMcp: handleMcpChange,
152167
switchModes: handleModeSwitchChange,
168+
finishTask: handleFinishTaskChange,
153169
retryRequests: handleRetryChange,
154170
}
155171

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,18 @@ export const ChatRowContent = ({
459459
</div>
460460
</>
461461
)
462+
case "finishTask":
463+
return (
464+
<>
465+
<div style={headerStyle}>
466+
{toolIcon("new-file")}
467+
<span style={{ fontWeight: "bold" }}>Roo wants to finish this task</span>
468+
</div>
469+
<div style={{ paddingLeft: "26px", marginTop: "4px" }}>
470+
<code>{tool.content}</code>
471+
</div>
472+
</>
473+
)
462474
default:
463475
return null
464476
}

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
6161
setMode,
6262
autoApprovalEnabled,
6363
alwaysAllowModeSwitch,
64+
alwaysAllowFinishTask,
6465
customModes,
6566
telemetrySetting,
6667
} = useExtensionState()
@@ -642,7 +643,8 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
642643
(alwaysAllowModeSwitch &&
643644
message.ask === "tool" &&
644645
(JSON.parse(message.text || "{}")?.tool === "switchMode" ||
645-
JSON.parse(message.text || "{}")?.tool === "newTask"))
646+
JSON.parse(message.text || "{}")?.tool === "newTask")) ||
647+
(alwaysAllowFinishTask && message.ask === "finishTask")
646648
)
647649
},
648650
[
@@ -657,6 +659,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
657659
alwaysAllowMcp,
658660
isMcpToolAlwaysAllowed,
659661
alwaysAllowModeSwitch,
662+
alwaysAllowFinishTask,
660663
],
661664
)
662665

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface ExtensionStateContextType extends ExtensionState {
3131
setAlwaysAllowBrowser: (value: boolean) => void
3232
setAlwaysAllowMcp: (value: boolean) => void
3333
setAlwaysAllowModeSwitch: (value: boolean) => void
34+
setAlwaysAllowFinishTask: (value: boolean) => void
3435
setBrowserToolEnabled: (value: boolean) => void
3536
setShowRooIgnoredFiles: (value: boolean) => void
3637
setShowAnnouncement: (value: boolean) => void
@@ -247,6 +248,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
247248
setAlwaysAllowBrowser: (value) => setState((prevState) => ({ ...prevState, alwaysAllowBrowser: value })),
248249
setAlwaysAllowMcp: (value) => setState((prevState) => ({ ...prevState, alwaysAllowMcp: value })),
249250
setAlwaysAllowModeSwitch: (value) => setState((prevState) => ({ ...prevState, alwaysAllowModeSwitch: value })),
251+
setAlwaysAllowFinishTask: (value) => setState((prevState) => ({ ...prevState, alwaysAllowFinishTask: value })),
250252
setShowAnnouncement: (value) => setState((prevState) => ({ ...prevState, shouldShowAnnouncement: value })),
251253
setAllowedCommands: (value) => setState((prevState) => ({ ...prevState, allowedCommands: value })),
252254
setSoundEnabled: (value) => setState((prevState) => ({ ...prevState, soundEnabled: value })),

0 commit comments

Comments
 (0)