refactor: rename package codexlens -> codexlens_search for independent distribution

Rename the v2 search engine package to `codexlens-search` (import as
`codexlens_search`) so it can be installed independently and consumed
by the original codex-lens as a dependency. This avoids package path
conflicts since both previously used `src/codexlens/`.

Changes:
- Rename src/codexlens/ -> src/codexlens_search/
- Update pyproject.toml: name=codexlens-search, version=0.2.0
- Update all imports across source, tests, and scripts
- Add public API exports in __init__.py (Config, SearchPipeline,
  IndexingPipeline, SearchResult, IndexStats)

37/37 tests pass. No functional changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
catlog22
2026-03-16 23:23:22 +08:00
parent a0a50d338a
commit 6712965b7f
32 changed files with 83 additions and 63 deletions

View File

@@ -1,5 +1,5 @@
import sys import sys
import os import os
# Ensure the local src directory takes precedence over any installed codexlens package # Ensure the local src directory takes precedence over any installed codexlens_search package
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src")) sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))

View File

@@ -3,9 +3,9 @@ requires = ["hatchling"]
build-backend = "hatchling.build" build-backend = "hatchling.build"
[project] [project]
name = "codex-lens-v2" name = "codexlens-search"
version = "0.1.0" version = "0.2.0"
description = "Minimal code semantic search library with 2-stage pipeline" description = "Lightweight semantic code search engine — 2-stage vector + FTS + RRF fusion"
requires-python = ">=3.10" requires-python = ">=3.10"
dependencies = [] dependencies = []
@@ -33,4 +33,4 @@ dev = [
] ]
[tool.hatch.build.targets.wheel] [tool.hatch.build.targets.wheel]
packages = ["src/codexlens"] packages = ["src/codexlens_search"]

View File

@@ -9,13 +9,13 @@ from pathlib import Path
# 确保 src 可被导入 # 确保 src 可被导入
sys.path.insert(0, str(Path(__file__).parent.parent / "src")) sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core.factory import create_ann_index, create_binary_index from codexlens_search.core.factory import create_ann_index, create_binary_index
from codexlens.embed.local import FastEmbedEmbedder from codexlens_search.embed.local import FastEmbedEmbedder
from codexlens.indexing import IndexingPipeline from codexlens_search.indexing import IndexingPipeline
from codexlens.rerank.local import FastEmbedReranker from codexlens_search.rerank.local import FastEmbedReranker
from codexlens.search.fts import FTSEngine from codexlens_search.search.fts import FTSEngine
from codexlens.search.pipeline import SearchPipeline from codexlens_search.search.pipeline import SearchPipeline
# ─── 配置 ────────────────────────────────────────────────────────────────── # ─── 配置 ──────────────────────────────────────────────────────────────────
REPO_ROOT = Path("D:/Claude_dms3") REPO_ROOT = Path("D:/Claude_dms3")

View File

@@ -11,13 +11,13 @@ from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent / "src")) sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
import numpy as np import numpy as np
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core.factory import create_ann_index, create_binary_index from codexlens_search.core.factory import create_ann_index, create_binary_index
from codexlens.embed.local import FastEmbedEmbedder from codexlens_search.embed.local import FastEmbedEmbedder
from codexlens.indexing import IndexingPipeline from codexlens_search.indexing import IndexingPipeline
from codexlens.rerank.base import BaseReranker from codexlens_search.rerank.base import BaseReranker
from codexlens.search.fts import FTSEngine from codexlens_search.search.fts import FTSEngine
from codexlens.search.pipeline import SearchPipeline from codexlens_search.search.pipeline import SearchPipeline
class KeywordReranker(BaseReranker): class KeywordReranker(BaseReranker):
@@ -32,7 +32,7 @@ class KeywordReranker(BaseReranker):
return scores return scores
PROJECT = Path(__file__).parent.parent PROJECT = Path(__file__).parent.parent
TARGET_DIR = PROJECT / "src" / "codexlens" # ~21 .py files, small TARGET_DIR = PROJECT / "src" / "codexlens_search" # ~21 .py files, small
INDEX_DIR = PROJECT / ".test_index_cache" INDEX_DIR = PROJECT / ".test_index_cache"
EXTENSIONS = {".py"} EXTENSIONS = {".py"}

View File

