cortex-local 2.3.0__tar.gz → 2.3.1__tar.gz

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.
Files changed (22) hide show
  1. {cortex_local-2.3.0 → cortex_local-2.3.1}/PKG-INFO +1 -1
  2. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/cli.py +2 -2
  3. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/indexer.py +30 -11
  4. {cortex_local-2.3.0 → cortex_local-2.3.1}/README.md +0 -0
  5. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/__init__.py +0 -0
  6. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/config.py +0 -0
  7. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/__init__.py +0 -0
  8. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/cache.py +0 -0
  9. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/chunker.py +0 -0
  10. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/code_graph.py +0 -0
  11. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/formatters.py +0 -0
  12. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/global_graph.py +0 -0
  13. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/graph.py +0 -0
  14. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/notes_graph.py +0 -0
  15. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/roslyn_analyzer.py +0 -0
  16. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/roslyn_tool/CortexAnalyzer.csproj +0 -0
  17. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/core/roslyn_tool/Program.cs +0 -0
  18. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/embedder.py +0 -0
  19. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/mcp_server.py +0 -0
  20. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/state.py +0 -0
  21. {cortex_local-2.3.0 → cortex_local-2.3.1}/cortex/watcher.py +0 -0
  22. {cortex_local-2.3.0 → cortex_local-2.3.1}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cortex-local
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Local semantic search MCP server — notes + code, embedded Qdrant, fastembed
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: click>=8.0.0
@@ -48,9 +48,9 @@ def pull_models() -> None:
48
48
  def stats() -> None:
49
49
  """Show cortex efficiency stats."""
50
50
  from .state import _stats
51
- from .mcp_server import _fmt_stats
51
+ from .core.formatters import fmt_stats
52
52
  from .config import VERSION
53
- click.echo(_fmt_stats(VERSION, _stats, current=True))
53
+ click.echo(fmt_stats(VERSION, _stats, current=True))
54
54
 
55
55
 
56
56
  @cli.group()
@@ -1,6 +1,7 @@
1
1
  """Index notes and code from a local path into embedded Qdrant."""
2
2
 
3
3
  import hashlib
4
+ import os
4
5
  import re
5
6
  from pathlib import Path
6
7
 
@@ -20,11 +21,33 @@ from .core import graph as _graph
20
21
  from .core import roslyn_analyzer as _roslyn
21
22
 
22
23
 
24
+ def _walk_code_files(root: Path, exclude_patterns: list) -> list[Path]:
25
+ """Walk root pruning SKIP_DIRS at directory level — avoids descending into bin/obj/node_modules."""
26
+ found = []
27
+ for dirpath, dirs, files in os.walk(root):
28
+ dirs[:] = [d for d in dirs if d not in SKIP_DIRS]
29
+ for fname in files:
30
+ p = Path(dirpath) / fname
31
+ if p.suffix in CODE_EXTS:
32
+ rel = str(p.relative_to(root)).replace("\\", "/")
33
+ if not _is_excluded(rel, exclude_patterns):
34
+ found.append(p)
35
+ return found
36
+
37
+
23
38
  def _qdrant() -> QdrantClient:
24
39
  migrate_legacy()
25
40
  d = data_dir()
26
41
  d.mkdir(parents=True, exist_ok=True)
27
- return QdrantClient(path=qdrant_path())
42
+ try:
43
+ return QdrantClient(path=qdrant_path())
44
+ except Exception as e:
45
+ if "already" in str(e).lower() or "lock" in str(e).lower():
46
+ raise SystemExit(
47
+ "Error: Qdrant database is locked by another process (cortex serve is running).\n"
48
+ "Stop cortex serve first, or use the reindex() MCP tool from Claude Code instead."
49
+ ) from e
50
+ raise
28
51
 
29
52
 
30
53
  def _ensure_collection(client: QdrantClient, name: str) -> bool:
@@ -185,12 +208,7 @@ def index_code(code_dir: Path, show_progress: bool = False) -> int:
185
208
  _ensure_collection(client, "code")
186
209
  use_sparse = _sparse_available()
187
210
 
188
- code_files = [
189
- p for p in code_dir.rglob("*")
190
- if p.is_file() and p.suffix in CODE_EXTS
191
- and not any(s in p.parts for s in SKIP_DIRS)
192
- and not _is_excluded(str(p.relative_to(code_dir)), exclude_patterns)
193
- ]
211
+ code_files = _walk_code_files(code_dir, exclude_patterns)
194
212
 
195
213
  cache = load_cache("code", cache_file())
196
214
  if client.get_collection("code").points_count == 0:
@@ -268,10 +286,11 @@ def index_path(path: Path, show_progress: bool = False) -> None:
268
286
  path = path.resolve()
269
287
  data_dir().mkdir(parents=True, exist_ok=True)
270
288
 
271
- md_files = list(path.rglob("*.md"))
272
- code_files = [p for p in path.rglob("*")
273
- if p.is_file() and p.suffix in CODE_EXTS
274
- and not any(s in p.parts for s in SKIP_DIRS)]
289
+ md_files = []
290
+ for dirpath, dirs, files in os.walk(path):
291
+ dirs[:] = [d for d in dirs if d not in SKIP_DIRS]
292
+ md_files.extend(Path(dirpath) / f for f in files if f.endswith(".md"))
293
+ code_files = _walk_code_files(path, [])
275
294
 
276
295
  if md_files:
277
296
  print(f"\nIndexing notes from {path} ({len(md_files)} .md files)...")
File without changes