chat: fix file recreation after deletion (#289986)

Fixes a bug where if a file is deleted and the agent then tries to
recreate it again (by doing an edit in startStreamingEdits) nothing
happens.

- If there is an existing deleted entry for the file and it has NOT been
  accepted, then replace it with the correct modified file entry. Takes
  the originalContent of the deleted file as the initial content of the
  new file.
- If the deleted entry HAS been accepted (is not in the modified state)
  then it is just discarded and replaced.

Fixes https://github.com/microsoft/vscode/issues/289925

(Commit message generated by Copilot)
This commit is contained in:
Connor Peet
2026-01-23 10:50:17 -08:00
committed by GitHub
parent 1d9805dc84
commit 8d86613bbf

View File

@@ -836,6 +836,8 @@ export class ChatEditingSession extends Disposable implements IChatEditingSessio
return entry.getCurrentSnapshot();
} else if (entry instanceof ChatEditingModifiedDocumentEntry) {
return entry.getCurrentContents();
} else if (entry instanceof ChatEditingDeletedFileEntry) {
return '';
} else {
throw new Error(`unknown entry type for ${entry.modifiedURI}`);
}
@@ -973,10 +975,30 @@ export class ChatEditingSession extends Disposable implements IChatEditingSessio
const existingEntry = this._entriesObs.get().find(e => isEqual(e.modifiedURI, resource));
if (existingEntry) {
if (telemetryInfo.requestId !== existingEntry.telemetryInfo.requestId) {
existingEntry.updateTelemetryInfo(telemetryInfo);
// If the existing entry is a deleted file entry, we need to replace it with a new modified entry
// This handles the case where a file was deleted and then recreated
if (existingEntry instanceof ChatEditingDeletedFileEntry) {
// Use the original content from the deleted entry as the initial content for the new entry
const initialContentFromDeleted = existingEntry.state.get() === ModifiedFileEntryState.Modified
? existingEntry.initialContent
: undefined;
// Remove the deleted entry
existingEntry.dispose();
const entries = this._entriesObs.get().filter(e => e !== existingEntry);
this._entriesObs.set(entries, undefined);
// Set the initial content from the deleted entry if it was still in modified state
if (initialContentFromDeleted !== undefined) {
_initialContent = initialContentFromDeleted;
}
// Fall through to create a new entry
} else {
if (telemetryInfo.requestId !== existingEntry.telemetryInfo.requestId) {
existingEntry.updateTelemetryInfo(telemetryInfo);
}
return existingEntry;
}
return existingEntry;
}
let entry: AbstractChatEditingModifiedFileEntry;