cortex-local 2.1.0__tar.gz → 2.1.12__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cortex-local
3
- Version: 2.1.0
3
+ Version: 2.1.12
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
@@ -1,5 +1,6 @@
1
1
  """Paths and constants for cortex local mode."""
2
2
 
3
+ import os
3
4
  import shutil
4
5
  from pathlib import Path
5
6
 
@@ -9,6 +10,7 @@ ACTIVE_WORKSPACE_FILE = CORTEX_DIR / "active_workspace"
9
10
 
10
11
  EMBED_MODEL = "nomic-ai/nomic-embed-text-v1.5"
11
12
  VECTOR_SIZE = 768
13
+ PPR_THRESHOLD = float(os.environ.get("PPR_THRESHOLD", "0.03"))
12
14
 
13
15
  try:
14
16
  from importlib.metadata import version
@@ -17,6 +17,86 @@ CHUNK_LINES = 30
17
17
  OVERLAP_LINES = 5
18
18
  MAX_CHUNK_LINES = 80
19
19
 
20
+ _FRAMEWORK_FILENAMES = {
21
+ "hooks.server": "sveltekit server hooks handle",
22
+ "hooks.client": "sveltekit client hooks",
23
+ "+page": "sveltekit page component",
24
+ "+layout": "sveltekit layout component",
25
+ "+server": "sveltekit api route endpoint",
26
+ "+page.server": "sveltekit page server load action",
27
+ "+layout.server": "sveltekit layout server load",
28
+ "+error": "sveltekit error page",
29
+ "svelte.config": "sveltekit",
30
+ "next.config": "nextjs",
31
+ "nuxt.config": "nuxt",
32
+ "astro.config": "astro",
33
+ "remix.config": "remix",
34
+ "_app": "nextjs",
35
+ "_document": "nextjs",
36
+ }
37
+
38
+ _FRAMEWORK_IMPORTS = [
39
+ ("@sveltejs/kit", "sveltekit"),
40
+ ("from 'react'", "react"),
41
+ ('from "react"', "react"),
42
+ ("from 'next/", "nextjs"),
43
+ ('from "next/', "nextjs"),
44
+ ("from 'vue'", "vue"),
45
+ ('from "vue"', "vue"),
46
+ ("@angular/core", "angular"),
47
+ ("from 'express'", "express"),
48
+ ('from "express"', "express"),
49
+ ("from 'fastify'", "fastify"),
50
+ ('from "fastify"', "fastify"),
51
+ ("from 'solid-js'", "solidjs"),
52
+ ('from "solid-js"', "solidjs"),
53
+ ("@remix-run/", "remix"),
54
+ ("from 'astro'", "astro"),
55
+ ('from "astro"', "astro"),
56
+ ("from fastapi", "fastapi"),
57
+ ("import fastapi", "fastapi"),
58
+ ("from django", "django"),
59
+ ("import django", "django"),
60
+ ("from flask", "flask"),
61
+ ("import flask", "flask"),
62
+ ("from starlette", "starlette"),
63
+ ("from pydantic", "pydantic"),
64
+ ("from sqlalchemy", "sqlalchemy"),
65
+ ("import torch", "pytorch"),
66
+ ("from torch", "pytorch"),
67
+ ("import tensorflow", "tensorflow"),
68
+ ("from tensorflow", "tensorflow"),
69
+ ("import numpy", "numpy"),
70
+ ("import pandas", "pandas"),
71
+ ("from sklearn", "scikit-learn"),
72
+ ("from transformers", "huggingface"),
73
+ ("from qdrant_client", "qdrant"),
74
+ ("from fastembed", "fastembed"),
75
+ ("import io.ktor", "ktor"),
76
+ ("import org.springframework", "spring"),
77
+ ("import androidx", "android"),
78
+ ("gin-gonic/gin", "gin"),
79
+ ("gofiber/fiber", "fiber"),
80
+ ("use actix", "actix"),
81
+ ("use axum", "axum"),
82
+ ("use tokio", "tokio"),
83
+ ]
84
+
85
+
86
+ def _extra_tokens(rel: str, lines: list) -> str:
87
+ stem = Path(rel).stem
88
+ parts = []
89
+ if stem in _FRAMEWORK_FILENAMES:
90
+ parts.append(_FRAMEWORK_FILENAMES[stem])
91
+ header = "\n".join(lines[:50])
92
+ seen = set(parts)
93
+ for pattern, framework in _FRAMEWORK_IMPORTS:
94
+ if pattern in header and framework not in seen:
95
+ parts.append(framework)
96
+ seen.add(framework)
97
+ return " ".join(parts)
98
+
99
+
20
100
  try:
21
101
  from tree_sitter import Language, Parser as _TSParser
22
102
  import tree_sitter_python as _tspy
@@ -49,7 +129,7 @@ except Exception:
49
129
  _TS_SEMANTIC = {}
50
130
 
51
131
 
