Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1588,8 +1588,24 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
}
}

async handleTerminalOperation(terminalOperation: "continue" | "abort") {
/**
* Handle terminal operations (continue/abort) with optional user message.
*
* When the user sends a message while a command is running (command_output ask),
* we need to both continue the terminal AND resolve the pending ask with the
* user's message. This prevents the UI from hanging.
*
* @param terminalOperation - "continue" to proceed or "abort" to kill the command
* @param text - Optional user message text
* @param images - Optional user message images
*/
async handleTerminalOperation(terminalOperation: "continue" | "abort", text?: string, images?: string[]) {
if (terminalOperation === "continue") {
// If user provided a message, resolve the pending ask with their message
// This allows the user to provide feedback while the command runs
if (text || (images && images.length > 0)) {
this.handleWebviewAskResponse("messageResponse", text, images)
}
this.terminalProcess?.continue()
} else if (terminalOperation === "abort") {
this.terminalProcess?.abort()
Expand Down
6 changes: 5 additions & 1 deletion src/core/webview/webviewMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,11 @@ export const webviewMessageHandler = async (

case "terminalOperation":
if (message.terminalOperation) {
provider.getCurrentTask()?.handleTerminalOperation(message.terminalOperation)
// Pass text/images if user sent a message with the terminal operation
// This allows the user to provide additional context when continuing
// a long-running command
const resolved = await resolveIncomingImages({ text: message.text, images: message.images })
provider.getCurrentTask()?.handleTerminalOperation(message.terminalOperation, resolved.text, resolved.images)
}
break
case "clearTask":
Expand Down
17 changes: 16 additions & 1 deletion webview-ui/src/components/chat/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -616,11 +616,26 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
switch (
clineAskRef.current // Use clineAskRef.current
) {
case "command_output":
// For command_output, send terminalOperation with user's message
// instead of askResponse. This allows the command to continue
// running in the background while keeping the UI responsive.
// The user's message is passed to the backend to be used as
// additional context when the command finishes.
vscode.postMessage({
type: "terminalOperation",
terminalOperation: "continue",
text,
images,
})
// Clear input but don't fully reset UI to avoid hang
setInputValue("")
setSelectedImages([])
return // Don't call handleChatReset
case "followup":
case "tool":
case "browser_action_launch":
case "command": // User can provide feedback to a tool or command use.
case "command_output": // User can send input to command stdin.
case "use_mcp_server":
case "completion_result": // If this happens then the user has feedback for the completion result.
case "resume_task":
Expand Down
Loading