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
This commit is contained in:
YeonGyu-Kim
2025-12-05 22:51:46 +09:00
parent 725ec9b91d
commit b045f6918e
2 changed files with 48 additions and 10 deletions

View File

@@ -36,6 +36,10 @@ export const SEVERITY_MAP: Record<number, string> = {
4: "hint", 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<string, Omit<LSPServerConfig, "id">> = { export const BUILTIN_SERVERS: Record<string, Omit<LSPServerConfig, "id">> = {
typescript: { typescript: {
command: ["typescript-language-server", "--stdio"], command: ["typescript-language-server", "--stdio"],

View File

@@ -1,5 +1,10 @@
import { tool } from "@opencode-ai/plugin/tool" import { tool } from "@opencode-ai/plugin/tool"
import { getAllServers } from "./config" import { getAllServers } from "./config"
import {
DEFAULT_MAX_REFERENCES,
DEFAULT_MAX_SYMBOLS,
DEFAULT_MAX_DIAGNOSTICS,
} from "./constants"
import { import {
withLspClient, withLspClient,
formatHoverResult, formatHoverResult,
@@ -112,7 +117,14 @@ export const lsp_find_references = tool({
return output 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 return output
} catch (e) { } catch (e) {
const output = `Error: ${e instanceof Error ? e.message : String(e)}` const output = `Error: ${e instanceof Error ? e.message : String(e)}`
@@ -138,13 +150,21 @@ export const lsp_document_symbols = tool({
return output return output
} }
let output: string const total = result.length
if ("range" in result[0]) { const truncated = total > DEFAULT_MAX_SYMBOLS
output = (result as DocumentSymbol[]).map((s) => formatDocumentSymbol(s)).join("\n") const limited = truncated ? result.slice(0, DEFAULT_MAX_SYMBOLS) : result
} else {
output = (result as SymbolInfo[]).map(formatSymbolInfo).join("\n") 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) { } catch (e) {
const output = `Error: ${e instanceof Error ? e.message : String(e)}` const output = `Error: ${e instanceof Error ? e.message : String(e)}`
return output return output
@@ -171,8 +191,15 @@ export const lsp_workspace_symbols = tool({
return output return output
} }
const limited = args.limit ? result.slice(0, args.limit) : result const total = result.length
const output = limited.map(formatSymbolInfo).join("\n") 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 return output
} catch (e) { } catch (e) {
const output = `Error: ${e instanceof Error ? e.message : String(e)}` const output = `Error: ${e instanceof Error ? e.message : String(e)}`
@@ -213,7 +240,14 @@ export const lsp_diagnostics = tool({
return output 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 return output
} catch (e) { } catch (e) {
const output = `Error: ${e instanceof Error ? e.message : String(e)}` const output = `Error: ${e instanceof Error ? e.message : String(e)}`