52
- def _sliding_window(lines: list, start: int, end: int, repo_name: str, rel: str, language: str, github_url_base: str = "") -> list:
132
+ def _sliding_window(lines: list, start: int, end: int, repo_name: str, rel: str, language: str, github_url_base: str = "", extra_tokens: str = "") -> list:
53
133
  step = CHUNK_LINES - OVERLAP_LINES
54
134
  chunks = []
55
135
  i = start
@@ -58,10 +138,13 @@ def _sliding_window(lines: list, start: int, end: int, repo_name: str, rel: str,
58
138
  body = "\n".join(lines[i:j]).strip()
59
139
  if body:
60
140
  url = f"{github_url_base}/{rel}#L{i+1}-L{j}" if github_url_base else ""
141
+ header = f"# {repo_name}/{rel} (lines {i+1}-{j})"
142
+ if extra_tokens:
143
+ header += f"\n# {extra_tokens}"
61
144
  chunks.append({
62
145
  "repo": repo_name, "file": rel, "language": language,
63
146
  "start_line": i + 1, "end_line": j,
64
- "text": f"# {repo_name}/{rel} (lines {i+1}-{j})\n\n{body}",
147
+ "text": f"{header}\n\n{body}",
65
148
  "github_url": url,
66
149
  })
67
150
  if j == end:
@@ -110,6 +193,7 @@ def chunk_file(path: Path, repo_name: str, base_dir: Path | None = None, github_
110
193
  except ValueError:
111
194
  rel = path.name
112
195
  language = LANG_MAP.get(ext, ext.lstrip("."))
196
+ extra = _extra_tokens(rel, lines)
113
197
 
114
198
  if _TS_AVAILABLE and ext in _TS_LANGUAGES:
115
199
  try:
@@ -123,19 +207,22 @@ def chunk_file(path: Path, repo_name: str, base_dir: Path | None = None, github_
123
207
  s = node.start_point[0]
124
208
  e = node.end_point[0] + 1
125
209
  if e - s > MAX_CHUNK_LINES:
126
- chunks.extend(_sliding_window(lines, s, e, repo_name, rel, language, github_url_base))
210
+ chunks.extend(_sliding_window(lines, s, e, repo_name, rel, language, github_url_base, extra))
127
211
  else:
128
212
  body = "\n".join(lines[s:e]).strip()
129
213
  if body:
130
214
  url = f"{github_url_base}/{rel}#L{s+1}-L{e}" if github_url_base else ""
215
+ header = f"# {repo_name}/{rel} (lines {s+1}-{e})"
216
+ if extra:
217
+ header += f"\n# {extra}"
131
218
  chunks.append({
132
219
  "repo": repo_name, "file": rel, "language": language,
133
220
  "start_line": s + 1, "end_line": e,
134
- "text": f"# {repo_name}/{rel} (lines {s+1}-{e})\n\n{body}",
221
+ "text": f"{header}\n\n{body}",
135
222
  "github_url": url,
136
223
  })
137
224
  return chunks
138
225
  except Exception:
139
226
  pass
140
227
 
141
- return _sliding_window(lines, 0, len(lines), repo_name, rel, language, github_url_base)
228
+ return _sliding_window(lines, 0, len(lines), repo_name, rel, language, github_url_base, extra)
@@ -13,7 +13,7 @@ from qdrant_client.models import Prefetch, Fusion, SparseVector
13
13
  from .config import (
14
14
  qdrant_path, data_dir, VERSION, VECTOR_SIZE,
15
15
  WORKSPACES_DIR, get_active_workspace, set_active_workspace,
16
- get_workspace_dir,
16
+ get_workspace_dir, PPR_THRESHOLD,
17
17
  )
18
18
  from .embedder import embed, sparse_embed
19
19
  from .state import _stats, get_graph_meta, save_stats, invalidate_graph_cache
@@ -59,7 +59,7 @@ def _ppr_block(matched_files: list, matched_scores: list) -> str | None:
59
59
  except Exception:
60
60
  return None
61
61
  graph_path = data_dir() / "graph_notes.json"
62
- extras, reason = ppr_augment(matched_files, matched_scores, graph_path, _return_reason=True)
62
+ extras, reason = ppr_augment(matched_files, matched_scores, graph_path, threshold=PPR_THRESHOLD, _return_reason=True)
63
63
  if extras:
64
64
  _stats["ppr_fires"] += 1
65
65
  _stats["ppr_results_added"] += len(extras)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cortex-local"
7
- version = "2.1.0"
7
+ dynamic = ["version"]
8
8
  description = "Local semantic search MCP server — notes + code, embedded Qdrant, fastembed"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -25,5 +25,10 @@ cortex = "cortex.cli:cli"
25
25
  [project.entry-points."mcp.servers"]
26
26
  cortex = "cortex.mcp_server:run"
27
27
 
28
+ [tool.hatch.version]
29
+ source = "regex"
30
+ path = "../VERSION"
31
+ pattern = "^(?P<version>[0-9]+\\.[0-9]+\\.[0-9]+)"
32
+
28
33
  [tool.hatch.build.targets.wheel]
29
34
  packages = ["cortex"]
File without changes