Files
Claude-Code-Workflow/codex-lens/docs/CODEXLENS_LSP_API_SPEC.md
catlog22 f14418603a feat(cli): 添加 --rule 选项支持模板自动发现
重构 ccw cli 模板系统:

- 新增 template-discovery.ts 模块,支持扁平化模板自动发现
- 添加 --rule <template> 选项,自动加载 protocol 和 template
- 模板目录从嵌套结构 (prompts/category/file.txt) 迁移到扁平结构 (prompts/category-function.txt)
- 更新所有 agent/command 文件,使用 $PROTO $TMPL 环境变量替代 $(cat ...) 模式
- 支持模糊匹配:--rule 02-review-architecture 可匹配 analysis-review-architecture.txt

其他更新:
- Dashboard: 添加 Claude Manager 和 Issue Manager 页面
- Codex-lens: 增强 chain_search 和 clustering 模块

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 19:20:24 +08:00

677 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Codexlens LSP API 规范
**版本**: 1.1
**状态**: ✅ APPROVED (Gemini Review)
**架构**: codexlens 提供 Python APICCW 实现 MCP 端点
**分析来源**: Gemini (架构评审) + Codex (实现评审)
**最后更新**: 2025-01-17
---
## 一、概述
### 1.1 背景
基于 cclsp MCP 服务器实现的分析,设计 codexlens 的 LSP 搜索方法接口,为 AI 提供代码智能能力。
### 1.2 架构决策
**MCP 端点由 CCW 实现codexlens 只提供 Python API**
```
┌─────────────────────────────────────────────────────────────┐
│ Claude Code │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ MCP Client │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ CCW MCP Server │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ MCP Tool Handlers │ │ │
│ │ │ • codexlens_file_context │ │ │
│ │ │ • codexlens_find_definition │ │ │
│ │ │ • codexlens_find_references │ │ │
│ │ │ • codexlens_semantic_search │ │ │
│ │ └──────────────────────┬──────────────────────────┘ │ │
│ └─────────────────────────┼─────────────────────────────┘ │
└────────────────────────────┼────────────────────────────────┘
│ Python API 调用
┌─────────────────────────────────────────────────────────────┐
│ codexlens │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Public API Layer │ │
│ │ codexlens.api.file_context() │ │
│ │ codexlens.api.find_definition() │ │
│ │ codexlens.api.find_references() │ │
│ │ codexlens.api.semantic_search() │ │
│ └──────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────▼────────────────────────────────┐ │
│ │ Core Components │ │
│ │ GlobalSymbolIndex | ChainSearchEngine | HoverProvider │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────▼────────────────────────────────┐ │
│ │ SQLite Index Databases │ │
│ │ global_symbols.db | *.index.db (per-directory) │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### 1.3 职责分离
| 组件 | 职责 |
|------|------|
| **codexlens** | Python API、索引查询、搜索算法、结果聚合、降级处理 |
| **CCW** | MCP 协议、参数校验、结果序列化、错误处理、project_root 推断 |
### 1.4 codexlens vs cclsp 对比
| 特性 | cclsp | codexlens |
|------|-------|-----------|
| 数据源 | 实时 LSP 服务器 | 预建 SQLite 索引 |
| 启动时间 | 200-3000ms | <50ms |
| 响应时间 | 50-500ms | <5ms |
| 跨语言 | 每语言需要 LSP 服务器 | 统一 Python/TS/JS/Go 索引 |
| 依赖 | 需要语言服务器 | 无外部依赖 |
| 准确度 | 100% (编译器级) | 95%+ (tree-sitter) |
| 重命名支持 | 是 | 否 (只读索引) |
| 实时诊断 | 是 | 通过 IDE MCP |
**推荐**: codexlens 用于快速搜索cclsp 用于精确重构
---
## 二、cclsp 设计模式 (参考)
### 2.1 MCP 工具接口设计
| 模式 | 说明 | 代码位置 |
|------|------|----------|
| **基于名称** | 接受 `symbol_name` 而非文件坐标 | `index.ts:70` |
| **安全消歧义** | `rename_symbol``rename_symbol_strict` 两步 | `index.ts:133, 172` |
| **复杂性抽象** | 隐藏 LSP 协议细节 | `index.ts:211` |
| **优雅失败** | 返回有用的文本响应 | 全局 |
### 2.2 符号解析算法
```
1. getDocumentSymbols (lsp-client.ts:1406)
└─ 获取文件所有符号
2. 处理两种格式:
├─ DocumentSymbol[] → 扁平化
└─ SymbolInformation[] → 二次定位
3. 过滤: symbol.name === symbolName && symbol.kind
4. 回退: 无结果时移除 kind 约束重试
5. 聚合: 遍历所有匹配,聚合定义位置
```
---
## 三、需求规格
### 需求 1: 文件上下文查询 (`file_context`)
**用途**: 读取代码文件,返回文件中所有方法的调用关系摘要
**输出示例**:
```markdown
## src/auth/login.py (3 methods)
### login_user (line 15-45)
- Calls: validate_password (auth/utils.py:23), create_session (session/manager.py:89)
- Called by: handle_login_request (api/routes.py:156), test_login (tests/test_auth.py:34)
### validate_token (line 47-62)
- Calls: decode_jwt (auth/jwt.py:12)
- Called by: auth_middleware (middleware/auth.py:28)
```
### 需求 2: 通用 LSP 搜索 (cclsp 兼容)
| 端点 | 用途 |
|------|------|
| `find_definition` | 根据符号名查找定义位置 |
| `find_references` | 查找符号的所有引用 |
| `workspace_symbols` | 工作区符号搜索 |
| `get_hover` | 获取符号悬停信息 |
### 需求 3: 向量 + LSP 融合搜索
**用途**: 结合向量语义搜索和结构化 LSP 搜索
**融合策略**:
- **RRF** (首选): 简单、不需要分数归一化、鲁棒
- **Cascade**: 特定场景,先向量后 LSP
- **Adaptive**: 长期目标,按查询类型自动选择
---
## 四、API 规范
### 4.1 模块结构
```
src/codexlens/
├─ api/ [新增] 公开 API 层
│ ├─ __init__.py 导出所有 API
│ ├─ file_context.py 文件上下文
│ ├─ definition.py 定义查找
│ ├─ references.py 引用查找
│ ├─ symbols.py 符号搜索
│ ├─ hover.py 悬停信息
│ └─ semantic.py 语义搜索
├─ storage/
│ ├─ global_index.py [扩展] get_file_symbols()
│ └─ relationship_query.py [新增] 有向调用查询
└─ search/
└─ chain_search.py [修复] schema 兼容
```
### 4.2 `codexlens.api.file_context()`
```python
from dataclasses import dataclass, field
from typing import List, Optional, Dict, Tuple
@dataclass
class CallInfo:
"""调用关系信息"""
symbol_name: str
file_path: Optional[str] # 目标文件 (可能为 None)
line: int
relationship: str # call | import | inheritance
@dataclass
class MethodContext:
"""方法上下文"""
name: str
kind: str # function | method | class
line_range: Tuple[int, int]
signature: Optional[str]
calls: List[CallInfo] # 出向调用
callers: List[CallInfo] # 入向调用
@dataclass
class FileContextResult:
"""文件上下文结果"""
file_path: str
language: str
methods: List[MethodContext]
summary: str # 人类可读摘要
discovery_status: Dict[str, bool] = field(default_factory=lambda: {
"outgoing_resolved": False,
"incoming_resolved": True,
"targets_resolved": False
})
def file_context(
project_root: str,
file_path: str,
include_calls: bool = True,
include_callers: bool = True,
max_depth: int = 1,
format: str = "brief" # brief | detailed | tree
) -> FileContextResult:
"""
获取代码文件的方法调用上下文。
Args:
project_root: 项目根目录 (用于定位索引)
file_path: 代码文件路径
include_calls: 是否包含出向调用
include_callers: 是否包含入向调用
max_depth: 调用链深度 (1=直接调用)
⚠️ V1 限制: 当前版本仅支持 max_depth=1
深度调用链分析将在 V2 实现
format: 输出格式
Returns:
FileContextResult
Raises:
IndexNotFoundError: 项目未索引
FileNotFoundError: 文件不存在
Note:
V1 实现限制:
- max_depth 仅支持 1 (直接调用)
- 出向调用目标文件可能为 None (未解析)
- 深度调用链分析作为 V2 特性规划
"""
```
### 4.3 `codexlens.api.find_definition()`
```python
@dataclass
class DefinitionResult:
"""定义查找结果"""
name: str
kind: str
file_path: str
line: int
end_line: int
signature: Optional[str]
container: Optional[str] # 所属类/模块
score: float
def find_definition(
project_root: str,
symbol_name: str,
symbol_kind: Optional[str] = None,
file_context: Optional[str] = None,
limit: int = 10
) -> List[DefinitionResult]:
"""
根据符号名称查找定义位置。
Fallback 策略:
1. 精确匹配 + kind 过滤
2. 精确匹配 (移除 kind)
3. 前缀匹配
"""
```
### 4.4 `codexlens.api.find_references()`
```python
@dataclass
class ReferenceResult:
"""引用结果"""
file_path: str
line: int
column: int
context_line: str
relationship: str # call | import | type_annotation | inheritance
@dataclass
class GroupedReferences:
"""按定义分组的引用"""
definition: DefinitionResult
references: List[ReferenceResult]
def find_references(
project_root: str,
symbol_name: str,
symbol_kind: Optional[str] = None,
include_definition: bool = True,
group_by_definition: bool = True,
limit: int = 100
) -> List[GroupedReferences]:
"""
查找符号的所有引用位置。
多定义时分组返回,解决引用混淆问题。
"""
```
### 4.5 `codexlens.api.workspace_symbols()`
```python
@dataclass
class SymbolInfo:
"""符号信息"""
name: str
kind: str
file_path: str
line: int
container: Optional[str]
score: float
def workspace_symbols(
project_root: str,
query: str,
kind_filter: Optional[List[str]] = None,
file_pattern: Optional[str] = None,
limit: int = 50
) -> List[SymbolInfo]:
"""在整个工作区搜索符号 (前缀匹配)。"""
```
### 4.6 `codexlens.api.get_hover()`
```python
@dataclass
class HoverInfo:
"""悬停信息"""
name: str
kind: str
signature: str
documentation: Optional[str]
file_path: str
line_range: Tuple[int, int]
type_info: Optional[str]
def get_hover(
project_root: str,
symbol_name: str,
file_path: Optional[str] = None
) -> Optional[HoverInfo]:
"""获取符号的详细悬停信息。"""
```
### 4.7 `codexlens.api.semantic_search()`
```python
@dataclass
class SemanticResult:
"""语义搜索结果"""
symbol_name: str
kind: str
file_path: str
line: int
vector_score: Optional[float]
structural_score: Optional[float]
fusion_score: float
snippet: str
match_reason: Optional[str]
def semantic_search(
project_root: str,
query: str,
mode: str = "fusion", # vector | structural | fusion
vector_weight: float = 0.5,
structural_weight: float = 0.3,
keyword_weight: float = 0.2,
fusion_strategy: str = "rrf", # rrf | staged | binary | hybrid
kind_filter: Optional[List[str]] = None,
limit: int = 20,
include_match_reason: bool = False
) -> List[SemanticResult]:
"""
语义搜索 - 结合向量和结构化搜索。
Args:
project_root: 项目根目录
query: 自然语言查询
mode: 搜索模式
- vector: 仅向量搜索
- structural: 仅结构搜索 (符号 + 关系)
- fusion: 融合搜索 (默认)
vector_weight: 向量搜索权重 [0, 1]
structural_weight: 结构搜索权重 [0, 1]
keyword_weight: 关键词搜索权重 [0, 1]
fusion_strategy: 融合策略 (映射到 chain_search.py)
- rrf: Reciprocal Rank Fusion (推荐,默认)
- staged: 分阶段级联 → staged_cascade_search
- binary: 二分重排级联 → binary_rerank_cascade_search
- hybrid: 混合级联 → hybrid_cascade_search
kind_filter: 符号类型过滤
limit: 最大返回数量
include_match_reason: 是否生成匹配原因 (启发式,非 LLM)
Returns:
按 fusion_score 排序的结果列表
降级行为:
- 无向量索引: vector_score=None, 使用 FTS + 结构搜索
- 无关系数据: structural_score=None, 仅向量搜索
"""
```
---
## 五、已知问题与解决方案
### 5.1 P0 阻塞项
| 问题 | 位置 | 解决方案 |
|------|------|----------|
| **索引 Schema 不匹配** | `chain_search.py:313-324` vs `dir_index.py:304-312` | 兼容 `full_path``path` |
| **文件符号查询缺失** | `global_index.py:214-260` | 新增 `get_file_symbols()` |
| **出向调用查询缺失** | `dir_index.py:333-342` | 新增 `RelationshipQuery` |
| **关系类型不一致** | `entities.py:74-79` | 规范化 `calls``call` |
### 5.2 设计缺陷 (Gemini 发现)
| 缺陷 | 影响 | 解决方案 |
|------|------|----------|
| **调用图不完整** | `file_context` 缺少出向调用 | 新增有向调用 API |
| **消歧义未定义** | 多定义时无法区分 | 实现 `rank_by_proximity()` |
| **AI 特性成本过高** | `explanation` 需要 LLM | 设为可选,默认关闭 |
| **融合参数不一致** | 3 分支但只有 2 权重 | 补充 `keyword_weight` |
### 5.3 消歧义算法
**V1 实现** (基于文件路径接近度):
```python
def rank_by_proximity(
results: List[DefinitionResult],
file_context: str
) -> List[DefinitionResult]:
"""按文件接近度排序 (V1: 路径接近度)"""
def proximity_score(result):
# 1. 同目录最高分
if os.path.dirname(result.file_path) == os.path.dirname(file_context):
return 100
# 2. 共同路径前缀长度
common = os.path.commonpath([result.file_path, file_context])
return len(common)
return sorted(results, key=proximity_score, reverse=True)
```
**V2 增强计划** (基于 import graph 距离):
```python
def rank_by_import_distance(
results: List[DefinitionResult],
file_context: str,
import_graph: Dict[str, Set[str]]
) -> List[DefinitionResult]:
"""按 import graph 距离排序 (V2)"""
def import_distance(result):
# BFS 计算最短 import 路径
return bfs_shortest_path(
import_graph,
file_context,
result.file_path
)
# 组合: 0.6 * import_distance + 0.4 * path_proximity
return sorted(results, key=lambda r: (
0.6 * import_distance(r) +
0.4 * (100 - proximity_score(r))
))
```
### 5.4 参考实现: `get_file_symbols()`
**位置**: `src/codexlens/storage/global_index.py`
```python
def get_file_symbols(self, file_path: str | Path) -> List[Symbol]:
"""
获取指定文件中定义的所有符号。
Args:
file_path: 文件路径 (相对或绝对)
Returns:
按行号排序的符号列表
"""
file_path_str = str(Path(file_path).resolve())
with self._lock:
conn = self._get_connection()
rows = conn.execute(
"""
SELECT symbol_name, symbol_kind, file_path, start_line, end_line
FROM global_symbols
WHERE project_id = ? AND file_path = ?
ORDER BY start_line
""",
(self.project_id, file_path_str),
).fetchall()
return [
Symbol(
name=row["symbol_name"],
kind=row["symbol_kind"],
range=(row["start_line"], row["end_line"]),
file=row["file_path"],
)
for row in rows
]
```
---
## 六、实现计划
### Phase 0: 基础设施 (16h)
| 任务 | 工时 | 说明 |
|------|------|------|
| 修复 `search_references` schema | 4h | 兼容两种 schema |
| 新增 `GlobalSymbolIndex.get_file_symbols()` | 4h | 文件符号查询 (见 5.4) |
| 新增 `RelationshipQuery` 类 | 6h | 有向调用查询 |
| 关系类型规范化层 | 2h | `calls``call` |
### Phase 1: API 层 (48h)
| 任务 | 工时 | 复杂度 |
|------|------|--------|
| `find_definition()` | 4h | S |
| `find_references()` | 8h | M |
| `workspace_symbols()` | 4h | S |
| `get_hover()` | 4h | S |
| `file_context()` | 16h | L |
| `semantic_search()` | 12h | M |
### Phase 2: 测试与文档 (16h)
| 任务 | 工时 |
|------|------|
| 单元测试 (≥80%) | 8h |
| API 文档 | 4h |
| 示例代码 | 4h |
### 关键路径
```
Phase 0.1 (schema fix)
Phase 0.2 (file symbols) → Phase 1.5 (file_context)
Phase 1 (其他 API)
Phase 2 (测试)
```
---
## 七、测试策略
### 7.1 单元测试
```python
# test_global_index.py
def test_get_file_symbols():
index = GlobalSymbolIndex(":memory:")
index.update_file_symbols(project_id=1, file_path="test.py", symbols=[...])
results = index.get_file_symbols("test.py")
assert len(results) == 3
# test_relationship_query.py
def test_outgoing_calls():
store = DirIndexStore(":memory:")
calls = store.get_outgoing_calls("src/auth.py", "login")
assert calls[0].relationship == "call" # 已规范化
```
### 7.2 Schema 兼容性测试
```python
def test_search_references_both_schemas():
"""测试两种 schema 的引用搜索"""
# 旧 schema: files(path, ...)
# 新 schema: files(full_path, ...)
```
### 7.3 降级测试
```python
def test_semantic_search_without_vectors():
result = semantic_search(query="auth", mode="fusion")
assert result.vector_score is None
assert result.fusion_score > 0
```
---
## 八、使用示例
```python
from codexlens.api import (
file_context,
find_definition,
find_references,
semantic_search
)
# 1. 获取文件上下文
result = file_context(
project_root="/path/to/project",
file_path="src/auth/login.py",
format="brief"
)
print(result.summary)
# 2. 查找定义
definitions = find_definition(
project_root="/path/to/project",
symbol_name="UserService",
symbol_kind="class"
)
# 3. 语义搜索
results = semantic_search(
project_root="/path/to/project",
query="处理用户登录验证的函数",
mode="fusion"
)
```
---
## 九、CCW 集成
| codexlens API | CCW MCP Tool |
|---------------|--------------|
| `file_context()` | `codexlens_file_context` |
| `find_definition()` | `codexlens_find_definition` |
| `find_references()` | `codexlens_find_references` |
| `workspace_symbols()` | `codexlens_workspace_symbol` |
| `get_hover()` | `codexlens_get_hover` |
| `semantic_search()` | `codexlens_semantic_search` |
---
## 十、分析来源
| 工具 | Session ID | 贡献 |
|------|------------|------|
| Gemini | `1768618654438-gemini` | 架构评审、设计缺陷、融合策略 |
| Codex | `1768618658183-codex` | 组件复用、复杂度估算、任务分解 |
| Gemini | `1768620615744-gemini` | 最终评审、改进建议、APPROVED |
---
## 十一、版本历史
| 版本 | 日期 | 变更 |
|------|------|------|
| 1.0 | 2025-01-17 | 初始版本,合并多文档 |
| 1.1 | 2025-01-17 | 应用 Gemini 评审改进: V1 限制说明、策略映射、消歧义增强、参考实现 |