cortex-local 2.4.4__tar.gz → 2.4.5__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 (24) hide show
  1. {cortex_local-2.4.4 → cortex_local-2.4.5}/PKG-INFO +1 -1
  2. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/cli.py +28 -11
  3. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/config.py +1 -0
  4. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/embedder.py +3 -3
  5. {cortex_local-2.4.4 → cortex_local-2.4.5}/.gitignore +0 -0
  6. {cortex_local-2.4.4 → cortex_local-2.4.5}/README.md +0 -0
  7. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/__init__.py +0 -0
  8. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/__init__.py +0 -0
  9. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/cache.py +0 -0
  10. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/chunker.py +0 -0
  11. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/code_graph.py +0 -0
  12. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/formatters.py +0 -0
  13. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/global_graph.py +0 -0
  14. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/graph.py +0 -0
  15. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/notes_graph.py +0 -0
  16. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/roslyn_analyzer.py +0 -0
  17. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/roslyn_tool/CortexAnalyzer.csproj +0 -0
  18. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/core/roslyn_tool/Program.cs +0 -0
  19. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/indexer.py +0 -0
  20. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/mcp_server.py +0 -0
  21. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/state.py +0 -0
  22. {cortex_local-2.4.4 → cortex_local-2.4.5}/cortex/watcher.py +0 -0
  23. {cortex_local-2.4.4 → cortex_local-2.4.5}/pyproject.toml +0 -0
  24. {cortex_local-2.4.4 → cortex_local-2.4.5}/tests/test_imports.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cortex-local
3
- Version: 2.4.4
3
+ Version: 2.4.5
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
@@ -11,7 +11,7 @@ import click
11
11
 
12
12
  from .config import (
13
13
  WORKSPACES_DIR, get_active_workspace, set_active_workspace, get_workspace_dir,
14
- data_dir, save_last_indexed_path, qdrant_path, get_config, VERSION,
14
+ data_dir, save_last_indexed_path, qdrant_path, get_config, VERSION, MODELS_DIR,
15
15
  )
16
16
 
17
17
 
@@ -161,18 +161,25 @@ def search_log_cmd(top: int) -> None:
161
161
  click.echo(f" {q}")
162
162
 
163
163
 
164
- _SYSTEM_DIRS = {"/", "/usr", "/bin", "/etc", "/sbin", "/var", r"C:\Windows"}
164
+ _SYSTEM_PREFIXES = [Path(p) for p in ("/usr", "/bin", "/etc", "/sbin", "/var", r"C:\Windows")]
165
165
  _SCOPE_CHOICES = click.Choice(["user", "local", "project"])
166
166
 
167
167
 
168
+ def _is_system_dir(p: Path) -> bool:
169
+ r = p.resolve()
170
+ if r == Path("/"):
171
+ return True
172
+ return any(prefix.exists() and r.is_relative_to(prefix) for prefix in _SYSTEM_PREFIXES)
173
+
174
+
168
175
  @cli.command("install")
169
176
  @click.option("--scope", default="user", type=_SCOPE_CHOICES, show_default=True,
170
177
  help="MCP registration scope.")
171
178
  def install_cmd(scope: str) -> None:
172
179
  """Download embedding models and register cortex MCP in Claude Code."""
173
180
  from .embedder import pull_models as _pull
174
- cwd = str(Path.cwd())
175
- if scope != "user" and cwd in _SYSTEM_DIRS:
181
+ cwd = Path.cwd()
182
+ if scope != "user" and _is_system_dir(cwd):
176
183
  click.echo(f"Warning: cwd looks like a system directory ({cwd}). Use --scope user to register globally.")
177
184
  click.echo("Downloading embedding models...")
178
185
  _pull()
@@ -223,18 +230,16 @@ def doctor_cmd() -> None:
223
230
  """Show cortex status: version, model cache, MCP registration, workspace, index."""
224
231
  click.echo(f"version {VERSION}")
225
232
 
