feat: open edit tool changes in VS Code diff view with line focus
Tool-card clicks for edit-like actions now open a VS Code diff instead of only the file Diff view focuses the first changed line for faster review Uses a virtual readonly original buffer to avoid opening unsaved draft tabs
This commit is contained in:
@@ -232,6 +232,45 @@ const getFirstChangedLineFromMetadata = (tool: string, metadata?: Record<string,
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const getPrimaryDiffFromMetadata = (
|
||||
tool: string,
|
||||
metadata?: Record<string, unknown>,
|
||||
preferredPath?: string,
|
||||
): string | undefined => {
|
||||
if (!metadata || (tool !== 'edit' && tool !== 'multiedit' && tool !== 'apply_patch')) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const files = Array.isArray(metadata.files) ? metadata.files : [];
|
||||
if (files.length > 0) {
|
||||
const preferred = typeof preferredPath === 'string' && preferredPath.length > 0
|
||||
? preferredPath
|
||||
: undefined;
|
||||
const matched = preferred
|
||||
? files.find((file) => {
|
||||
if (!file || typeof file !== 'object') {
|
||||
return false;
|
||||
}
|
||||
const candidate = file as { relativePath?: unknown; filePath?: unknown };
|
||||
return candidate.relativePath === preferred || candidate.filePath === preferred;
|
||||
})
|
||||
: files[0];
|
||||
|
||||
if (matched && typeof matched === 'object') {
|
||||
const patch = (matched as { diff?: unknown }).diff;
|
||||
if (typeof patch === 'string' && patch.trim().length > 0) {
|
||||
return patch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof metadata.diff === 'string' && metadata.diff.trim().length > 0) {
|
||||
return metadata.diff;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const getRelativePath = (absolutePath: string, currentDirectory: string): string => {
|
||||
if (absolutePath.startsWith(currentDirectory)) {
|
||||
const relativePath = absolutePath.substring(currentDirectory.length);
|
||||
@@ -1713,14 +1752,21 @@ const ToolPart: React.FC<ToolPartProps> = ({
|
||||
|
||||
let filePath: unknown;
|
||||
let targetLine: number | undefined;
|
||||
let toolDiff: string | undefined;
|
||||
if (part.tool === 'edit' || part.tool === 'multiedit') {
|
||||
filePath = input?.filePath || input?.file_path || input?.path || metadata?.filePath || metadata?.file_path || metadata?.path;
|
||||
targetLine = getFirstChangedLineFromMetadata(part.tool, metadata);
|
||||
if (typeof filePath === 'string') {
|
||||
toolDiff = getPrimaryDiffFromMetadata(part.tool, metadata, filePath);
|
||||
}
|
||||
} else if (part.tool === 'apply_patch') {
|
||||
const files = Array.isArray(metadata?.files) ? metadata?.files : [];
|
||||
const firstFile = files[0] as { relativePath?: string; filePath?: string } | undefined;
|
||||
filePath = firstFile?.relativePath || firstFile?.filePath;
|
||||
targetLine = getFirstChangedLineFromMetadata(part.tool, metadata);
|
||||
if (typeof filePath === 'string') {
|
||||
toolDiff = getPrimaryDiffFromMetadata(part.tool, metadata, filePath);
|
||||
}
|
||||
} else if (['write', 'create', 'file_write', 'read', 'view', 'file_read', 'cat'].includes(part.tool)) {
|
||||
filePath = input?.filePath || input?.file_path || input?.path || metadata?.filePath || metadata?.file_path || metadata?.path;
|
||||
}
|
||||
@@ -1731,6 +1777,11 @@ const ToolPart: React.FC<ToolPartProps> = ({
|
||||
if (!filePath.startsWith('/')) {
|
||||
absolutePath = currentDirectory.endsWith('/') ? currentDirectory + filePath : currentDirectory + '/' + filePath;
|
||||
}
|
||||
if (runtime.runtime.isVSCode && toolDiff && (part.tool === 'edit' || part.tool === 'multiedit' || part.tool === 'apply_patch')) {
|
||||
const label = `${getRelativePath(absolutePath, currentDirectory)} (changes)`;
|
||||
void runtime.editor.openDiff('', absolutePath, label, { line: targetLine, patch: toolDiff });
|
||||
return;
|
||||
}
|
||||
runtime.editor.openFile(absolutePath, targetLine);
|
||||
} else {
|
||||
onToggle(part.id);
|
||||
|
||||
Reference in New Issue
Block a user