@@ -0,0 +1,20 @@
"""codexlens-search: Lightweight semantic code search engine.
Public API for consumers (e.g. codex-lens):
from codexlens_search import SearchPipeline, IndexingPipeline, Config
from codexlens_search.core import create_ann_index, create_binary_index
from codexlens_search.embed.local import FastEmbedEmbedder
from codexlens_search.rerank.api import APIReranker
"""
from codexlens_search.config import Config
from codexlens_search.indexing import IndexingPipeline, IndexStats
from codexlens_search.search.pipeline import SearchPipeline, SearchResult
__all__ = [
"Config",
"IndexingPipeline",
"IndexStats",
"SearchPipeline",
"SearchResult",
]

View File

@@ -6,8 +6,8 @@ from pathlib import Path
import numpy as np import numpy as np
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core.base import BaseBinaryIndex from codexlens_search.core.base import BaseBinaryIndex
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -3,8 +3,8 @@ from __future__ import annotations
import logging import logging
from pathlib import Path from pathlib import Path
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core.base import BaseANNIndex, BaseBinaryIndex from codexlens_search.core.base import BaseANNIndex, BaseBinaryIndex
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -52,22 +52,22 @@ def create_ann_index(path: str | Path, dim: int, config: Config) -> BaseANNIndex
backend = config.ann_backend backend = config.ann_backend
if backend == "faiss": if backend == "faiss":
from codexlens.core.faiss_index import FAISSANNIndex from codexlens_search.core.faiss_index import FAISSANNIndex
return FAISSANNIndex(path, dim, config) return FAISSANNIndex(path, dim, config)
if backend == "hnswlib": if backend == "hnswlib":
from codexlens.core.index import ANNIndex from codexlens_search.core.index import ANNIndex
return ANNIndex(path, dim, config) return ANNIndex(path, dim, config)
# auto: try faiss first, then hnswlib # auto: try faiss first, then hnswlib
if _FAISS_AVAILABLE: if _FAISS_AVAILABLE:
from codexlens.core.faiss_index import FAISSANNIndex from codexlens_search.core.faiss_index import FAISSANNIndex
gpu_tag = " (GPU available)" if _has_faiss_gpu() else " (CPU)" gpu_tag = " (GPU available)" if _has_faiss_gpu() else " (CPU)"
logger.info("Auto-selected FAISS ANN backend%s", gpu_tag) logger.info("Auto-selected FAISS ANN backend%s", gpu_tag)
return FAISSANNIndex(path, dim, config) return FAISSANNIndex(path, dim, config)
if _HNSWLIB_AVAILABLE: if _HNSWLIB_AVAILABLE:
from codexlens.core.index import ANNIndex from codexlens_search.core.index import ANNIndex
logger.info("Auto-selected hnswlib ANN backend") logger.info("Auto-selected hnswlib ANN backend")
return ANNIndex(path, dim, config) return ANNIndex(path, dim, config)
@@ -97,20 +97,20 @@ def create_binary_index(
backend = config.binary_backend backend = config.binary_backend
if backend == "faiss": if backend == "faiss":
from codexlens.core.faiss_index import FAISSBinaryIndex from codexlens_search.core.faiss_index import FAISSBinaryIndex
return FAISSBinaryIndex(path, dim, config) return FAISSBinaryIndex(path, dim, config)
if backend == "hnswlib": if backend == "hnswlib":
from codexlens.core.binary import BinaryStore from codexlens_search.core.binary import BinaryStore
return BinaryStore(path, dim, config) return BinaryStore(path, dim, config)
# auto: try faiss first, then numpy-based BinaryStore # auto: try faiss first, then numpy-based BinaryStore
if _FAISS_AVAILABLE: if _FAISS_AVAILABLE:
from codexlens.core.faiss_index import FAISSBinaryIndex from codexlens_search.core.faiss_index import FAISSBinaryIndex
logger.info("Auto-selected FAISS binary backend") logger.info("Auto-selected FAISS binary backend")
return FAISSBinaryIndex(path, dim, config) return FAISSBinaryIndex(path, dim, config)
# numpy BinaryStore is always available (no extra deps) # numpy BinaryStore is always available (no extra deps)
from codexlens.core.binary import BinaryStore from codexlens_search.core.binary import BinaryStore
logger.info("Auto-selected numpy BinaryStore backend") logger.info("Auto-selected numpy BinaryStore backend")
return BinaryStore(path, dim, config) return BinaryStore(path, dim, config)

View File

@@ -7,8 +7,8 @@ from pathlib import Path
import numpy as np import numpy as np
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core.base import BaseANNIndex, BaseBinaryIndex from codexlens_search.core.base import BaseANNIndex, BaseBinaryIndex
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -6,8 +6,8 @@ from pathlib import Path
import numpy as np import numpy as np
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core.base import BaseANNIndex from codexlens_search.core.base import BaseANNIndex
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -14,11 +14,11 @@ from pathlib import Path
import numpy as np import numpy as np
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core.binary import BinaryStore from codexlens_search.core.binary import BinaryStore
from codexlens.core.index import ANNIndex from codexlens_search.core.index import ANNIndex
from codexlens.embed.base import BaseEmbedder from codexlens_search.embed.base import BaseEmbedder
from codexlens.search.fts import FTSEngine from codexlens_search.search.fts import FTSEngine
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -5,7 +5,7 @@ import time
import httpx import httpx
from codexlens.config import Config from codexlens_search.config import Config
from .base import BaseReranker from .base import BaseReranker
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from codexlens.config import Config from codexlens_search.config import Config
from .base import BaseReranker from .base import BaseReranker

View File

@@ -3,12 +3,12 @@ import numpy as np
import tempfile import tempfile
from pathlib import Path from pathlib import Path
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core import ANNIndex, BinaryStore from codexlens_search.core import ANNIndex, BinaryStore
from codexlens.embed.base import BaseEmbedder from codexlens_search.embed.base import BaseEmbedder
from codexlens.rerank.base import BaseReranker from codexlens_search.rerank.base import BaseReranker
from codexlens.search.fts import FTSEngine from codexlens_search.search.fts import FTSEngine
from codexlens.search.pipeline import SearchPipeline from codexlens_search.search.pipeline import SearchPipeline
# Test documents: 20 code snippets with id, path, content # Test documents: 20 code snippets with id, path, content
TEST_DOCS = [ TEST_DOCS = [

View File

@@ -1,4 +1,4 @@
from codexlens.config import Config from codexlens_search.config import Config
def test_config_instantiates_no_args(): def test_config_instantiates_no_args():

View File

@@ -8,8 +8,8 @@ from pathlib import Path
import numpy as np import numpy as np
import pytest import pytest
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.core import ANNIndex, BinaryStore from codexlens_search.core import ANNIndex, BinaryStore
DIM = 32 DIM = 32

View File

@@ -18,9 +18,9 @@ def _make_fastembed_mock():
_make_fastembed_mock() _make_fastembed_mock()
from codexlens.config import Config # noqa: E402 from codexlens_search.config import Config # noqa: E402
from codexlens.embed.base import BaseEmbedder # noqa: E402 from codexlens_search.embed.base import BaseEmbedder # noqa: E402
from codexlens.embed.local import EMBED_PROFILES, FastEmbedEmbedder # noqa: E402 from codexlens_search.embed.local import EMBED_PROFILES, FastEmbedEmbedder # noqa: E402
class TestEmbedSingle(unittest.TestCase): class TestEmbedSingle(unittest.TestCase):

View File

@@ -5,10 +5,10 @@ from unittest.mock import MagicMock, patch
import pytest import pytest
from codexlens.config import Config from codexlens_search.config import Config
from codexlens.rerank.base import BaseReranker from codexlens_search.rerank.base import BaseReranker
from codexlens.rerank.local import FastEmbedReranker from codexlens_search.rerank.local import FastEmbedReranker
from codexlens.rerank.api import APIReranker from codexlens_search.rerank.api import APIReranker
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@@ -5,16 +5,16 @@ from unittest.mock import MagicMock
import pytest import pytest
from codexlens.search.fts import FTSEngine from codexlens_search.search.fts import FTSEngine
from codexlens.search.fusion import ( from codexlens_search.search.fusion import (
DEFAULT_WEIGHTS, DEFAULT_WEIGHTS,
QueryIntent, QueryIntent,
detect_query_intent, detect_query_intent,
get_adaptive_weights, get_adaptive_weights,
reciprocal_rank_fusion, reciprocal_rank_fusion,
) )
from codexlens.search.pipeline import SearchPipeline, SearchResult from codexlens_search.search.pipeline import SearchPipeline, SearchResult
from codexlens.config import Config from codexlens_search.config import Config
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------