gencode-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
# Proposal: LSP Tool
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0014
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement an LSP (Language Server Protocol) tool that provides code intelligence features like go-to-definition, find-references, hover documentation, and symbol search. This enables the agent to navigate codebases with the same precision as modern IDEs.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Currently, mycode relies on text-based search (Grep, Glob) for code navigation. This leads to:
|
|
16
|
+
|
|
17
|
+
1. **Imprecise results**: Text search finds string matches, not semantic references
|
|
18
|
+
2. **No type information**: Can't determine variable types or function signatures
|
|
19
|
+
3. **No call hierarchy**: Can't trace function call relationships
|
|
20
|
+
4. **Limited understanding**: Agent must infer code structure from text patterns
|
|
21
|
+
5. **Slower exploration**: Multiple searches needed to understand relationships
|
|
22
|
+
|
|
23
|
+
An LSP tool provides IDE-quality code intelligence for precise navigation.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code's LSP tool provides comprehensive code intelligence:
|
|
28
|
+
|
|
29
|
+
### Tool Definition
|
|
30
|
+
```typescript
|
|
31
|
+
LSP({
|
|
32
|
+
operation: "goToDefinition",
|
|
33
|
+
filePath: "/path/to/file.ts",
|
|
34
|
+
line: 42,
|
|
35
|
+
character: 15
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Supported Operations
|
|
40
|
+
| Operation | Description |
|
|
41
|
+
|-----------|-------------|
|
|
42
|
+
| `goToDefinition` | Find where a symbol is defined |
|
|
43
|
+
| `findReferences` | Find all references to a symbol |
|
|
44
|
+
| `hover` | Get documentation and type info |
|
|
45
|
+
| `documentSymbol` | Get all symbols in a document |
|
|
46
|
+
| `workspaceSymbol` | Search symbols across workspace |
|
|
47
|
+
| `goToImplementation` | Find interface implementations |
|
|
48
|
+
| `prepareCallHierarchy` | Get call hierarchy item at position |
|
|
49
|
+
| `incomingCalls` | Find callers of a function |
|
|
50
|
+
| `outgoingCalls` | Find callees from a function |
|
|
51
|
+
|
|
52
|
+
### Key Characteristics
|
|
53
|
+
- Position-based (1-indexed line and character)
|
|
54
|
+
- Requires configured LSP server for file type
|
|
55
|
+
- Graceful fallback when no server available
|
|
56
|
+
- Returns structured location data
|
|
57
|
+
|
|
58
|
+
### Example Usage
|
|
59
|
+
```
|
|
60
|
+
User: Where is the AuthService class defined?
|
|
61
|
+
|
|
62
|
+
Agent: Let me find the definition.
|
|
63
|
+
[LSP: goToDefinition on AuthService at line 15, char 10]
|
|
64
|
+
|
|
65
|
+
AuthService is defined at:
|
|
66
|
+
src/services/auth.ts:25
|
|
67
|
+
|
|
68
|
+
The class has the following methods:
|
|
69
|
+
- login(email: string, password: string): Promise<User>
|
|
70
|
+
- logout(): void
|
|
71
|
+
- refreshToken(): Promise<string>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Detailed Design
|
|
75
|
+
|
|
76
|
+
### API Design
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// src/tools/lsp/types.ts
|
|
80
|
+
type LSPOperation =
|
|
81
|
+
| 'goToDefinition'
|
|
82
|
+
| 'findReferences'
|
|
83
|
+
| 'hover'
|
|
84
|
+
| 'documentSymbol'
|
|
85
|
+
| 'workspaceSymbol'
|
|
86
|
+
| 'goToImplementation'
|
|
87
|
+
| 'prepareCallHierarchy'
|
|
88
|
+
| 'incomingCalls'
|
|
89
|
+
| 'outgoingCalls';
|
|
90
|
+
|
|
91
|
+
interface LSPInput {
|
|
92
|
+
operation: LSPOperation;
|
|
93
|
+
filePath: string;
|
|
94
|
+
line: number; // 1-based line number
|
|
95
|
+
character: number; // 1-based character offset
|
|
96
|
+
query?: string; // For workspaceSymbol search
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface Location {
|
|
100
|
+
uri: string;
|
|
101
|
+
range: {
|
|
102
|
+
start: { line: number; character: number };
|
|
103
|
+
end: { line: number; character: number };
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface Symbol {
|
|
108
|
+
name: string;
|
|
109
|
+
kind: SymbolKind;
|
|
110
|
+
location: Location;
|
|
111
|
+
containerName?: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface HoverInfo {
|
|
115
|
+
contents: string; // Markdown formatted
|
|
116
|
+
range?: Location['range'];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
interface CallHierarchyItem {
|
|
120
|
+
name: string;
|
|
121
|
+
kind: SymbolKind;
|
|
122
|
+
uri: string;
|
|
123
|
+
range: Location['range'];
|
|
124
|
+
selectionRange: Location['range'];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface LSPOutput {
|
|
128
|
+
success: boolean;
|
|
129
|
+
operation: LSPOperation;
|
|
130
|
+
result?: {
|
|
131
|
+
definitions?: Location[];
|
|
132
|
+
references?: Location[];
|
|
133
|
+
hover?: HoverInfo;
|
|
134
|
+
symbols?: Symbol[];
|
|
135
|
+
callItems?: CallHierarchyItem[];
|
|
136
|
+
incomingCalls?: { from: CallHierarchyItem; fromRanges: Location['range'][] }[];
|
|
137
|
+
outgoingCalls?: { to: CallHierarchyItem; fromRanges: Location['range'][] }[];
|
|
138
|
+
};
|
|
139
|
+
error?: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
type SymbolKind =
|
|
143
|
+
| 'File' | 'Module' | 'Namespace' | 'Package'
|
|
144
|
+
| 'Class' | 'Method' | 'Property' | 'Field'
|
|
145
|
+
| 'Constructor' | 'Enum' | 'Interface' | 'Function'
|
|
146
|
+
| 'Variable' | 'Constant' | 'String' | 'Number'
|
|
147
|
+
| 'Boolean' | 'Array' | 'Object' | 'Key'
|
|
148
|
+
| 'Null' | 'EnumMember' | 'Struct' | 'Event'
|
|
149
|
+
| 'Operator' | 'TypeParameter';
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// src/tools/lsp/lsp-tool.ts
|
|
154
|
+
const lspTool: Tool<LSPInput> = {
|
|
155
|
+
name: 'LSP',
|
|
156
|
+
description: `Interact with Language Server Protocol for code intelligence.
|
|
157
|
+
|
|
158
|
+
Operations:
|
|
159
|
+
- goToDefinition: Find where a symbol is defined
|
|
160
|
+
- findReferences: Find all references to a symbol
|
|
161
|
+
- hover: Get documentation and type info for a symbol
|
|
162
|
+
- documentSymbol: Get all symbols in a document
|
|
163
|
+
- workspaceSymbol: Search for symbols across workspace
|
|
164
|
+
- goToImplementation: Find implementations of interface/abstract
|
|
165
|
+
- prepareCallHierarchy: Get call hierarchy item at position
|
|
166
|
+
- incomingCalls: Find all callers of a function
|
|
167
|
+
- outgoingCalls: Find all functions called by a function
|
|
168
|
+
|
|
169
|
+
Parameters:
|
|
170
|
+
- operation: The LSP operation to perform
|
|
171
|
+
- filePath: Path to the file (absolute or relative)
|
|
172
|
+
- line: Line number (1-based, as shown in editors)
|
|
173
|
+
- character: Character offset (1-based, as shown in editors)
|
|
174
|
+
|
|
175
|
+
Note: LSP servers must be configured for the file type.
|
|
176
|
+
Returns error if no server is available.
|
|
177
|
+
`,
|
|
178
|
+
parameters: z.object({
|
|
179
|
+
operation: z.enum([
|
|
180
|
+
'goToDefinition', 'findReferences', 'hover',
|
|
181
|
+
'documentSymbol', 'workspaceSymbol', 'goToImplementation',
|
|
182
|
+
'prepareCallHierarchy', 'incomingCalls', 'outgoingCalls'
|
|
183
|
+
]),
|
|
184
|
+
filePath: z.string(),
|
|
185
|
+
line: z.number().int().positive(),
|
|
186
|
+
character: z.number().int().positive(),
|
|
187
|
+
query: z.string().optional()
|
|
188
|
+
}),
|
|
189
|
+
execute: async (input, context) => { ... }
|
|
190
|
+
};
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Implementation Approach
|
|
194
|
+
|
|
195
|
+
1. **Server Management**: Maintain pool of LSP servers by language
|
|
196
|
+
2. **Protocol Communication**: JSON-RPC over stdio/socket
|
|
197
|
+
3. **Document Sync**: Keep servers informed of file changes
|
|
198
|
+
4. **Result Mapping**: Convert LSP results to our format
|
|
199
|
+
5. **Graceful Degradation**: Return helpful error when no server
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// src/tools/lsp/server-manager.ts
|
|
203
|
+
interface LSPServerConfig {
|
|
204
|
+
language: string;
|
|
205
|
+
command: string;
|
|
206
|
+
args: string[];
|
|
207
|
+
rootPath?: string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const DEFAULT_SERVERS: Record<string, LSPServerConfig> = {
|
|
211
|
+
typescript: {
|
|
212
|
+
language: 'typescript',
|
|
213
|
+
command: 'typescript-language-server',
|
|
214
|
+
args: ['--stdio']
|
|
215
|
+
},
|
|
216
|
+
javascript: {
|
|
217
|
+
language: 'javascript',
|
|
218
|
+
command: 'typescript-language-server',
|
|
219
|
+
args: ['--stdio']
|
|
220
|
+
},
|
|
221
|
+
python: {
|
|
222
|
+
language: 'python',
|
|
223
|
+
command: 'pylsp',
|
|
224
|
+
args: []
|
|
225
|
+
},
|
|
226
|
+
go: {
|
|
227
|
+
language: 'go',
|
|
228
|
+
command: 'gopls',
|
|
229
|
+
args: []
|
|
230
|
+
},
|
|
231
|
+
rust: {
|
|
232
|
+
language: 'rust',
|
|
233
|
+
command: 'rust-analyzer',
|
|
234
|
+
args: []
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
class LSPServerManager {
|
|
239
|
+
private servers: Map<string, LanguageServer> = new Map();
|
|
240
|
+
|
|
241
|
+
async getServer(filePath: string): Promise<LanguageServer | null> {
|
|
242
|
+
const language = detectLanguage(filePath);
|
|
243
|
+
|
|
244
|
+
if (this.servers.has(language)) {
|
|
245
|
+
return this.servers.get(language)!;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const config = DEFAULT_SERVERS[language];
|
|
249
|
+
if (!config) return null;
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const server = await this.startServer(config);
|
|
253
|
+
this.servers.set(language, server);
|
|
254
|
+
return server;
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.warn(`Failed to start LSP server for ${language}:`, error);
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private async startServer(config: LSPServerConfig): Promise<LanguageServer> {
|
|
262
|
+
const process = spawn(config.command, config.args, { stdio: 'pipe' });
|
|
263
|
+
const server = new LanguageServer(process);
|
|
264
|
+
await server.initialize({ rootPath: config.rootPath || process.cwd() });
|
|
265
|
+
return server;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async shutdown(): Promise<void> {
|
|
269
|
+
for (const server of this.servers.values()) {
|
|
270
|
+
await server.shutdown();
|
|
271
|
+
}
|
|
272
|
+
this.servers.clear();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Core LSP client implementation
|
|
279
|
+
class LanguageServer {
|
|
280
|
+
private process: ChildProcess;
|
|
281
|
+
private requestId: number = 0;
|
|
282
|
+
private pendingRequests: Map<number, { resolve: Function; reject: Function }>;
|
|
283
|
+
|
|
284
|
+
async goToDefinition(uri: string, line: number, char: number): Promise<Location[]> {
|
|
285
|
+
return this.request('textDocument/definition', {
|
|
286
|
+
textDocument: { uri },
|
|
287
|
+
position: { line: line - 1, character: char - 1 } // Convert to 0-based
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async findReferences(uri: string, line: number, char: number): Promise<Location[]> {
|
|
292
|
+
return this.request('textDocument/references', {
|
|
293
|
+
textDocument: { uri },
|
|
294
|
+
position: { line: line - 1, character: char - 1 },
|
|
295
|
+
context: { includeDeclaration: true }
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async hover(uri: string, line: number, char: number): Promise<HoverInfo | null> {
|
|
300
|
+
const result = await this.request('textDocument/hover', {
|
|
301
|
+
textDocument: { uri },
|
|
302
|
+
position: { line: line - 1, character: char - 1 }
|
|
303
|
+
});
|
|
304
|
+
if (!result) return null;
|
|
305
|
+
return {
|
|
306
|
+
contents: formatHoverContents(result.contents),
|
|
307
|
+
range: result.range
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
private async request(method: string, params: unknown): Promise<unknown> {
|
|
312
|
+
const id = this.requestId++;
|
|
313
|
+
return new Promise((resolve, reject) => {
|
|
314
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
315
|
+
this.send({ jsonrpc: '2.0', id, method, params });
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### File Changes
|
|
322
|
+
|
|
323
|
+
| File | Action | Description |
|
|
324
|
+
|------|--------|-------------|
|
|
325
|
+
| `src/tools/lsp/types.ts` | Create | LSP type definitions |
|
|
326
|
+
| `src/tools/lsp/lsp-tool.ts` | Create | Tool implementation |
|
|
327
|
+
| `src/tools/lsp/server-manager.ts` | Create | LSP server lifecycle |
|
|
328
|
+
| `src/tools/lsp/language-server.ts` | Create | LSP protocol client |
|
|
329
|
+
| `src/tools/lsp/utils.ts` | Create | Helper functions |
|
|
330
|
+
| `src/tools/lsp/index.ts` | Create | Module exports |
|
|
331
|
+
| `src/tools/index.ts` | Modify | Register LSP tool |
|
|
332
|
+
| `package.json` | Modify | Add vscode-languageserver-protocol |
|
|
333
|
+
|
|
334
|
+
## User Experience
|
|
335
|
+
|
|
336
|
+
### Go to Definition
|
|
337
|
+
```
|
|
338
|
+
Agent: Let me find where AuthService is defined.
|
|
339
|
+
|
|
340
|
+
[LSP: goToDefinition at src/api/users.ts:15:10]
|
|
341
|
+
|
|
342
|
+
┌─ Definition ──────────────────────────────────────┐
|
|
343
|
+
│ Symbol: AuthService │
|
|
344
|
+
│ Location: src/services/auth.ts:25:1 │
|
|
345
|
+
│ Kind: Class │
|
|
346
|
+
└───────────────────────────────────────────────────┘
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Find References
|
|
350
|
+
```
|
|
351
|
+
Agent: I'll find all usages of the getUserById function.
|
|
352
|
+
|
|
353
|
+
[LSP: findReferences at src/services/users.ts:42:15]
|
|
354
|
+
|
|
355
|
+
┌─ References (8 found) ────────────────────────────┐
|
|
356
|
+
│ src/api/users.ts:15 │
|
|
357
|
+
│ src/api/admin.ts:78 │
|
|
358
|
+
│ src/services/auth.ts:92 │
|
|
359
|
+
│ src/hooks/useUser.ts:23 │
|
|
360
|
+
│ src/tests/users.test.ts:45, 67, 89, 102 │
|
|
361
|
+
└───────────────────────────────────────────────────┘
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Hover Information
|
|
365
|
+
```
|
|
366
|
+
Agent: Let me check the type of this variable.
|
|
367
|
+
|
|
368
|
+
[LSP: hover at src/components/UserCard.tsx:18:12]
|
|
369
|
+
|
|
370
|
+
┌─ Hover Info ──────────────────────────────────────┐
|
|
371
|
+
│ (parameter) user: User │
|
|
372
|
+
│ │
|
|
373
|
+
│ Represents a user in the system. │
|
|
374
|
+
│ │
|
|
375
|
+
│ @interface User │
|
|
376
|
+
│ @property {string} id - Unique identifier │
|
|
377
|
+
│ @property {string} email - User email │
|
|
378
|
+
│ @property {string} name - Display name │
|
|
379
|
+
└───────────────────────────────────────────────────┘
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Call Hierarchy
|
|
383
|
+
```
|
|
384
|
+
Agent: Let me trace who calls this function.
|
|
385
|
+
|
|
386
|
+
[LSP: incomingCalls at src/services/api.ts:156:10]
|
|
387
|
+
|
|
388
|
+
┌─ Incoming Calls to fetchData() ───────────────────┐
|
|
389
|
+
│ ← useQuery (src/hooks/useQuery.ts:34) │
|
|
390
|
+
│ ← loadInitialData (src/app/init.ts:78) │
|
|
391
|
+
│ ← refreshCache (src/services/cache.ts:45) │
|
|
392
|
+
└───────────────────────────────────────────────────┘
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### No Server Available
|
|
396
|
+
```
|
|
397
|
+
Agent: [LSP: goToDefinition on file.xyz:10:5]
|
|
398
|
+
|
|
399
|
+
No LSP server configured for .xyz files.
|
|
400
|
+
Falling back to text-based search.
|
|
401
|
+
|
|
402
|
+
[Grep: searching for definition...]
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Alternatives Considered
|
|
406
|
+
|
|
407
|
+
### Alternative 1: Built-in Parser
|
|
408
|
+
Parse code directly without external servers.
|
|
409
|
+
|
|
410
|
+
**Pros**: No external dependencies, always available
|
|
411
|
+
**Cons**: Complex to support multiple languages accurately
|
|
412
|
+
**Decision**: Rejected - LSP provides better accuracy
|
|
413
|
+
|
|
414
|
+
### Alternative 2: Tree-sitter Integration
|
|
415
|
+
Use tree-sitter for parsing.
|
|
416
|
+
|
|
417
|
+
**Pros**: Fast, incremental parsing
|
|
418
|
+
**Cons**: Query language learning curve, less semantic info
|
|
419
|
+
**Decision**: Considered for fallback
|
|
420
|
+
|
|
421
|
+
### Alternative 3: IDE Extension Only
|
|
422
|
+
Require VS Code or similar IDE.
|
|
423
|
+
|
|
424
|
+
**Pros**: Guaranteed LSP availability
|
|
425
|
+
**Cons**: Limits CLI-only usage
|
|
426
|
+
**Decision**: Rejected - CLI independence is important
|
|
427
|
+
|
|
428
|
+
## Security Considerations
|
|
429
|
+
|
|
430
|
+
1. **Process Isolation**: LSP servers run in separate processes
|
|
431
|
+
2. **Resource Limits**: Limit memory and CPU per server
|
|
432
|
+
3. **Timeout**: Kill unresponsive servers
|
|
433
|
+
4. **Path Validation**: Only access files in workspace
|
|
434
|
+
5. **No Arbitrary Code**: LSP servers don't execute user code
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
const SERVER_LIMITS = {
|
|
438
|
+
maxMemoryMB: 512,
|
|
439
|
+
startupTimeoutMs: 30000,
|
|
440
|
+
requestTimeoutMs: 10000,
|
|
441
|
+
maxServers: 5
|
|
442
|
+
};
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Testing Strategy
|
|
446
|
+
|
|
447
|
+
1. **Unit Tests**:
|
|
448
|
+
- Protocol message formatting
|
|
449
|
+
- Result parsing
|
|
450
|
+
- Server lifecycle
|
|
451
|
+
|
|
452
|
+
2. **Integration Tests**:
|
|
453
|
+
- TypeScript server operations
|
|
454
|
+
- Python server operations
|
|
455
|
+
- Multi-language projects
|
|
456
|
+
|
|
457
|
+
3. **Manual Testing**:
|
|
458
|
+
- Large codebases
|
|
459
|
+
- Cross-file references
|
|
460
|
+
- Complex type hierarchies
|
|
461
|
+
|
|
462
|
+
## Migration Path
|
|
463
|
+
|
|
464
|
+
1. **Phase 1**: TypeScript/JavaScript server
|
|
465
|
+
2. **Phase 2**: Python, Go, Rust servers
|
|
466
|
+
3. **Phase 3**: Custom server configuration
|
|
467
|
+
4. **Phase 4**: Auto-install missing servers
|
|
468
|
+
5. **Phase 5**: IDE integration for shared servers
|
|
469
|
+
|
|
470
|
+
No breaking changes to existing tools.
|
|
471
|
+
|
|
472
|
+
## References
|
|
473
|
+
|
|
474
|
+
- [Language Server Protocol Specification](https://microsoft.github.io/language-server-protocol/)
|
|
475
|
+
- [VSCode Language Server Node](https://github.com/microsoft/vscode-languageserver-node)
|
|
476
|
+
- [typescript-language-server](https://github.com/typescript-language-server/typescript-language-server)
|
|
477
|
+
- [gopls - Go Language Server](https://pkg.go.dev/golang.org/x/tools/gopls)
|
|
478
|
+
- [rust-analyzer](https://rust-analyzer.github.io/)
|