226
- cache_dir = Path.home() / ".cache" / "fastembed"
227
- cache_ok = cache_dir.exists() and any(cache_dir.iterdir())
233
+ cache_ok = MODELS_DIR.exists() and any(MODELS_DIR.iterdir())
228
234
  click.echo(f"model cache {'ok' if cache_ok else 'missing — run: cortex pull-models'}")
229
235
 
230
236
  claude = shutil.which("claude")
231
237
  mcp_status = "claude not found in PATH"
232
238
  if claude:
233
- r = subprocess.run([claude, "mcp", "list"], capture_output=True, text=True)
234
- output = r.stdout + r.stderr
235
- if "cortex" in output.lower():
236
- lines = [l for l in output.splitlines() if "cortex" in l.lower()]
237
- mcp_status = lines[0].strip() if lines else "registered"
239
+ r = subprocess.run([claude, "mcp", "get", "cortex"], capture_output=True, text=True)
240
+ if r.returncode == 0:
241
+ detail = r.stdout.strip().splitlines()[0] if r.stdout.strip() else "registered"
242
+ mcp_status = detail
238
243
  else:
239
244
  mcp_status = "not registered — run: cortex install"
240
245
  click.echo(f"MCP {mcp_status}")
@@ -245,3 +250,15 @@ def doctor_cmd() -> None:
245
250
 
246
251
  last = get_config()["index"].get("last_path") or "(none)"
247
252
  click.echo(f"last indexed {last}")
253
+
254
+ claude_json = Path.home() / ".claude.json"
255
+ if claude_json.exists():
256
+ try:
257
+ projects = json.loads(claude_json.read_text()).get("projects", {})
258
+ stale = [p for p, v in projects.items() if "cortex" in v.get("mcpServers", {})]
259
+ if stale:
260
+ click.echo("\nStale local registrations (run from each dir to remove):")
261
+ for p in stale:
262
+ click.echo(f" cd {p} && claude mcp remove cortex --scope local")
263
+ except Exception:
264
+ pass
@@ -6,6 +6,7 @@ import tomllib
6
6
  from pathlib import Path
7
7
 
8
8
  CORTEX_DIR = Path.home() / ".cortex"
9
+ MODELS_DIR = CORTEX_DIR / "models"
9
10
  WORKSPACES_DIR = CORTEX_DIR / "workspaces"
10
11
  ACTIVE_WORKSPACE_FILE = CORTEX_DIR / "active_workspace"
11
12
  CONFIG_FILE = CORTEX_DIR / "config.toml"
@@ -5,7 +5,7 @@ import os
5
5
  os.environ.setdefault("HF_HUB_DISABLE_SYMLINKS_WARNING", "1")
6
6
  os.environ.setdefault("HF_HUB_DISABLE_IMPLICIT_TOKEN", "1")
7
7
 
8
- from .config import EMBED_MODEL
8
+ from .config import EMBED_MODEL, MODELS_DIR
9
9
 
10
10
  _dense = None
11
11
  _sparse = None
@@ -30,7 +30,7 @@ def embed(text: str) -> list:
30
30
  global _dense
31
31
  if _dense is None:
32
32
  from fastembed import TextEmbedding
33
- _dense = TextEmbedding(EMBED_MODEL)
33
+ _dense = TextEmbedding(EMBED_MODEL, cache_dir=str(MODELS_DIR))
34
34
  return list(_dense.embed([text[:4000]]))[0].tolist()
35
35
 
36
36
 
@@ -39,7 +39,7 @@ def sparse_embed(text: str) -> tuple:
39
39
  global _sparse
40
40
  if _sparse is None:
41
41
  from fastembed import SparseTextEmbedding
42
- _sparse = SparseTextEmbedding("Qdrant/bm25")
42
+ _sparse = SparseTextEmbedding("Qdrant/bm25", cache_dir=str(MODELS_DIR))
43
43
  e = list(_sparse.embed([text[:4000]]))[0]
44
44
  return e.indices.tolist(), e.values.tolist()
45
45
 
File without changes
File without changes