Skip to content
Merged
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
25 changes: 12 additions & 13 deletions src/core/tools/insertContentTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export async function insertContentTool(
approvalContent = updatedContent
}

// Prepare the approval message (same for both flows)
const completeMessage = JSON.stringify({
...sharedMessageProps,
diff,
Expand All @@ -144,35 +145,33 @@ export async function insertContentTool(
isProtected: isWriteProtected,
} satisfies ClineSayTool)

// Show diff view if focus disruption prevention is disabled
if (!isPreventFocusDisruptionEnabled) {
await cline.diffViewProvider.open(relPath)
await cline.diffViewProvider.update(updatedContent, true)
cline.diffViewProvider.scrollToFirstDiff()
}

// Ask for approval (same for both flows)
const didApprove = await cline
.ask("tool", completeMessage, isWriteProtected)
.then((response) => response.response === "yesButtonClicked")

if (!didApprove) {
// Revert changes if diff view was shown
if (!isPreventFocusDisruptionEnabled) {
await cline.diffViewProvider.revertChanges()
}
pushToolResult("Changes were rejected by the user.")
await cline.diffViewProvider.reset()
return
}

// Save the changes
if (isPreventFocusDisruptionEnabled) {
// Direct file write without diff view or opening the file
await cline.diffViewProvider.saveDirectly(relPath, updatedContent, false, diagnosticsEnabled, writeDelayMs)
} else {
// Original behavior with diff view
// Show changes in diff view
if (!cline.diffViewProvider.isEditing) {
await cline.ask("tool", JSON.stringify(sharedMessageProps), true).catch(() => {})
// First open with original content
await cline.diffViewProvider.open(relPath)
await cline.diffViewProvider.update(fileContent, false)
cline.diffViewProvider.scrollToFirstDiff()
await delay(200)
}

await cline.diffViewProvider.update(updatedContent, true)

// Call saveChanges to update the DiffViewProvider properties
await cline.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs)
}
Expand Down
89 changes: 59 additions & 30 deletions src/core/tools/multiApplyDiffTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,17 +525,17 @@ ${errorDetails ? `\nTechnical details:\n${errorDetails}\n` : ""}
isProtected: isWriteProtected,
}

