Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit d43eca9

Browse files
committed
fix: add cancel confirmation, panel scroll constraint, and Phase 6 extension-point comments
1 parent 15f4be4 commit d43eca9

3 files changed

Lines changed: 53 additions & 9 deletions

File tree

src/core/task/BackgroundTaskRunner.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88
* - Are not added to the clineStack
99
*
1010
* This is Phase 4 of the parallel execution roadmap: Background Read-Only Concurrency.
11+
*
12+
* Phase 6+ extension points:
13+
* - To support write-capable background tasks, extend BACKGROUND_TASK_ALLOWED_TOOLS
14+
* and add a file-locking mechanism to prevent conflicts with foreground edits.
15+
* - For real-time progress streaming, add an `onProgressUpdate` callback to
16+
* BackgroundTaskInfo and emit partial tool-call summaries from Task.
17+
* - For persistent history across sessions, serialize completedTasks to global
18+
* state via the TaskHistoryStore and restore on provider initialization.
19+
* - For tab-based switching, expose the background task's clineMessages via
20+
* getTasksStatus() so the webview can render a full conversation view.
1121
*/
1222

1323
import { BackgroundTaskStatusInfo } from "@roo-code/types"

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

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useMemo } from "react"
1+
import React, { useState, useCallback, useMemo } from "react"
22

33
import type { BackgroundTaskStatusInfo } from "@roo-code/types"
44

@@ -69,11 +69,20 @@ function getStatusColor(status: BackgroundTaskStatusInfo["status"]): string {
6969

7070
function BackgroundTaskItem({ task }: { task: BackgroundTaskStatusInfo }) {
7171
const [showResult, setShowResult] = useState(false)
72+
const [confirmingCancel, setConfirmingCancel] = useState(false)
7273
const isRunning = task.status === "running"
7374

74-
const handleCancel = () => {
75+
const handleCancelClick = useCallback(() => {
76+
if (!confirmingCancel) {
77+
setConfirmingCancel(true)
78+
// Auto-reset after 3 seconds if user doesn't confirm
79+
setTimeout(() => setConfirmingCancel(false), 3000)
80+
return
81+
}
82+
// Second click confirms cancellation
83+
setConfirmingCancel(false)
7584
vscode.postMessage({ type: "cancelBackgroundTask", taskId: task.taskId })
76-
}
85+
}, [confirmingCancel, task.taskId])
7786

7887
const shortId = task.taskId.slice(0, 8)
7988

@@ -102,10 +111,18 @@ function BackgroundTaskItem({ task }: { task: BackgroundTaskStatusInfo }) {
102111
)}
103112
{isRunning && (
104113
<button
105-
className="text-xs text-vscode-errorForeground hover:opacity-80 cursor-pointer bg-transparent border-none p-0 flex items-center gap-0.5"
106-
onClick={handleCancel}
107-
title="Cancel background task">
108-
<span className="codicon codicon-stop-circle text-xs" />
114+
className={`text-xs cursor-pointer bg-transparent border-none p-0 flex items-center gap-0.5 ${
115+
confirmingCancel
116+
? "text-vscode-errorForeground font-medium"
117+
: "text-vscode-errorForeground hover:opacity-80"
118+
}`}
119+
onClick={handleCancelClick}
120+
title={confirmingCancel ? "Click again to confirm cancellation" : "Cancel background task"}>
121+
{confirmingCancel ? (
122+
<span>Cancel?</span>
123+
) : (
124+
<span className="codicon codicon-stop-circle text-xs" />
125+
)}
109126
</button>
110127
)}
111128
</div>
@@ -123,6 +140,16 @@ function BackgroundTaskItem({ task }: { task: BackgroundTaskStatusInfo }) {
123140
* BackgroundTasksPanel shows active and recently completed background tasks
124141
* as a collapsible section in the chat sidebar. Only renders when there are
125142
* background tasks to display.
143+
*
144+
* Phase 6+ evolution notes:
145+
* - This panel can be promoted to a tab-based view alongside the main chat
146+
* by extracting the task list into a shared component and rendering it in
147+
* both the sidebar panel and a dedicated "Background Tasks" tab.
148+
* - For real-time progress streaming, each BackgroundTaskItem could accept
149+
* a `progressMessages` prop with the last N tool-call summaries.
150+
* - For conversation replay, clicking a completed task could open its full
151+
* message history in a read-only chat view (reuse ChatView with a
152+
* `readOnly` flag and the task's clineMessages).
126153
*/
127154
const BackgroundTasksPanel: React.FC = () => {
128155
const { backgroundTasks } = useExtensionState()
@@ -155,7 +182,7 @@ const BackgroundTasksPanel: React.FC = () => {
155182
<span className="text-[10px] text-vscode-descriptionForeground">{tasks.length} total</span>
156183
</button>
157184
{!isCollapsed && (
158-
<div className="px-2 pb-1.5">
185+
<div className="px-2 pb-1.5 max-h-[200px] overflow-y-auto">
159186
{tasks.map((task) => (
160187
<BackgroundTaskItem key={task.taskId} task={task} />
161188
))}

webview-ui/src/components/chat/__tests__/BackgroundTasksPanel.spec.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ describe("BackgroundTasksPanel", () => {
8080
expect(cancelButton).toBeDefined()
8181
})
8282

83-
it("should send cancelBackgroundTask message when cancel is clicked", () => {
83+
it("should require two clicks to cancel (confirmation pattern)", () => {
8484
mockBackgroundTasks.push({
8585
taskId: "task-cancel-me",
8686
parentTaskId: "parent-1",
@@ -90,8 +90,15 @@ describe("BackgroundTasksPanel", () => {
9090

9191
render(<BackgroundTasksPanel />)
9292
const cancelButton = screen.getByTitle("Cancel background task")
93+
94+
// First click shows confirmation text, does NOT send message
9395
fireEvent.click(cancelButton)
96+
expect(vscode.postMessage).not.toHaveBeenCalled()
97+
expect(screen.getByText("Cancel?")).toBeDefined()
9498

99+
// Second click confirms and sends the cancel message
100+
const confirmButton = screen.getByTitle("Click again to confirm cancellation")
101+
fireEvent.click(confirmButton)
95102
expect(vscode.postMessage).toHaveBeenCalledWith({
96103
type: "cancelBackgroundTask",
97104
taskId: "task-cancel-me",

0 commit comments

Comments
 (0)