| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import z from "zod"
- import { Tool } from "./tool"
- import path from "path"
- import { LSP } from "../lsp"
- import DESCRIPTION from "./lsp.txt"
- import { Instance } from "../project/instance"
- import { pathToFileURL } from "url"
- const operations = [
- "goToDefinition",
- "findReferences",
- "hover",
- "documentSymbol",
- "workspaceSymbol",
- "goToImplementation",
- "prepareCallHierarchy",
- "incomingCalls",
- "outgoingCalls",
- ] as const
- export const LspTool = Tool.define("lsp", {
- description: DESCRIPTION,
- parameters: z.object({
- operation: z.enum(operations).describe("The LSP operation to perform"),
- filePath: z.string().describe("The absolute or relative path to the file"),
- line: z.number().int().min(1).describe("The line number (1-based, as shown in editors)"),
- character: z.number().int().min(1).describe("The character offset (1-based, as shown in editors)"),
- }),
- execute: async (args, ctx) => {
- await ctx.ask({
- permission: "lsp",
- patterns: ["*"],
- always: ["*"],
- metadata: {},
- })
- const file = path.isAbsolute(args.filePath) ? args.filePath : path.join(Instance.directory, args.filePath)
- const uri = pathToFileURL(file).href
- const position = {
- file,
- line: args.line - 1,
- character: args.character - 1,
- }
- const relPath = path.relative(Instance.worktree, file)
- const title = `${args.operation} ${relPath}:${args.line}:${args.character}`
- const exists = await Bun.file(file).exists()
- if (!exists) {
- throw new Error(`File not found: ${file}`)
- }
- const available = await LSP.hasClients(file)
- if (!available) {
- throw new Error("No LSP server available for this file type.")
- }
- await LSP.touchFile(file, true)
- const result: unknown[] = await (async () => {
- switch (args.operation) {
- case "goToDefinition":
- return LSP.definition(position)
- case "findReferences":
- return LSP.references(position)
- case "hover":
- return LSP.hover(position)
- case "documentSymbol":
- return LSP.documentSymbol(uri)
- case "workspaceSymbol":
- return LSP.workspaceSymbol("")
- case "goToImplementation":
- return LSP.implementation(position)
- case "prepareCallHierarchy":
- return LSP.prepareCallHierarchy(position)
- case "incomingCalls":
- return LSP.incomingCalls(position)
- case "outgoingCalls":
- return LSP.outgoingCalls(position)
- }
- })()
- const output = (() => {
- if (result.length === 0) return `No results found for ${args.operation}`
- return JSON.stringify(result, null, 2)
- })()
- return {
- title,
- metadata: { result },
- output,
- }
- },
- })
|