feat: 添加 LSP 代码诊断功能
- 实现 LSP 客户端,支持与语言服务器通信 - 支持多种语言: TypeScript, Python, Go, Rust, C/C++ 等 - write_file/edit_file 工具集成 LSP 诊断,写入后自动检查代码错误 - 添加 CLI 命令管理语言服务器 (ai-assist lsp list/install/info) - 智能等待机制:首次启动 LSP 等待 2s,后续仅需 300ms - 将 read_file/write_file/edit_file 设为核心工具,确保文件操作使用正确的工具 - 更新系统提示词,引导 AI 使用文件工具而非 bash 命令
This commit is contained in:
@@ -4,6 +4,7 @@ import type { ToolResult } from '../../types/index.js';
|
||||
import type { ToolWithMetadata } from '../types.js';
|
||||
import { loadDescription } from '../load_description.js';
|
||||
import { getPermissionManager } from '../../permission/index.js';
|
||||
import { touchFile, getFormattedFileDiagnostics, isLanguageSupported } from '../../lsp/index.js';
|
||||
|
||||
export const editFileTool: ToolWithMetadata = {
|
||||
name: 'edit_file',
|
||||
@@ -13,7 +14,7 @@ export const editFileTool: ToolWithMetadata = {
|
||||
category: 'filesystem',
|
||||
description: '编辑文件内容(查找替换)',
|
||||
keywords: ['edit', 'file', 'replace', 'modify', 'change', 'update', '编辑', '文件', '替换', '修改', '更新'],
|
||||
deferLoading: true,
|
||||
deferLoading: false, // 核心工具,始终可用
|
||||
},
|
||||
parameters: {
|
||||
path: {
|
||||
@@ -87,9 +88,27 @@ export const editFileTool: ToolWithMetadata = {
|
||||
const newContent = content.replace(oldString, newString);
|
||||
await fs.writeFile(absolutePath, newContent, 'utf-8');
|
||||
|
||||
let output = `文件已编辑: ${absolutePath}`;
|
||||
|
||||
// 如果支持 LSP,通知语言服务器并获取诊断
|
||||
if (isLanguageSupported(absolutePath)) {
|
||||
try {
|
||||
const isFirstStart = await touchFile(absolutePath, false);
|
||||
// 首次启动需要更长时间,后续只需短暂等待
|
||||
const waitTime = isFirstStart ? 2000 : 300;
|
||||
await new Promise(resolve => setTimeout(resolve, waitTime));
|
||||
const diagnostics = await getFormattedFileDiagnostics(absolutePath);
|
||||
if (diagnostics) {
|
||||
output += `\n\n⚠️ 代码检查发现问题,请修复:${diagnostics}`;
|
||||
}
|
||||
} catch {
|
||||
// LSP 错误不影响主流程
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: `文件已编辑: ${absolutePath}`,
|
||||
output,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
|
||||
@@ -13,7 +13,7 @@ export const readFileTool: ToolWithMetadata = {
|
||||
category: 'filesystem',
|
||||
description: '读取文件内容',
|
||||
keywords: ['read', 'file', 'content', 'cat', 'view', 'open', '读取', '文件', '内容', '查看', '打开'],
|
||||
deferLoading: true,
|
||||
deferLoading: false, // 核心工具,始终可用
|
||||
},
|
||||
parameters: {
|
||||
path: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { ToolResult } from '../../types/index.js';
|
||||
import type { ToolWithMetadata } from '../types.js';
|
||||
import { loadDescription } from '../load_description.js';
|
||||
import { getPermissionManager } from '../../permission/index.js';
|
||||
import { touchFile, getFormattedFileDiagnostics, isLanguageSupported } from '../../lsp/index.js';
|
||||
|
||||
export const writeFileTool: ToolWithMetadata = {
|
||||
name: 'write_file',
|
||||
@@ -13,7 +14,7 @@ export const writeFileTool: ToolWithMetadata = {
|
||||
category: 'filesystem',
|
||||
description: '写入文件内容',
|
||||
keywords: ['write', 'file', 'save', 'create', '写入', '文件', '保存', '创建', '新建'],
|
||||
deferLoading: true,
|
||||
deferLoading: false, // 核心工具,始终可用
|
||||
},
|
||||
parameters: {
|
||||
path: {
|
||||
@@ -61,9 +62,28 @@ export const writeFileTool: ToolWithMetadata = {
|
||||
try {
|
||||
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
|
||||
await fs.writeFile(absolutePath, content, 'utf-8');
|
||||
|
||||
let output = `文件已写入: ${absolutePath}`;
|
||||
|
||||
// 如果支持 LSP,通知语言服务器并获取诊断
|
||||
if (isLanguageSupported(absolutePath)) {
|
||||
try {
|
||||
const isFirstStart = await touchFile(absolutePath, true);
|
||||
// 首次启动需要更长时间,后续只需短暂等待
|
||||
const waitTime = isFirstStart ? 2000 : 300;
|
||||
await new Promise(resolve => setTimeout(resolve, waitTime));
|
||||
const diagnostics = await getFormattedFileDiagnostics(absolutePath);
|
||||
if (diagnostics) {
|
||||
output += `\n\n⚠️ 代码检查发现问题,请修复:${diagnostics}`;
|
||||
}
|
||||
} catch {
|
||||
// LSP 错误不影响主流程
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: `文件已写入: ${absolutePath}`,
|
||||
output,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user