// If single file, ask for approval
// If single file, handle based on PREVENT_FOCUS_DISRUPTION setting
let didApprove = true
if (operationsToApprove.length === 1) {
// Prepare common data for single file operation
const diffContents = diffItems.map((item) => item.content).join("\n\n")
const operationMessage = JSON.stringify({
...sharedMessageProps,
diff: diffContents,
} satisfies ClineSayTool)

let toolProgressStatus

if (cline.diffStrategy && cline.diffStrategy.getProgressStatus) {
toolProgressStatus = cline.diffStrategy.getProgressStatus(
{
Expand All @@ -546,40 +546,69 @@ ${errorDetails ? `\nTechnical details:\n${errorDetails}\n` : ""}
)
}

// Check if file is write-protected
// Set up diff view
cline.diffViewProvider.editType = "modify"

// Show diff view if focus disruption prevention is disabled
if (!isPreventFocusDisruptionEnabled) {
await cline.diffViewProvider.open(relPath)
await cline.diffViewProvider.update(originalContent!, true)
cline.diffViewProvider.scrollToFirstDiff()
} else {
// For direct save, we still need to set originalContent
cline.diffViewProvider.originalContent = await fs.readFile(absolutePath, "utf-8")
}

// Ask for approval (same for both flows)
const isWriteProtected = cline.rooProtectedController?.isWriteProtected(relPath) || false
didApprove = await askApproval("tool", operationMessage, toolProgressStatus, isWriteProtected)
}

if (!didApprove) {
if (!isPreventFocusDisruptionEnabled) {
await cline.diffViewProvider.revertChanges()
if (!didApprove) {
// Revert changes if diff view was shown
if (!isPreventFocusDisruptionEnabled) {
await cline.diffViewProvider.revertChanges()
}
results.push(`Changes to ${relPath} were not approved by user`)
continue
}
results.push(`Changes to ${relPath} were not approved by user`)
continue
}

if (isPreventFocusDisruptionEnabled) {
// Direct file write without diff view or opening the file
cline.diffViewProvider.editType = "modify"
cline.diffViewProvider.originalContent = await fs.readFile(absolutePath, "utf-8")
await cline.diffViewProvider.saveDirectly(
relPath,
originalContent!,
false,
diagnosticsEnabled,
writeDelayMs,
)
// Save the changes
if (isPreventFocusDisruptionEnabled) {
// Direct file write without diff view or opening the file
await cline.diffViewProvider.saveDirectly(
relPath,
originalContent!,
false,
diagnosticsEnabled,
writeDelayMs,
)
} else {
// Call saveChanges to update the DiffViewProvider properties
await cline.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs)
}
} else {
// Original behavior with diff view
// Show diff view before asking for approval (only for single file or after batch approval)
cline.diffViewProvider.editType = "modify"
await cline.diffViewProvider.open(relPath)
await cline.diffViewProvider.update(originalContent!, true)
cline.diffViewProvider.scrollToFirstDiff()

// Call saveChanges to update the DiffViewProvider properties
await cline.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs)
// Batch operations - already approved above
if (isPreventFocusDisruptionEnabled) {
// Direct file write without diff view or opening the file
cline.diffViewProvider.editType = "modify"
cline.diffViewProvider.originalContent = await fs.readFile(absolutePath, "utf-8")
await cline.diffViewProvider.saveDirectly(
relPath,
originalContent!,
false,
diagnosticsEnabled,
writeDelayMs,
)
} else {
// Original behavior with diff view
cline.diffViewProvider.editType = "modify"
await cline.diffViewProvider.open(relPath)
await cline.diffViewProvider.update(originalContent!, true)
cline.diffViewProvider.scrollToFirstDiff()

// Call saveChanges to update the DiffViewProvider properties
await cline.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs)
}
}

// Track file edit operation
Expand Down
23 changes: 10 additions & 13 deletions src/core/tools/searchAndReplaceTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,17 +210,25 @@ export async function searchAndReplaceTool(
EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION,
)

// Request user approval for changes
const completeMessage = JSON.stringify({
...sharedMessageProps,
diff,
isProtected: isWriteProtected,
} satisfies ClineSayTool)

// Show diff view if focus disruption prevention is disabled
if (!isPreventFocusDisruptionEnabled) {
await cline.diffViewProvider.open(validRelPath)
await cline.diffViewProvider.update(newContent, true)
cline.diffViewProvider.scrollToFirstDiff()
}

const didApprove = await cline
.ask("tool", completeMessage, isWriteProtected)
.then((response) => response.response === "yesButtonClicked")

if (!didApprove) {
// Revert changes if diff view was shown
if (!isPreventFocusDisruptionEnabled) {
await cline.diffViewProvider.revertChanges()
}
Expand All @@ -229,22 +237,11 @@ export async function searchAndReplaceTool(
return
}

// Save the changes
if (isPreventFocusDisruptionEnabled) {
// Direct file write without diff view or opening the file
await cline.diffViewProvider.saveDirectly(validRelPath, newContent, false, diagnosticsEnabled, writeDelayMs)
} else {
// Original behavior with diff view
// Show changes in diff view
if (!cline.diffViewProvider.isEditing) {
await cline.ask("tool", JSON.stringify(sharedMessageProps), true).catch(() => {})
await cline.diffViewProvider.open(validRelPath)
await cline.diffViewProvider.update(fileContent, false)
cline.diffViewProvider.scrollToFirstDiff()
await delay(200)
}

await cline.diffViewProvider.update(newContent, true)

// Call saveChanges to update the DiffViewProvider properties
await cline.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs)
}
Expand Down
Loading