feat: 添加文件写入 diff 预览和 LSP 诊断优化

- 文件写入/编辑前显示 diff 对比供用户确认
- LSP 诊断只显示错误和警告,忽略 hint/info
- 优化 LSP 等待时间:首次启动 2s,后续 300ms
This commit is contained in:
2025-12-11 00:44:42 +08:00
parent 929f6f7850
commit 09839b15a0
8 changed files with 646 additions and 29 deletions
+27 -23
View File
@@ -42,32 +42,11 @@ export const editFileTool: ToolWithMetadata = {
? filePath
: path.join(cwd, filePath);
// 权限检查
const permissionManager = getPermissionManager();
const permResult = await permissionManager.checkFilePermission({
operation: 'edit',
path: absolutePath,
workdir: cwd,
});
if (!permResult.allowed) {
if (permResult.needsConfirmation) {
return {
success: false,
output: '',
error: `需要用户确认: 编辑 ${absolutePath}\n原因: ${permResult.reason || '需要权限确认'}`,
};
}
return {
success: false,
output: '',
error: `权限被拒绝: ${permResult.reason || '不允许编辑此文件'}`,
};
}
try {
// 先读取文件内容,用于验证和 diff 显示
const content = await fs.readFile(absolutePath, 'utf-8');
// 验证 old_string 是否存在且唯一
if (!content.includes(oldString)) {
return {
success: false,
@@ -85,6 +64,31 @@ export const editFileTool: ToolWithMetadata = {
};
}
// 权限检查(传递内容用于 diff 显示)
const permissionManager = getPermissionManager();
const permResult = await permissionManager.checkFilePermission({
operation: 'edit',
path: absolutePath,
workdir: cwd,
oldContent: oldString,
newContent: newString,
});
if (!permResult.allowed) {
if (permResult.needsConfirmation) {
return {
success: false,
output: '',
error: `需要用户确认: 编辑 ${absolutePath}\n原因: ${permResult.reason || '需要权限确认'}`,
};
}
return {
success: false,
output: '',
error: `权限被拒绝: ${permResult.reason || '不允许编辑此文件'}`,
};
}
const newContent = content.replace(oldString, newString);
await fs.writeFile(absolutePath, newContent, 'utf-8');
+2 -1
View File
@@ -36,12 +36,13 @@ export const writeFileTool: ToolWithMetadata = {
? filePath
: path.join(cwd, filePath);
// 权限检查
// 权限检查(传递内容用于 diff 显示)
const permissionManager = getPermissionManager();
const permResult = await permissionManager.checkFilePermission({
operation: 'write',
path: absolutePath,
workdir: cwd,
newContent: content,
});
if (!permResult.allowed) {