feat(coder): add LSP code intelligence tools

- lsp/ module: types, config, JSON-RPC client, server-manager, operations
- lsp_diagnostics: TypeScript/JavaScript diagnostics for a file
- lsp_goto_definition: find symbol definition at position
- lsp_find_references: find all references to a symbol
- Registered as READ_TOOLS in tool index
This commit is contained in:
2026-06-07 17:57:35 +00:00
parent bc83475a3d
commit ee749d8698
9 changed files with 488 additions and 1 deletions

View File

@@ -0,0 +1,48 @@
import { z } from 'zod';
import { readFile } from 'node:fs/promises';
import type { ToolDef, ToolContext } from './types.js';
import { resolveWritePath } from '../write_guard.js';
import { lspManager } from '../lsp/server-manager.js';
import { getDiagnostics } from '../lsp/operations.js';
const LspDiagnosticsInput = z.object({
file_path: z.string().describe('Path to the file to check for diagnostics'),
});
type InputT = z.infer<typeof LspDiagnosticsInput>;
export const lspDiagnosticsTool: ToolDef<InputT> = {
name: 'lsp_diagnostics',
description: 'Get TypeScript/JavaScript diagnostics (errors, warnings) for a file. Returns diagnostic messages with severity and location.',
inputSchema: LspDiagnosticsInput,
jsonSchema: {
type: 'function',
function: {
name: 'lsp_diagnostics',
description: 'Get TypeScript/JavaScript diagnostics for a file',
parameters: {
type: 'object',
properties: {
file_path: { type: 'string', description: 'Path to the file' },
},
required: ['file_path'],
},
},
},
async execute(input: InputT, projectRoot: string, _context: ToolContext): Promise<unknown> {
const resolved = await resolveWritePath(projectRoot, input.file_path);
const content = await readFile(resolved, 'utf8');
const client = await lspManager.getClient(resolved);
if (!client) return { error: 'Unsupported file type for LSP diagnostics' };
const diagnostics = await getDiagnostics(client, resolved, content);
if (diagnostics.length === 0) return { result: 'No diagnostics found.' };
const lines = diagnostics.map((d) => {
const sev = ['', 'error', 'warning', 'info', 'hint'][d.severity] ?? 'unknown';
return `[${sev}] line ${d.range.start.line + 1}:${d.range.start.character + 1} - ${d.message}`;
});
return { result: lines.join('\n') };
},
};