feat(lsp): add lsp AI tool for code navigation (TS/JS)#293
Merged
Conversation
Adds an 'lsp' tool that lets the AI agent query a language server for code navigation: goToDefinition, findReferences, hover, documentSymbol, workspaceSymbol, goToImplementation. Currently supports TypeScript / JavaScript via typescript-language-server. The tool spawns typescript-language-server as a child process and speaks JSON-RPC 2.0 over stdio. No external LSP client library is needed — the client implements minimal Content-Length framing and request/response matching (~200 lines). Design: - lsp-client.ts: session management (reference-counted per workspace, 30s idle cleanup), JSON-RPC framing, initialize handshake, didOpen/ didClose document sync, and the 6 query methods - builtin-lsp-tool.ts: the LocalTool definition with zod-free hand-written JSON Schema (matching Kun's existing tool convention), position conversion (1-based input → 0-based LSP), and result simplification (strips file:// URIs to paths, converts positions back to 1-based, maps symbol kind numbers to names) The server binary must be installed (npm install -g typescript-language- server typescript). If missing, the tool returns a helpful error with install instructions instead of crashing. Registered as a builtin tool alongside read/bash/grep/etc. via buildBuiltinLocalTools(). Read-only operations, policy 'auto'.
Three fixes from code review:
1. Process leak: export shutdownAllLspSessions() and register a
process.on('exit') handler that SIGKILLs all active LSP servers
synchronously. Previously, if the host process exited within the
30s idle window, the language server (and its tsserver child) would
become orphaned.
2. Acquire race: sessions map now stores Promise<LspSession> instead of
LspSession. The first caller writes its Promise before any await;
concurrent callers await the same Promise. Previously two concurrent
tool calls could each spawn their own server.
3. Server crash: the 'exit' and 'error' handlers now call killSession()
which rejects all pending requests immediately. Previously a server
crash would leave pending requests hanging until their 30s timeout.
Collaborator
|
hope Future work can fast coming,lsp is very useful |
Contributor
Author
|
Thanks for the merge! Glad the LSP tool is useful
I'm working on a few more features (git worktree pool, memory management UI) and would love to discuss the project's roadmap and technical direction. If you're open to it, we could connect on WeChat or Telegram — my wechat is “xiaobailong0216”
Happy to keep contributing either way!
Martini
***@***.***
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an
lspAI tool that lets the agent query a language server for code navigation. Currently supports TypeScript / JavaScript viatypescript-language-server. This is the AI-tool-only version (no editor integration); a follow-up can add it to the Monaco/CodeMirror editor once that lands.Supported operations
goToDefinitionfindReferenceshoverdocumentSymbolworkspaceSymbolgoToImplementationPositions are 1-based (as editors display them); the tool converts to 0-based internally and back to 1-based in output.
Architecture
No external LSP client library (
vscode-languageserver-protocol/vscode-jsonrpc). The client implements minimal Content-Length framing and request/response matching in ~200 lines — this avoids adding a new dependency tokun/and keeps the PR self-contained.Files
kun/src/adapters/tool/lsp-client.tskun/src/adapters/tool/builtin-lsp-tool.tskun/src/adapters/tool/builtin-tools.tsbuildBuiltinLocalTools()Key design decisions
kun/dependency. JSON-RPC framing is hand-rolled (~100 lines) rather than pulling invscode-languageserver-protocol. The framing logic is straightforward (Content-Length header + body) and has no edge cases for the query-only operations we support.typescript-language-serverisn't installed, the tool returns a helpful error (Install with: npm install -g typescript-language-server typescript) instead of crashing the agent loop.policy: 'auto',toolKind: 'tool_call'. No approval needed.file://URIs, 0-based positions, and numeric symbol kinds. The tool converts these to plain paths, 1-based positions, and human-readable kind names so the output is compact for the agent's context window.Prerequisites
The user (or their project) must have
typescript-language-serverinstalled:Or locally:
npm install -D typescript-language-server typescript(the tool checksnode_modules/.bin/first).Verification
kun/typecheck passes (tsc --noEmit)kun/tool tests pass (24/24)developtoo)Future work (not in this PR)