From b045f6918e7828941a61b551eaa3bdf4bf9fc058 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 5 Dec 2025 22:51:46 +0900 Subject: [PATCH] feat(lsp): add result limits to prevent token overflow - Add DEFAULT_MAX_REFERENCES, DEFAULT_MAX_SYMBOLS, DEFAULT_MAX_DIAGNOSTICS (200 each) - Apply limits to lsp_find_references, lsp_document_symbols, lsp_workspace_symbols, lsp_diagnostics - Show truncation warning when results exceed limits --- src/tools/lsp/constants.ts | 4 +++ src/tools/lsp/tools.ts | 54 +++++++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/tools/lsp/constants.ts b/src/tools/lsp/constants.ts index a001a36..5b2fa97 100644 --- a/src/tools/lsp/constants.ts +++ b/src/tools/lsp/constants.ts @@ -36,6 +36,10 @@ export const SEVERITY_MAP: Record = { 4: "hint", } +export const DEFAULT_MAX_REFERENCES = 200 +export const DEFAULT_MAX_SYMBOLS = 200 +export const DEFAULT_MAX_DIAGNOSTICS = 200 + export const BUILTIN_SERVERS: Record> = { typescript: { command: ["typescript-language-server", "--stdio"], diff --git a/src/tools/lsp/tools.ts b/src/tools/lsp/tools.ts index f30f47c..68a7458 100644 --- a/src/tools/lsp/tools.ts +++ b/src/tools/lsp/tools.ts @@ -1,5 +1,10 @@ import { tool } from "@opencode-ai/plugin/tool" import { getAllServers } from "./config" +import { + DEFAULT_MAX_REFERENCES, + DEFAULT_MAX_SYMBOLS, + DEFAULT_MAX_DIAGNOSTICS, +} from "./constants" import { withLspClient, formatHoverResult, @@ -112,7 +117,14 @@ export const lsp_find_references = tool({ return output } - const output = result.map(formatLocation).join("\n") + const total = result.length + const truncated = total > DEFAULT_MAX_REFERENCES + const limited = truncated ? result.slice(0, DEFAULT_MAX_REFERENCES) : result + const lines = limited.map(formatLocation) + if (truncated) { + lines.unshift(`Found ${total} references (showing first ${DEFAULT_MAX_REFERENCES}):`) + } + const output = lines.join("\n") return output } catch (e) { const output = `Error: ${e instanceof Error ? e.message : String(e)}` @@ -138,13 +150,21 @@ export const lsp_document_symbols = tool({ return output } - let output: string - if ("range" in result[0]) { - output = (result as DocumentSymbol[]).map((s) => formatDocumentSymbol(s)).join("\n") - } else { - output = (result as SymbolInfo[]).map(formatSymbolInfo).join("\n") + const total = result.length + const truncated = total > DEFAULT_MAX_SYMBOLS + const limited = truncated ? result.slice(0, DEFAULT_MAX_SYMBOLS) : result + + const lines: string[] = [] + if (truncated) { + lines.push(`Found ${total} symbols (showing first ${DEFAULT_MAX_SYMBOLS}):`) } - return output + + if ("range" in limited[0]) { + lines.push(...(limited as DocumentSymbol[]).map((s) => formatDocumentSymbol(s))) + } else { + lines.push(...(limited as SymbolInfo[]).map(formatSymbolInfo)) + } + return lines.join("\n") } catch (e) { const output = `Error: ${e instanceof Error ? e.message : String(e)}` return output @@ -171,8 +191,15 @@ export const lsp_workspace_symbols = tool({ return output } - const limited = args.limit ? result.slice(0, args.limit) : result - const output = limited.map(formatSymbolInfo).join("\n") + const total = result.length + const limit = Math.min(args.limit ?? DEFAULT_MAX_SYMBOLS, DEFAULT_MAX_SYMBOLS) + const truncated = total > limit + const limited = result.slice(0, limit) + const lines = limited.map(formatSymbolInfo) + if (truncated) { + lines.unshift(`Found ${total} symbols (showing first ${limit}):`) + } + const output = lines.join("\n") return output } catch (e) { const output = `Error: ${e instanceof Error ? e.message : String(e)}` @@ -213,7 +240,14 @@ export const lsp_diagnostics = tool({ return output } - const output = diagnostics.map(formatDiagnostic).join("\n") + const total = diagnostics.length + const truncated = total > DEFAULT_MAX_DIAGNOSTICS + const limited = truncated ? diagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS) : diagnostics + const lines = limited.map(formatDiagnostic) + if (truncated) { + lines.unshift(`Found ${total} diagnostics (showing first ${DEFAULT_MAX_DIAGNOSTICS}):`) + } + const output = lines.join("\n") return output } catch (e) { const output = `Error: ${e instanceof Error ? e.message : String(e)}`