refactor(lsp): consolidate LSP tools - remove lsp_hover, lsp_code_actions, lsp_code_action_resolve - merge lsp_document_symbols + lsp_workspace_symbols into lsp_symbols with scope parameter - update all references in hooks, templates, and documentation
This commit is contained in:
@@ -526,17 +526,13 @@ Ask @explore for the policy on this feature
|
||||
あなたがエディタで使っているその機能、他のエージェントは触ることができません。
|
||||
最高の同僚に最高の道具を渡してください。これでリファクタリングも、ナビゲーションも、分析も、エージェントが適切に行えるようになります。
|
||||
|
||||
- **lsp_hover**: その位置の型情報、ドキュメント、シグネチャを取得
|
||||
- **lsp_goto_definition**: シンボル定義へジャンプ
|
||||
- **lsp_find_references**: ワークスペース全体で使用箇所を検索
|
||||
- **lsp_document_symbols**: ファイルのシンボルアウトラインを取得
|
||||
- **lsp_workspace_symbols**: プロジェクト全体から名前でシンボルを検索
|
||||
- **lsp_symbols**: ファイルからシンボルを取得 (scope='document') またはワークスペース全体を検索 (scope='workspace')
|
||||
- **lsp_diagnostics**: ビルド前にエラー/警告を取得
|
||||
- **lsp_servers**: 利用可能な LSP サーバー一覧
|
||||
- **lsp_prepare_rename**: 名前変更操作の検証
|
||||
- **lsp_rename**: ワークスペース全体でシンボル名を変更
|
||||
- **lsp_code_actions**: 利用可能なクイックフィックス/リファクタリングを取得
|
||||
- **lsp_code_action_resolve**: コードアクションを適用
|
||||
- **ast_grep_search**: AST 認識コードパターン検索 (25言語対応)
|
||||
- **ast_grep_replace**: AST 認識コード置換
|
||||
|
||||
|
||||
@@ -549,17 +549,13 @@ Syntax highlighting, autocomplete, refactoring, navigation, analysis—and now a
|
||||
The features in your editor? Other agents can't touch them.
|
||||
Hand your best tools to your best colleagues. Now they can properly refactor, navigate, and analyze.
|
||||
|
||||
- **lsp_hover**: Type info, docs, signatures at position
|
||||
- **lsp_goto_definition**: Jump to symbol definition
|
||||
- **lsp_find_references**: Find all usages across workspace
|
||||
- **lsp_document_symbols**: Get file symbol outline
|
||||
- **lsp_workspace_symbols**: Search symbols by name across project
|
||||
- **lsp_symbols**: Get symbols from file (scope='document') or search across workspace (scope='workspace')
|
||||
- **lsp_diagnostics**: Get errors/warnings before build
|
||||
- **lsp_servers**: List available LSP servers
|
||||
- **lsp_prepare_rename**: Validate rename operation
|
||||
- **lsp_rename**: Rename symbol across workspace
|
||||
- **lsp_code_actions**: Get available quick fixes/refactorings
|
||||
- **lsp_code_action_resolve**: Apply code action
|
||||
- **ast_grep_search**: AST-aware code pattern search (25 languages)
|
||||
- **ast_grep_replace**: AST-aware code replacement
|
||||
- **call_omo_agent**: Spawn specialized explore/librarian agents. Supports `run_in_background` parameter for async execution.
|
||||
|
||||
@@ -548,17 +548,13 @@ gh repo star code-yeongyu/oh-my-opencode
|
||||
你编辑器中的功能?其他智能体无法触及。
|
||||
把你最好的工具交给你最好的同事。现在它们可以正确地重构、导航和分析。
|
||||
|
||||
- **lsp_hover**:位置处的类型信息、文档、签名
|
||||
- **lsp_goto_definition**:跳转到符号定义
|
||||
- **lsp_find_references**:查找工作区中的所有使用
|
||||
- **lsp_document_symbols**:获取文件符号概览
|
||||
- **lsp_workspace_symbols**:按名称在项目中搜索符号
|
||||
- **lsp_symbols**:从文件获取符号 (scope='document') 或在工作区中搜索 (scope='workspace')
|
||||
- **lsp_diagnostics**:在构建前获取错误/警告
|
||||
- **lsp_servers**:列出可用的 LSP 服务器
|
||||
- **lsp_prepare_rename**:验证重命名操作
|
||||
- **lsp_rename**:在工作区中重命名符号
|
||||
- **lsp_code_actions**:获取可用的快速修复/重构
|
||||
- **lsp_code_action_resolve**:应用代码操作
|
||||
- **ast_grep_search**:AST 感知的代码模式搜索(25 种语言)
|
||||
- **ast_grep_replace**:AST 感知的代码替换
|
||||
- **call_omo_agent**:生成专业的 explore/librarian 智能体。支持 `run_in_background` 参数进行异步执行。
|
||||
|
||||
@@ -198,7 +198,7 @@ export const DynamicContextPruningConfigSchema = z.object({
|
||||
/** Tools that should never be pruned */
|
||||
protected_tools: z.array(z.string()).default([
|
||||
"task", "todowrite", "todoread",
|
||||
"lsp_rename", "lsp_code_action_resolve",
|
||||
"lsp_rename",
|
||||
"session_read", "session_write", "session_search",
|
||||
]),
|
||||
/** Pruning strategies configuration */
|
||||
|
||||
@@ -117,13 +117,13 @@ If \`--create-new\`: Read all existing first (preserve context) → then delete
|
||||
lsp_servers() # Check availability
|
||||
|
||||
# Entry points (parallel)
|
||||
lsp_document_symbols(filePath="src/index.ts")
|
||||
lsp_document_symbols(filePath="main.py")
|
||||
lsp_symbols(filePath="src/index.ts", scope="document")
|
||||
lsp_symbols(filePath="main.py", scope="document")
|
||||
|
||||
# Key symbols (parallel)
|
||||
lsp_workspace_symbols(filePath=".", query="class")
|
||||
lsp_workspace_symbols(filePath=".", query="interface")
|
||||
lsp_workspace_symbols(filePath=".", query="function")
|
||||
lsp_symbols(filePath=".", scope="workspace", query="class")
|
||||
lsp_symbols(filePath=".", scope="workspace", query="interface")
|
||||
lsp_symbols(filePath=".", scope="workspace", query="function")
|
||||
|
||||
# Centrality for top exports
|
||||
lsp_find_references(filePath="...", line=X, character=Y)
|
||||
|
||||
@@ -148,20 +148,15 @@ While background agents are running, use direct tools:
|
||||
### LSP Tools for Precise Analysis:
|
||||
|
||||
\`\`\`typescript
|
||||
// Get symbol information at target location
|
||||
lsp_hover(filePath, line, character) // Type info, docs, signatures
|
||||
|
||||
// Find definition(s)
|
||||
lsp_goto_definition(filePath, line, character) // Where is it defined?
|
||||
|
||||
// Find ALL usages across workspace
|
||||
lsp_find_references(filePath, line, character, includeDeclaration=true)
|
||||
|
||||
// Get file structure
|
||||
lsp_document_symbols(filePath) // Hierarchical outline
|
||||
|
||||
// Search symbols by name
|
||||
lsp_workspace_symbols(filePath, query="[target_symbol]")
|
||||
// Get file structure (scope='document') or search symbols (scope='workspace')
|
||||
lsp_symbols(filePath, scope="document") // Hierarchical outline
|
||||
lsp_symbols(filePath, scope="workspace", query="[target_symbol]") // Search by name
|
||||
|
||||
// Get current diagnostics
|
||||
lsp_diagnostics(filePath) // Errors, warnings before we start
|
||||
@@ -593,7 +588,7 @@ You already know these tools. Use them intelligently:
|
||||
|
||||
## LSP Tools
|
||||
Leverage the full LSP toolset (\`lsp_*\`) for precision analysis. Key patterns:
|
||||
- **Understand before changing**: \`lsp_hover\`, \`lsp_goto_definition\` to grasp context
|
||||
- **Understand before changing**: \`lsp_goto_definition\` to grasp context
|
||||
- **Impact analysis**: \`lsp_find_references\` to map all usages before modification
|
||||
- **Safe refactoring**: \`lsp_prepare_rename\` → \`lsp_rename\` for symbol renames
|
||||
- **Continuous verification**: \`lsp_diagnostics\` after every change
|
||||
|
||||
@@ -320,7 +320,6 @@ export async function executeCompact(
|
||||
"todowrite",
|
||||
"todoread",
|
||||
"lsp_rename",
|
||||
"lsp_code_action_resolve",
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ const DEFAULT_PROTECTED_TOOLS = new Set([
|
||||
"todowrite",
|
||||
"todoread",
|
||||
"lsp_rename",
|
||||
"lsp_code_action_resolve",
|
||||
"session_read",
|
||||
"session_write",
|
||||
"session_search",
|
||||
|
||||
@@ -13,8 +13,7 @@ const TRUNCATABLE_TOOLS = [
|
||||
"Glob",
|
||||
"safe_glob",
|
||||
"lsp_find_references",
|
||||
"lsp_document_symbols",
|
||||
"lsp_workspace_symbols",
|
||||
"lsp_symbols",
|
||||
"lsp_diagnostics",
|
||||
"ast_grep_search",
|
||||
"interactive_bash",
|
||||
|
||||
@@ -30,7 +30,7 @@ tools/
|
||||
## TOOL CATEGORIES
|
||||
| Category | Tools | Purpose |
|
||||
|----------|-------|---------|
|
||||
| LSP | lsp_hover, lsp_goto_definition, lsp_find_references, lsp_diagnostics, lsp_rename, etc. | IDE-grade code intelligence (11 tools) |
|
||||
| LSP | lsp_goto_definition, lsp_find_references, lsp_symbols, lsp_diagnostics, lsp_rename, etc. | IDE-grade code intelligence (7 tools) |
|
||||
| AST | ast_grep_search, ast_grep_replace | Structural pattern matching/rewriting |
|
||||
| Search | grep, glob | Timeout-safe file and content search |
|
||||
| Session | session_list, session_read, session_search, session_info | History navigation and retrieval |
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import {
|
||||
lsp_hover,
|
||||
lsp_goto_definition,
|
||||
lsp_find_references,
|
||||
lsp_document_symbols,
|
||||
lsp_workspace_symbols,
|
||||
lsp_symbols,
|
||||
lsp_diagnostics,
|
||||
lsp_servers,
|
||||
lsp_prepare_rename,
|
||||
lsp_rename,
|
||||
lsp_code_actions,
|
||||
lsp_code_action_resolve,
|
||||
lspManager,
|
||||
} from "./lsp"
|
||||
|
||||
@@ -60,17 +56,13 @@ export function createBackgroundTools(manager: BackgroundManager, client: Openco
|
||||
}
|
||||
|
||||
export const builtinTools: Record<string, ToolDefinition> = {
|
||||
lsp_hover,
|
||||
lsp_goto_definition,
|
||||
lsp_find_references,
|
||||
lsp_document_symbols,
|
||||
lsp_workspace_symbols,
|
||||
lsp_symbols,
|
||||
lsp_diagnostics,
|
||||
lsp_servers,
|
||||
lsp_prepare_rename,
|
||||
lsp_rename,
|
||||
lsp_code_actions,
|
||||
lsp_code_action_resolve,
|
||||
ast_grep_search,
|
||||
ast_grep_replace,
|
||||
grep,
|
||||
|
||||
@@ -7,19 +7,16 @@ import {
|
||||
} from "./constants"
|
||||
import {
|
||||
withLspClient,
|
||||
formatHoverResult,
|
||||
formatLocation,
|
||||
formatDocumentSymbol,
|
||||
formatSymbolInfo,
|
||||
formatDiagnostic,
|
||||
filterDiagnosticsBySeverity,
|
||||
formatPrepareRenameResult,
|
||||
formatCodeActions,
|
||||
applyWorkspaceEdit,
|
||||
formatApplyResult,
|
||||
} from "./utils"
|
||||
import type {
|
||||
HoverResult,
|
||||
Location,
|
||||
LocationLink,
|
||||
DocumentSymbol,
|
||||
@@ -28,33 +25,10 @@ import type {
|
||||
PrepareRenameResult,
|
||||
PrepareRenameDefaultBehavior,
|
||||
WorkspaceEdit,
|
||||
CodeAction,
|
||||
Command,
|
||||
} from "./types"
|
||||
|
||||
|
||||
|
||||
export const lsp_hover: ToolDefinition = tool({
|
||||
description: "Get type info, docs, and signature for a symbol at position.",
|
||||
args: {
|
||||
filePath: tool.schema.string(),
|
||||
line: tool.schema.number().min(1).describe("1-based"),
|
||||
character: tool.schema.number().min(0).describe("0-based"),
|
||||
},
|
||||
execute: async (args, context) => {
|
||||
try {
|
||||
const result = await withLspClient(args.filePath, async (client) => {
|
||||
return (await client.hover(args.filePath, args.line, args.character)) as HoverResult | null
|
||||
})
|
||||
const output = formatHoverResult(result)
|
||||
return output
|
||||
} catch (e) {
|
||||
const output = `Error: ${e instanceof Error ? e.message : String(e)}`
|
||||
return output
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
export const lsp_goto_definition: ToolDefinition = tool({
|
||||
description: "Jump to symbol definition. Find WHERE something is defined.",
|
||||
args: {
|
||||
@@ -129,60 +103,29 @@ export const lsp_find_references: ToolDefinition = tool({
|
||||
},
|
||||
})
|
||||
|
||||
export const lsp_document_symbols: ToolDefinition = tool({
|
||||
description: "Get hierarchical outline of all symbols in a file.",
|
||||
export const lsp_symbols: ToolDefinition = tool({
|
||||
description: "Get symbols from file (document) or search across workspace. Use scope='document' for file outline, scope='workspace' for project-wide symbol search.",
|
||||
args: {
|
||||
filePath: tool.schema.string(),
|
||||
filePath: tool.schema.string().describe("File path for LSP context"),
|
||||
scope: tool.schema.enum(["document", "workspace"]).default("document").describe("'document' for file symbols, 'workspace' for project-wide search"),
|
||||
query: tool.schema.string().optional().describe("Symbol name to search (required for workspace scope)"),
|
||||
limit: tool.schema.number().optional().describe("Max results (default 50)"),
|
||||
},
|
||||
execute: async (args, context) => {
|
||||
try {
|
||||
const scope = args.scope ?? "document"
|
||||
|
||||
if (scope === "workspace") {
|
||||
if (!args.query) {
|
||||
return "Error: 'query' is required for workspace scope"
|
||||
}
|
||||
|
||||
const result = await withLspClient(args.filePath, async (client) => {
|
||||
return (await client.documentSymbols(args.filePath)) as DocumentSymbol[] | SymbolInfo[] | null
|
||||
return (await client.workspaceSymbols(args.query!)) as SymbolInfo[] | null
|
||||
})
|
||||
|
||||
if (!result || result.length === 0) {
|
||||
const output = "No symbols found"
|
||||
return output
|
||||
}
|
||||
|
||||
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}):`)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
export const lsp_workspace_symbols: ToolDefinition = tool({
|
||||
description: "Search symbols by name across ENTIRE workspace.",
|
||||
args: {
|
||||
filePath: tool.schema.string(),
|
||||
query: tool.schema.string().describe("Symbol name (fuzzy match)"),
|
||||
limit: tool.schema.number().optional().describe("Max results"),
|
||||
},
|
||||
execute: async (args, context) => {
|
||||
try {
|
||||
const result = await withLspClient(args.filePath, async (client) => {
|
||||
return (await client.workspaceSymbols(args.query)) as SymbolInfo[] | null
|
||||
})
|
||||
|
||||
if (!result || result.length === 0) {
|
||||
const output = "No symbols found"
|
||||
return output
|
||||
return "No symbols found"
|
||||
}
|
||||
|
||||
const total = result.length
|
||||
@@ -193,11 +136,35 @@ export const lsp_workspace_symbols: ToolDefinition = tool({
|
||||
if (truncated) {
|
||||
lines.unshift(`Found ${total} symbols (showing first ${limit}):`)
|
||||
}
|
||||
const output = lines.join("\n")
|
||||
return output
|
||||
return lines.join("\n")
|
||||
} else {
|
||||
const result = await withLspClient(args.filePath, async (client) => {
|
||||
return (await client.documentSymbols(args.filePath)) as DocumentSymbol[] | SymbolInfo[] | null
|
||||
})
|
||||
|
||||
if (!result || result.length === 0) {
|
||||
return "No symbols found"
|
||||
}
|
||||
|
||||
const total = result.length
|
||||
const limit = Math.min(args.limit ?? DEFAULT_MAX_SYMBOLS, DEFAULT_MAX_SYMBOLS)
|
||||
const truncated = total > limit
|
||||
const limited = truncated ? result.slice(0, limit) : result
|
||||
|
||||
const lines: string[] = []
|
||||
if (truncated) {
|
||||
lines.push(`Found ${total} symbols (showing first ${limit}):`)
|
||||
}
|
||||
|
||||
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
|
||||
return `Error: ${e instanceof Error ? e.message : String(e)}`
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -317,89 +284,3 @@ export const lsp_rename: ToolDefinition = tool({
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
export const lsp_code_actions: ToolDefinition = tool({
|
||||
description: "Get available quick fixes, refactorings, and source actions (organize imports, fix all).",
|
||||
args: {
|
||||
filePath: tool.schema.string(),
|
||||
startLine: tool.schema.number().min(1).describe("1-based"),
|
||||
startCharacter: tool.schema.number().min(0).describe("0-based"),
|
||||
endLine: tool.schema.number().min(1).describe("1-based"),
|
||||
endCharacter: tool.schema.number().min(0).describe("0-based"),
|
||||
kind: tool.schema
|
||||
.enum([
|
||||
"quickfix",
|
||||
"refactor",
|
||||
"refactor.extract",
|
||||
"refactor.inline",
|
||||
"refactor.rewrite",
|
||||
"source",
|
||||
"source.organizeImports",
|
||||
"source.fixAll",
|
||||
])
|
||||
.optional()
|
||||
.describe("Filter by code action kind"),
|
||||
},
|
||||
execute: async (args, context) => {
|
||||
try {
|
||||
const only = args.kind ? [args.kind] : undefined
|
||||
const result = await withLspClient(args.filePath, async (client) => {
|
||||
return (await client.codeAction(
|
||||
args.filePath,
|
||||
args.startLine,
|
||||
args.startCharacter,
|
||||
args.endLine,
|
||||
args.endCharacter,
|
||||
only
|
||||
)) as (CodeAction | Command)[] | null
|
||||
})
|
||||
const output = formatCodeActions(result)
|
||||
return output
|
||||
} catch (e) {
|
||||
const output = `Error: ${e instanceof Error ? e.message : String(e)}`
|
||||
return output
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
export const lsp_code_action_resolve: ToolDefinition = tool({
|
||||
description: "Resolve and APPLY a code action from lsp_code_actions.",
|
||||
args: {
|
||||
filePath: tool.schema.string(),
|
||||
codeAction: tool.schema.string().describe("Code action JSON from lsp_code_actions"),
|
||||
},
|
||||
execute: async (args, context) => {
|
||||
try {
|
||||
const codeAction = JSON.parse(args.codeAction) as CodeAction
|
||||
const resolved = await withLspClient(args.filePath, async (client) => {
|
||||
return (await client.codeActionResolve(codeAction)) as CodeAction | null
|
||||
})
|
||||
|
||||
if (!resolved) {
|
||||
const output = "Failed to resolve code action"
|
||||
return output
|
||||
}
|
||||
|
||||
const lines: string[] = []
|
||||
lines.push(`Action: ${resolved.title}`)
|
||||
if (resolved.kind) lines.push(`Kind: ${resolved.kind}`)
|
||||
|
||||
if (resolved.edit) {
|
||||
const result = applyWorkspaceEdit(resolved.edit)
|
||||
lines.push(formatApplyResult(result))
|
||||
} else {
|
||||
lines.push("No edit to apply")
|
||||
}
|
||||
|
||||
if (resolved.command) {
|
||||
lines.push(`Command: ${resolved.command.title} (${resolved.command.command}) - not executed`)
|
||||
}
|
||||
|
||||
const output = lines.join("\n")
|
||||
return output
|
||||
} catch (e) {
|
||||
const output = `Error: ${e instanceof Error ? e.message : String(e)}`
|
||||
return output
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user