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

21 KiB
Raw Permalink Blame History

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_symbolrename_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)

用途: 读取代码文件,返回文件中所有方法的调用关系摘要

输出示例:

## 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()

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()

@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()

@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()

@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()

@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]:
    """获取符号的详细悬停信息。"""
@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_pathpath
文件符号查询缺失 global_index.py:214-260 新增 get_file_symbols()
出向调用查询缺失 dir_index.py:333-342 新增 RelationshipQuery
关系类型不一致 entities.py:74-79 规范化 callscall

5.2 设计缺陷 (Gemini 发现)

缺陷 影响 解决方案
调用图不完整 file_context 缺少出向调用 新增有向调用 API
消歧义未定义 多定义时无法区分 实现 rank_by_proximity()
AI 特性成本过高 explanation 需要 LLM 设为可选,默认关闭
融合参数不一致 3 分支但只有 2 权重 补充 keyword_weight

5.3 消歧义算法

V1 实现 (基于文件路径接近度):

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 距离):

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

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 callscall

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 单元测试

# 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 兼容性测试

def test_search_references_both_schemas():
    """测试两种 schema 的引用搜索"""
    # 旧 schema: files(path, ...)
    # 新 schema: files(full_path, ...)

7.3 降级测试

def test_semantic_search_without_vectors():
    result = semantic_search(query="auth", mode="fusion")
    assert result.vector_score is None
    assert result.fusion_score > 0

八、使用示例

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 限制说明、策略映射、消歧义增强、参考实现