Chat-only edits are not tracked

This commit is contained in:
Shawn 2025-08-31 22:10:47 -04:00 committed by Hannes Rudolph
parent 90d9306534
commit b4086b1a5a
6 changed files with 113 additions and 34 deletions

View file

@ -221,29 +221,80 @@ async function checkGitInstallation(
try {
const checkpointFileChangeManager = provider?.getFileChangeManager()
if (checkpointFileChangeManager) {
// Get the initial baseline (preserve for cumulative diff tracking)
const initialBaseline = checkpointFileChangeManager.getChanges().baseCheckpoint
// Get the current baseline for cumulative tracking
let currentBaseline = checkpointFileChangeManager.getChanges().baseCheckpoint
// For cumulative tracking, we want to calculate from baseline to new checkpoint
// But if this is the first time or baseline is invalid, update it to fromHash
try {
await service.getDiff({ from: currentBaseline, to: currentBaseline })
log(
`[Task#checkpointCreated] Using existing baseline ${currentBaseline} for cumulative tracking`,
)
} catch (baselineValidationError) {
// Baseline is invalid, use fromHash as the new baseline for cumulative tracking
log(
`[Task#checkpointCreated] Baseline validation failed for ${currentBaseline}: ${baselineValidationError instanceof Error ? baselineValidationError.message : String(baselineValidationError)}`,
)
log(`[Task#checkpointCreated] Updating baseline to fromHash: ${fromHash}`)
currentBaseline = fromHash
// Update FileChangeManager baseline to match
try {
await checkpointFileChangeManager.updateBaseline(currentBaseline)
log(`[Task#checkpointCreated] Successfully updated baseline to ${currentBaseline}`)
} catch (updateError) {
log(
`[Task#checkpointCreated] Failed to update baseline: ${updateError instanceof Error ? updateError.message : String(updateError)}`,
)
throw updateError
}
}
log(
`[Task#checkpointCreated] Calculating cumulative changes from initial baseline ${initialBaseline} to ${toHash}`,
`[Task#checkpointCreated] Calculating cumulative changes from baseline ${currentBaseline} to ${toHash}`,
)
// Calculate cumulative diff from initial baseline to new checkpoint using checkpoint service
const changes = await service.getDiff({ from: initialBaseline, to: toHash })
// Calculate cumulative diff from baseline to new checkpoint using checkpoint service
const changes = await service.getDiff({ from: currentBaseline, to: toHash })
if (changes && changes.length > 0) {
// Convert to FileChange format with correct checkpoint references
const fileChanges = changes.map((change: any) => ({
uri: change.paths.relative,
type: (change.paths.newFile
? "create"
: change.paths.deletedFile
? "delete"
: "edit") as FileChangeType,
fromCheckpoint: initialBaseline, // Always reference initial baseline for cumulative view
toCheckpoint: toHash, // Current checkpoint for comparison
linesAdded: change.content.after ? change.content.after.split("\n").length : 0,
linesRemoved: change.content.before ? change.content.before.split("\n").length : 0,
}))
const fileChanges = changes.map((change: any) => {
const type = (
change.paths.newFile ? "create" : change.paths.deletedFile ? "delete" : "edit"
) as FileChangeType
// Calculate actual line differences for the change
let linesAdded = 0
let linesRemoved = 0
if (type === "create") {
// New file: all lines are added
linesAdded = change.content.after ? change.content.after.split("\n").length : 0
linesRemoved = 0
} else if (type === "delete") {
// Deleted file: all lines are removed
linesAdded = 0
linesRemoved = change.content.before ? change.content.before.split("\n").length : 0
} else {
// Modified file: use FileChangeManager's improved calculation method
const lineDifferences = FileChangeManager.calculateLineDifferences(
change.content.before || "",
change.content.after || "",
)
linesAdded = lineDifferences.linesAdded
linesRemoved = lineDifferences.linesRemoved
}
return {
uri: change.paths.relative,
type,
fromCheckpoint: currentBaseline, // Reference current baseline for cumulative view
toCheckpoint: toHash, // Current checkpoint for comparison
linesAdded,
linesRemoved,
}
})
log(`[Task#checkpointCreated] Found ${fileChanges.length} cumulative file changes`)
@ -253,13 +304,13 @@ async function checkGitInstallation(
// DON'T clear accepted/rejected state here - preserve user's accept/reject decisions
// The state should only be cleared on baseline changes (checkpoint restore) or task restart
// Get filtered changeset that excludes already accepted/rejected files and only shows LLM-modified files
// Get changeset that excludes already accepted/rejected files and only shows LLM-modified files
const filteredChangeset = await checkpointFileChangeManager.getLLMOnlyChanges(
task.taskId,
task.fileContextTracker,
)
// Create changeset and send to webview (only LLM-modified, unaccepted files)
// Create changeset and send to webview (unaccepted files)
const serializableChangeset = {
baseCheckpoint: filteredChangeset.baseCheckpoint,
files: filteredChangeset.files,
@ -274,13 +325,13 @@ async function checkGitInstallation(
filesChanged: serializableChangeset,
})
} else {
log(`[Task#checkpointCreated] No changes found between ${initialBaseline} and ${toHash}`)
log(`[Task#checkpointCreated] No changes found between ${currentBaseline} and ${toHash}`)
}
// DON'T update the baseline - keep it at initial baseline for cumulative tracking
// DON'T update the baseline - keep it at current baseline for cumulative tracking
// The baseline should only change when explicitly requested (e.g., checkpoint restore)
log(
`[Task#checkpointCreated] Keeping FileChangeManager baseline at ${initialBaseline} for cumulative tracking`,
`[Task#checkpointCreated] Keeping FileChangeManager baseline at ${currentBaseline} for cumulative tracking`,
)
}
} catch (error) {
@ -457,12 +508,14 @@ export async function checkpointRestore(
provider?.log(`[checkpointRestore] Cleared accept/reject state for fresh start`)
}
// Calculate and send current changes (should be empty immediately after restore)
const changes = fileChangeManager.getChanges()
provider?.postMessageToWebview({
type: "filesChanged",
filesChanged: changes.files.length > 0 ? changes : undefined,
})
// Calculate and send current changes with LLM-only filtering (should be empty immediately after restore)
if (cline.taskId && cline.fileContextTracker) {
const changes = await fileChangeManager.getLLMOnlyChanges(cline.taskId, cline.fileContextTracker)
provider?.postMessageToWebview({
type: "filesChanged",
filesChanged: changes.files.length > 0 ? changes : undefined,
})
}
}
} catch (error) {
provider?.log(`[checkpointRestore] Failed to update FileChangeManager baseline: ${error}`)

View file

@ -230,6 +230,13 @@ export async function applyDiffToolLegacy(
// Get the formatted response message
const message = await cline.diffViewProvider.pushToolWriteResult(cline, cline.cwd, !fileExists)
// Track file as edited by LLM for FCO
try {
await cline.fileContextTracker.trackFileContext(relPath.toString(), "roo_edited")
} catch (error) {
console.error("Failed to track file edit in context:", error)
}
// Check for single SEARCH/REPLACE block warning
const searchBlocks = (diffContent.match(/<<<<<<< SEARCH/g) || []).length
const singleBlockNotice =

View file

@ -174,9 +174,11 @@ export async function insertContentTool(
await cline.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs)
}
// Track file edit operation
if (relPath) {
await cline.fileContextTracker.trackFileContext(relPath, "roo_edited" as RecordSource)
// Track file edit operation for FCO
try {
await cline.fileContextTracker.trackFileContext(relPath, "roo_edited")
} catch (error) {
console.error("Failed to track file edit in context:", error)
}
cline.didEditFile = true

View file

@ -244,9 +244,11 @@ export async function searchAndReplaceTool(
await cline.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs)
}
// Track file edit operation
if (relPath) {
await cline.fileContextTracker.trackFileContext(relPath, "roo_edited" as RecordSource)
// Track file edit operation for FCO
try {
await cline.fileContextTracker.trackFileContext(validRelPath.toString(), "roo_edited")
} catch (error) {
console.error("Failed to track file edit in context:", error)
}
cline.didEditFile = true

View file

@ -304,6 +304,13 @@ export async function writeToFileTool(
// Get the formatted response message
const message = await cline.diffViewProvider.pushToolWriteResult(cline, cline.cwd, !fileExists)
// Track file as edited by LLM for FCO
try {
await cline.fileContextTracker.trackFileContext(relPath.toString(), "roo_edited")
} catch (error) {
console.error("Failed to track file edit in context:", error)
}
pushToolResult(message)
await cline.diffViewProvider.reset()

View file

@ -419,6 +419,14 @@ const FileItem: React.FC<FileItemProps> = React.memo(
}}>
{file.uri}
</div>
<div
style={{
fontSize: "11px",
color: "var(--vscode-descriptionForeground)",
marginTop: "2px",
}}>
{t(`file-changes:file_types.${file.type}`)}
</div>
</div>
<div style={{ display: "flex", alignItems: "center", gap: "8px", marginLeft: "8px" }}>