fix(frontend): preserve edit file trailing context

This commit is contained in:
JOJO 2026-06-20 19:19:58 +08:00
parent f661dc6456
commit 6c368d2aa0

View File

@ -298,19 +298,19 @@ function renderEditFile(result: any, args: any): string {
const newText = rep.new_string || '';
const detail = details[idx] || {};
const contexts = Array.isArray(detail.contexts) ? detail.contexts : [];
const oldLines = oldText ? oldText.split('\n') : [];
const newLines = newText ? newText.split('\n') : [];
const buildPairRows = (context?: any) => {
const rows: any[] = [];
const startLineCandidate = Number(context?.old_start_line ?? detail.matched_lines?.[0]);
const startLine = Number.isFinite(startLineCandidate) ? startLineCandidate : null;
if (oldText) {
const oldLines = oldText.split('\n');
oldLines.forEach((line: string, lineIdx: number) => {
rows.push({ lineNo: startLine === null ? null : startLine + lineIdx, marker: '-', text: line, className: 'diff-remove' });
});
}
if (newText) {
const newLines = newText.split('\n');
newLines.forEach((line: string, lineIdx: number) => {
rows.push({ lineNo: startLine === null ? null : startLine + lineIdx, marker: '+', text: line, className: 'diff-add' });
});
@ -337,12 +337,24 @@ function renderEditFile(result: any, args: any): string {
rawAfterLines.length >= 2 && String(rawAfterLines[rawAfterLines.length - 1]?.text ?? '') === ''
? rawAfterLines.slice(0, -1)
: rawAfterLines;
// 编辑后新增/删除行数不同会导致后续行号偏移after context 需按新文件位置重新编号
const contextOldStartLine = Number(context?.old_start_line ?? detail.matched_lines?.[0]);
const contextOldEndLine = Number(context?.old_end_line ?? contextOldStartLine);
const oldLineCount = Number.isFinite(contextOldStartLine) && Number.isFinite(contextOldEndLine)
? Math.max(1, contextOldEndLine - contextOldStartLine + 1)
: Math.max(1, (oldText ? oldText.split('\n').length : 1));
const newLineCount = newText === '' ? 0 : newText.split('\n').length;
const afterContextOffset = newLineCount - oldLineCount;
beforeLines.forEach((item: any) => {
rows.push({ lineNo: Number(item.line), marker: ' ', text: String(item.text ?? ''), className: '' });
});
rows.push(...buildPairRows(context));
afterLines.forEach((item: any) => {
rows.push({ lineNo: Number(item.line), marker: ' ', text: String(item.text ?? ''), className: '' });
const rawLineNo = Number(item.line);
const lineNo = Number.isFinite(rawLineNo) ? rawLineNo + afterContextOffset : rawLineNo;
rows.push({ lineNo, marker: ' ', text: String(item.text ?? ''), className: '' });
});
const numberedRows = rows.filter((row) => typeof row.lineNo === 'number' && Number.isFinite(row.lineNo));
hunks.push({
@ -375,14 +387,8 @@ function renderEditFile(result: any, args: any): string {
const markerOrder: Record<string, number> = { ' ': 0, '-': 1, '+': 2 };
mergedHunks.forEach((hunk, hunkIdx) => {
if (hunkIdx > 0) renderDiffLine(null, ' ', '⋮', 'diff-separator');
const changedLines = new Set(
hunk.rows
.filter((row: any) => (row.marker === '-' || row.marker === '+') && typeof row.lineNo === 'number')
.map((row: any) => row.lineNo)
);
const seenContextLines = new Set<number>();
hunk.rows
.filter((row: any) => !(row.marker === ' ' && changedLines.has(row.lineNo)))
const filteredRows = hunk.rows
.filter((row: any) => {
if (row.marker !== ' ' || typeof row.lineNo !== 'number') return true;
if (seenContextLines.has(row.lineNo)) return false;
@ -400,8 +406,8 @@ function renderEditFile(result: any, args: any): string {
// 上下文行或跨类型:按行号优先
const lineDelta = (a.lineNo ?? Number.MAX_SAFE_INTEGER) - (b.lineNo ?? Number.MAX_SAFE_INTEGER);
return lineDelta || (markerOrder[a.marker] ?? 9) - (markerOrder[b.marker] ?? 9);
})
.forEach((row: any) => renderDiffLine(row.lineNo, row.marker, row.text, row.className));
});
filteredRows.forEach((row: any) => renderDiffLine(row.lineNo, row.marker, row.text, row.className));
});
html += '</div>';
}