code-context-control 2.145.1__py3-none-any.whl → 2.145.2__py3-none-any.whl
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.
- cli/c3.py +1 -1
- {code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/METADATA +1 -1
- {code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/RECORD +8 -8
- services/embedding_index.py +76 -13
- {code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/WHEEL +0 -0
- {code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/entry_points.txt +0 -0
- {code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/licenses/LICENSE +0 -0
- {code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/top_level.txt +0 -0
cli/c3.py
CHANGED
|
@@ -91,7 +91,7 @@ console = Console() if HAS_RICH else None
|
|
|
91
91
|
# Config
|
|
92
92
|
CONFIG_DIR = ".c3"
|
|
93
93
|
CONFIG_FILE = ".c3/config.json"
|
|
94
|
-
__version__ = "2.145.
|
|
94
|
+
__version__ = "2.145.2"
|
|
95
95
|
|
|
96
96
|
# The PreToolUse matcher for native subagent calls (installer and hub migration).
|
|
97
97
|
AGENT_MATCHER = "Agent|Task"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.145.
|
|
3
|
+
Version: 2.145.2
|
|
4
4
|
Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
cli/__init__.py,sha256=ec66drCZGNMRU4V6ov0zVhYZph1us12Vn8OvG_LJyRY,22
|
|
2
2
|
cli/_hook_utils.py,sha256=RhfS2WS5VMSi2w2Jxcts1wg5WC-UFp89JOQvcO5Jjb8,23002
|
|
3
3
|
cli/_shell_writes.py,sha256=XzUNlUDljmg-wZxK03xHnRe36WeQxe4tpO9HKVFwP5o,5090
|
|
4
|
-
cli/c3.py,sha256=
|
|
4
|
+
cli/c3.py,sha256=Thn44zRVOuNqg22oafbPECYSXzQCBYZycF377xu1zIE,431828
|
|
5
5
|
cli/docs.html,sha256=pPxcP5ieY0DcfEDvegwIcRxbz1woLZoKLVSF-4JVy0Q,146784
|
|
6
6
|
cli/edits.html,sha256=UjAhoCmBmQ89cklGvJqzC6eyNP2tc8H6T-e01DVkLvE,43418
|
|
7
7
|
cli/hook_access_guard.py,sha256=Mjrrt3agYCWPqSjdzk_Sw4ooMrizO8Um-nQjgGfXck4,27896
|
|
@@ -131,7 +131,7 @@ cli/ui/components/sessions.js,sha256=FIKtil76B8tCkAmcFV7hlj6GQ_DCJK2jCzvEmdK7NBE
|
|
|
131
131
|
cli/ui/components/settings.js,sha256=FXcn-UQE2mXC6HFsLeEas-wAUFKt0OJaLySroZQMhGA,84095
|
|
132
132
|
cli/ui/components/sidebar.js,sha256=K2ym2kUgpbyG-EBA_wBIIiqQY8qTatsiBZwzseMWuIQ,9939
|
|
133
133
|
cli/ui/components/tasks.js,sha256=vyKQ3uwoppMwvdEaHlhWXW4oWcAisx4NveqzMhsYqHo,38438
|
|
134
|
-
code_context_control-2.145.
|
|
134
|
+
code_context_control-2.145.2.dist-info/licenses/LICENSE,sha256=l8Kh5QCNWNvR6kIt8L0BUZvc2LAFiHv2c-FnsGnUZf4,11301
|
|
135
135
|
core/__init__.py,sha256=TSDCEcM4V7gcZVM3w2ykJaqEUch4Dkon-rivV17T73s,2501
|
|
136
136
|
core/codex_patch.py,sha256=CxvT_rQIwPNTRJZj9EHJmx0ZdOeSLxjiixuLI3Z7lPc,2107
|
|
137
137
|
core/config.py,sha256=wCjrZKXRywUbR6WRcO7optyOirAQ2DeRNdPCU0X5zIY,23762
|
|
@@ -233,7 +233,7 @@ services/e2e_benchmark.py,sha256=5Z3rE42o08MKVbIX_769V0RX2yAzSVcApCvdAQ9YLAU,134
|
|
|
233
233
|
services/e2e_evaluator.py,sha256=FsB4vMzcFUcmicfIwRtA8JZ_XeMpuk2_-86F2iVNEDc,17783
|
|
234
234
|
services/e2e_tasks.py,sha256=Ln5VbGDIcS3NY3aml5ERbgjfjLxEslmRZ8AyaYxpWEo,34524
|
|
235
235
|
services/edit_ledger.py,sha256=Tj8Q14o19VHQHpofRHdbZKKcVs17v-ctZ3LOeVTqvdQ,29362
|
|
236
|
-
services/embedding_index.py,sha256=
|
|
236
|
+
services/embedding_index.py,sha256=wqq7odpGzAxyO-lxr6N1WusyEGInGgEQUjuEw445Bxs,27711
|
|
237
237
|
services/enforcement_policy.py,sha256=znjABRB-8TSl0ELazY2ALzux2YJ5nWf8TvxLRhDsL2w,18905
|
|
238
238
|
services/error_reporting.py,sha256=HZ3ru8i5RLf8nq2R4iRnTs5sm1blUxknSbv5hdxuxs0,4139
|
|
239
239
|
services/file_map.py,sha256=j37DTR-UE_PMNj7vG2HiHucpwpJNaKgiD94UNUU-UXE,17091
|
|
@@ -333,8 +333,8 @@ tui/screens/search_view.py,sha256=MMHjVdlk3HZSuDBSvq8IGrqv_Mh5Us6YqXQ80bcWSMk,19
|
|
|
333
333
|
tui/screens/session_view.py,sha256=eZ1eDwHTvPOck1wCCviixtOaCxIkBT_95ytNNNriGNA,5991
|
|
334
334
|
tui/screens/stats.py,sha256=p81PjzdaIv7hllb8f45-rlVe4lJZwSdIMqu7e86_u5s,6223
|
|
335
335
|
tui/screens/ui_view.py,sha256=1QJCgLh2YfgWIpvzRG1KOGXYEaOYX6ojN61Azjf2oX0,2125
|
|
336
|
-
code_context_control-2.145.
|
|
337
|
-
code_context_control-2.145.
|
|
338
|
-
code_context_control-2.145.
|
|
339
|
-
code_context_control-2.145.
|
|
340
|
-
code_context_control-2.145.
|
|
336
|
+
code_context_control-2.145.2.dist-info/METADATA,sha256=bHhi9gHWwyOe6v9kxLBSGBFgB_jEEtfWVQomsR91rss,28902
|
|
337
|
+
code_context_control-2.145.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
338
|
+
code_context_control-2.145.2.dist-info/entry_points.txt,sha256=7kX_WUsDCF2hbXzvbNyscyaBb9AeA-DJY5v_5hN0DlU,93
|
|
339
|
+
code_context_control-2.145.2.dist-info/top_level.txt,sha256=wRt41zBybVF3qAiNXHz9BURbkKvUvfhmWWtKMhaw6eE,29
|
|
340
|
+
code_context_control-2.145.2.dist-info/RECORD,,
|
services/embedding_index.py
CHANGED
|
@@ -6,10 +6,13 @@ embeddings. Tracks file content hashes to only re-embed changed files.
|
|
|
6
6
|
Falls back gracefully when Ollama or chromadb are unavailable.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
import gc
|
|
9
10
|
import hashlib
|
|
10
11
|
import json
|
|
11
12
|
import logging
|
|
13
|
+
import shutil
|
|
12
14
|
import threading
|
|
15
|
+
from datetime import datetime
|
|
13
16
|
from pathlib import Path
|
|
14
17
|
|
|
15
18
|
log = logging.getLogger("c3.embedding_index")
|
|
@@ -106,19 +109,7 @@ class EmbeddingIndex:
|
|
|
106
109
|
def _init_backends(self):
|
|
107
110
|
"""Initialize chromadb collection and check Ollama."""
|
|
108
111
|
try:
|
|
109
|
-
|
|
110
|
-
from chromadb.config import Settings
|
|
111
|
-
|
|
112
|
-
persist_dir = str(self._index_dir / "chromadb")
|
|
113
|
-
Path(persist_dir).mkdir(parents=True, exist_ok=True)
|
|
114
|
-
self._chroma_client = chromadb.PersistentClient(
|
|
115
|
-
path=persist_dir,
|
|
116
|
-
settings=Settings(anonymized_telemetry=False),
|
|
117
|
-
)
|
|
118
|
-
self._collection = self._chroma_client.get_or_create_collection(
|
|
119
|
-
name=COLLECTION_NAME,
|
|
120
|
-
metadata={"hnsw:space": "cosine"},
|
|
121
|
-
)
|
|
112
|
+
self._open_chroma()
|
|
122
113
|
self._available = True
|
|
123
114
|
self._drop_legacy_collection()
|
|
124
115
|
except Exception as e:
|
|
@@ -135,6 +126,78 @@ class EmbeddingIndex:
|
|
|
135
126
|
self._model_ok = False
|
|
136
127
|
self._ollama_ok = self._ollama_up and self._model_ok
|
|
137
128
|
|
|
129
|
+
def _open_chroma(self, _retried: bool = False) -> None:
|
|
130
|
+
"""Open the persistent collection, quarantining a corrupt store once.
|
|
131
|
+
|
|
132
|
+
A damaged HNSW segment does not surface at open time: the Rust backend
|
|
133
|
+
accepts the client and the collection handle, then faults on the first
|
|
134
|
+
real read. When that read happens on the background index thread it has
|
|
135
|
+
taken the whole MCP process down with an access violation, which the
|
|
136
|
+
host reports only as a dead server (seen 2026-07-17, 2026-09-06).
|
|
137
|
+
|
|
138
|
+
So probe here, on the init path, where the failure is still a catchable
|
|
139
|
+
Python exception, and treat a failed probe as a corrupt store: close the
|
|
140
|
+
client, move the directory aside, and reopen empty. The store is a
|
|
141
|
+
rebuildable cache, so the cost is one re-embed, not lost data.
|
|
142
|
+
"""
|
|
143
|
+
import chromadb
|
|
144
|
+
from chromadb.config import Settings
|
|
145
|
+
|
|
146
|
+
persist_dir = self._index_dir / "chromadb"
|
|
147
|
+
persist_dir.mkdir(parents=True, exist_ok=True)
|
|
148
|
+
self._chroma_client = chromadb.PersistentClient(
|
|
149
|
+
path=str(persist_dir),
|
|
150
|
+
settings=Settings(anonymized_telemetry=False),
|
|
151
|
+
)
|
|
152
|
+
self._collection = self._chroma_client.get_or_create_collection(
|
|
153
|
+
name=COLLECTION_NAME,
|
|
154
|
+
metadata={"hnsw:space": "cosine"},
|
|
155
|
+
)
|
|
156
|
+
try:
|
|
157
|
+
self._collection.count()
|
|
158
|
+
except Exception as e:
|
|
159
|
+
if _retried:
|
|
160
|
+
raise
|
|
161
|
+
log.warning(
|
|
162
|
+
"embedding store failed its health probe (%s); "
|
|
163
|
+
"quarantining and rebuilding",
|
|
164
|
+
e,
|
|
165
|
+
)
|
|
166
|
+
self._quarantine_store(persist_dir)
|
|
167
|
+
self._open_chroma(_retried=True)
|
|
168
|
+
|
|
169
|
+
def _close_chroma(self) -> None:
|
|
170
|
+
"""Drop the client so Windows releases its handle on chroma.sqlite3."""
|
|
171
|
+
client = self._chroma_client
|
|
172
|
+
self._collection = None
|
|
173
|
+
self._chroma_client = None
|
|
174
|
+
try:
|
|
175
|
+
close = getattr(client, "close", None)
|
|
176
|
+
if callable(close):
|
|
177
|
+
close()
|
|
178
|
+
except Exception:
|
|
179
|
+
pass
|
|
180
|
+
gc.collect()
|
|
181
|
+
|
|
182
|
+
def _quarantine_store(self, persist_dir: Path) -> None:
|
|
183
|
+
"""Move a corrupt store and its hash file aside for post-mortem.
|
|
184
|
+
|
|
185
|
+
The hashes go with it: they claim vectors that the fresh store does not
|
|
186
|
+
have, so leaving them behind would suppress the very rebuild this is
|
|
187
|
+
meant to trigger.
|
|
188
|
+
"""
|
|
189
|
+
self._close_chroma()
|
|
190
|
+
dest = self._index_dir / f"quarantine_corrupt_{datetime.now():%Y%m%d_%H%M%S}"
|
|
191
|
+
dest.mkdir(parents=True, exist_ok=True)
|
|
192
|
+
shutil.move(str(persist_dir), str(dest / persist_dir.name))
|
|
193
|
+
try:
|
|
194
|
+
if self._hash_file.exists():
|
|
195
|
+
shutil.move(str(self._hash_file), str(dest / self._hash_file.name))
|
|
196
|
+
except OSError:
|
|
197
|
+
self._hash_file.unlink(missing_ok=True)
|
|
198
|
+
self._file_hashes = {}
|
|
199
|
+
log.warning("quarantined corrupt embedding store to %s", dest)
|
|
200
|
+
|
|
138
201
|
def _drop_legacy_collection(self) -> None:
|
|
139
202
|
"""Best-effort removal of the pre-2.108.0 collection and hash file.
|
|
140
203
|
|
|
File without changes
|
{code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{code_context_control-2.145.1.dist-info → code_context_control-2.145.2.dist-info}/top_level.txt
RENAMED
|
File without changes
|