codevira 1.7.0__tar.gz → 1.7.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.
- {codevira-1.7.0 → codevira-1.7.1}/CHANGELOG.md +31 -0
- {codevira-1.7.0/codevira.egg-info → codevira-1.7.1}/PKG-INFO +2 -2
- {codevira-1.7.0 → codevira-1.7.1}/README.md +1 -1
- {codevira-1.7.0 → codevira-1.7.1/codevira.egg-info}/PKG-INFO +2 -2
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/__init__.py +1 -1
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/auto_init.py +9 -1
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/cli.py +2 -1
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/http_server.py +7 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/migrate.py +7 -2
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/server.py +9 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/search.py +79 -0
- {codevira-1.7.0 → codevira-1.7.1}/pyproject.toml +1 -1
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_auto_init.py +2 -1
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_migrate.py +2 -1
- {codevira-1.7.0 → codevira-1.7.1}/LICENSE +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/MANIFEST.in +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/agents/builder.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/agents/developer.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/agents/documenter.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/agents/orchestrator.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/agents/planner.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/agents/reviewer.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/agents/tester.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/SOURCES.txt +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/dependency_links.txt +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/entry_points.txt +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/requires.txt +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/top_level.txt +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/config.example.yaml +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/docs/how-i-built-persistent-memory-for-ai-agents.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/docs/linkedin-article-ai-agent-memory.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/docs/linkedin-post-ai-agent-memory.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/docs/medium-your-ai-coding-agent-has-amnesia.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/docs/roadmap.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/graph/_schema.yaml +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/__init__.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/chunker.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/global_db.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/graph_generator.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/index_codebase.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/outcome_tracker.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/rule_learner.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/sqlite_graph.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/indexer/treesitter_parser.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/__main__.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/crash_logger.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/__init__.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/builder.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/developer.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/documenter.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/orchestrator.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/planner.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/reviewer.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/tester.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/config.example.yaml +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/coding-standards.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/engineering-excellence.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/git-cicd-governance.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/git_commits.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/incremental-updates.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/master_rule.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/multi-language.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/persistence.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/resilience-observability.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/smoke-testing.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/testing-standards.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/detect.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/gitignore.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/global_sync.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/ide_inject.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/launchd.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/log_retention.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/paths.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/prompts.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/__init__.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/changesets.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/code_reader.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/graph.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/learning.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/playbook.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/roadmap.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/coding-standards.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/engineering-excellence.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/git-cicd-governance.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/git_commits.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/incremental-updates.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/master_rule.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/persistence.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/resilience-observability.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/smoke-testing.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/rules/testing-standards.md +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/setup.cfg +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_chunker.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_cli.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_crash_logger.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_detect.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_gitignore.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_global_db.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_global_sync.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_graph_generator.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_http_server.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_ide_inject.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_index_codebase.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_launchd.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_log_retention.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_outcome_tracker.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_paths.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_prompts.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_rule_learner.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_server.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_sqlite_graph.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_changesets.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_code_reader.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_graph.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_learning.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_playbook.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_roadmap.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_search.py +0 -0
- {codevira-1.7.0 → codevira-1.7.1}/tests/test_treesitter_parser.py +0 -0
|
@@ -13,6 +13,37 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
+
## [1.7.1] — 2026-04-22 — Search Timeout Fix & Version Display
|
|
17
|
+
|
|
18
|
+
Two small but user-visible fixes on top of v1.7.0.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **`search_codebase` timeout on first call** (reported by a user testing
|
|
23
|
+
on Antigravity). The embedding model (`all-MiniLM-L6-v2`) was being
|
|
24
|
+
instantiated fresh on every MCP tool call, which triggered a ~90MB
|
|
25
|
+
download + PyTorch init on first ever use (30-60s on slow networks)
|
|
26
|
+
and 1-3s of re-init overhead on every subsequent call. Antigravity's
|
|
27
|
+
~30s MCP tool timeout killed the query before the model finished loading.
|
|
28
|
+
|
|
29
|
+
Three-layer fix:
|
|
30
|
+
1. Module-level cache for the chroma client + embedding function,
|
|
31
|
+
keyed by `db_dir`. Subsequent calls are now instant.
|
|
32
|
+
2. Background `prewarm_embedding_model()` spawned at server startup
|
|
33
|
+
(both stdio and HTTP transports). Model loads in parallel with
|
|
34
|
+
the MCP handshake window.
|
|
35
|
+
3. Cold-path timeout guard: if a query arrives while warmup is still
|
|
36
|
+
in progress, returns `{"status": "warming", ...}` within 10 seconds
|
|
37
|
+
instead of blocking until the MCP timeout fires. The agent gets a
|
|
38
|
+
clean retryable response.
|
|
39
|
+
|
|
40
|
+
- **`codevira register` banner showed hardcoded `v1.6`** after upgrading
|
|
41
|
+
to v1.7.0. Now reads `mcp_server.__version__` dynamically. Same fix
|
|
42
|
+
applied to `metadata.json` version field written during auto-init and
|
|
43
|
+
migration.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
16
47
|
## [1.7.0] — 2026-04-18 — Token Efficiency & AI-First Tool Design
|
|
17
48
|
|
|
18
49
|
**The biggest release since v1.0.** We realized Codevira was dumping 15k-60k
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: codevira
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: Persistent adaptive memory for AI coding agents — MCP server with context graph, semantic search, adaptive learning, roadmap tracking, and cross-tool continuity.
|
|
5
5
|
Author-email: Sachin Shelke <sachin.worldnet@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -44,7 +44,7 @@ Provides-Extra: all
|
|
|
44
44
|
[](https://www.python.org/)
|
|
45
45
|
[](LICENSE)
|
|
46
46
|
[](https://modelcontextprotocol.io)
|
|
47
|
-
[](CHANGELOG.md)
|
|
48
48
|
[](CONTRIBUTING.md)
|
|
49
49
|
|
|
50
50
|
**Built for solo developers** working on local projects with AI agents. Codevira gives every AI tool you use access to the same persistent project memory — so you stop re-explaining your codebase every session, stop losing carefully-made decisions, and stop burning tokens on re-discovery.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.python.org/)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://modelcontextprotocol.io)
|
|
8
|
-
[](CHANGELOG.md)
|
|
9
9
|
[](CONTRIBUTING.md)
|
|
10
10
|
|
|
11
11
|
**Built for solo developers** working on local projects with AI agents. Codevira gives every AI tool you use access to the same persistent project memory — so you stop re-explaining your codebase every session, stop losing carefully-made decisions, and stop burning tokens on re-discovery.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: codevira
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: Persistent adaptive memory for AI coding agents — MCP server with context graph, semantic search, adaptive learning, roadmap tracking, and cross-tool continuity.
|
|
5
5
|
Author-email: Sachin Shelke <sachin.worldnet@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -44,7 +44,7 @@ Provides-Extra: all
|
|
|
44
44
|
[](https://www.python.org/)
|
|
45
45
|
[](LICENSE)
|
|
46
46
|
[](https://modelcontextprotocol.io)
|
|
47
|
-
[](CHANGELOG.md)
|
|
48
48
|
[](CONTRIBUTING.md)
|
|
49
49
|
|
|
50
50
|
**Built for solo developers** working on local projects with AI agents. Codevira gives every AI tool you use access to the same persistent project memory — so you stop re-explaining your codebase every session, stop losing carefully-made decisions, and stop burning tokens on re-discovery.
|
|
@@ -223,6 +223,14 @@ def _write_config(data_dir: Path, detected: dict, project_root: Path) -> None:
|
|
|
223
223
|
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
|
|
224
224
|
|
|
225
225
|
|
|
226
|
+
def _codevira_version() -> str:
|
|
227
|
+
try:
|
|
228
|
+
from mcp_server import __version__
|
|
229
|
+
return __version__
|
|
230
|
+
except Exception:
|
|
231
|
+
return "unknown"
|
|
232
|
+
|
|
233
|
+
|
|
226
234
|
def _write_metadata(data_dir: Path, project_root: Path) -> None:
|
|
227
235
|
"""Write metadata.json so the centralized dir is recognized."""
|
|
228
236
|
import json
|
|
@@ -234,7 +242,7 @@ def _write_metadata(data_dir: Path, project_root: Path) -> None:
|
|
|
234
242
|
"git_remote": _get_git_remote_url(project_root),
|
|
235
243
|
"original_path": str(project_root),
|
|
236
244
|
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
237
|
-
"version":
|
|
245
|
+
"version": _codevira_version(),
|
|
238
246
|
"auto_initialized": True,
|
|
239
247
|
}
|
|
240
248
|
(data_dir / "metadata.json").write_text(json.dumps(metadata, indent=2))
|
|
@@ -464,8 +464,9 @@ def cmd_register(
|
|
|
464
464
|
project_root = get_project_root()
|
|
465
465
|
cmd_path, python_exe = _resolve_command()
|
|
466
466
|
|
|
467
|
+
from mcp_server import __version__
|
|
467
468
|
print()
|
|
468
|
-
print(" Codevira — Global IDE Registration (
|
|
469
|
+
print(f" Codevira — Global IDE Registration (v{__version__})")
|
|
469
470
|
print(" " + "─" * 44)
|
|
470
471
|
print()
|
|
471
472
|
|
|
@@ -340,6 +340,13 @@ def run_http_server(
|
|
|
340
340
|
except Exception as e:
|
|
341
341
|
logger.warning("Log retention cleanup failed: %s", e)
|
|
342
342
|
|
|
343
|
+
# v1.7: Pre-warm the embedding model in a background thread
|
|
344
|
+
try:
|
|
345
|
+
from mcp_server.tools.search import prewarm_embedding_model
|
|
346
|
+
prewarm_embedding_model()
|
|
347
|
+
except Exception as e:
|
|
348
|
+
logger.warning("Embedding prewarm failed: %s", e)
|
|
349
|
+
|
|
343
350
|
# ---- TLS certificate setup ----
|
|
344
351
|
ssl_certfile: str | None = None
|
|
345
352
|
ssl_keyfile: str | None = None
|
|
@@ -22,7 +22,12 @@ from pathlib import Path
|
|
|
22
22
|
|
|
23
23
|
logger = logging.getLogger(__name__)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
def _codevira_version() -> str:
|
|
26
|
+
try:
|
|
27
|
+
from mcp_server import __version__
|
|
28
|
+
return __version__
|
|
29
|
+
except Exception:
|
|
30
|
+
return "unknown"
|
|
26
31
|
|
|
27
32
|
|
|
28
33
|
def detect_migration_needed(project_root: Path) -> bool:
|
|
@@ -140,7 +145,7 @@ def migrate_to_centralized(project_root: Path) -> dict:
|
|
|
140
145
|
"git_remote": git_remote,
|
|
141
146
|
"original_path": str(project_root),
|
|
142
147
|
"migrated_at": datetime.now(timezone.utc).isoformat(),
|
|
143
|
-
"version":
|
|
148
|
+
"version": _codevira_version(),
|
|
144
149
|
}
|
|
145
150
|
(centralized / "metadata.json").write_text(json.dumps(metadata, indent=2))
|
|
146
151
|
|
|
@@ -1135,6 +1135,15 @@ def main():
|
|
|
1135
1135
|
try: log_crash(e, context="log retention cleanup")
|
|
1136
1136
|
except Exception: pass
|
|
1137
1137
|
|
|
1138
|
+
# v1.7: Pre-warm the embedding model in a background thread so the first
|
|
1139
|
+
# search_codebase() call doesn't hit the MCP client's ~30s timeout
|
|
1140
|
+
# while waiting for PyTorch init / model download.
|
|
1141
|
+
try:
|
|
1142
|
+
from mcp_server.tools.search import prewarm_embedding_model
|
|
1143
|
+
prewarm_embedding_model()
|
|
1144
|
+
except Exception as e:
|
|
1145
|
+
logger.warning("Embedding prewarm failed: %s", e)
|
|
1146
|
+
|
|
1138
1147
|
async def _run():
|
|
1139
1148
|
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
|
|
1140
1149
|
await server.run(
|
|
@@ -9,6 +9,16 @@ def _get_db() -> SQLiteGraph:
|
|
|
9
9
|
db_path = get_data_dir() / "graph" / "graph.db"
|
|
10
10
|
return SQLiteGraph(db_path)
|
|
11
11
|
|
|
12
|
+
|
|
13
|
+
# Module-level cache for the semantic search stack.
|
|
14
|
+
# Creating SentenceTransformerEmbeddingFunction triggers:
|
|
15
|
+
# - ~90MB model download on first use (cached in ~/.cache/huggingface/)
|
|
16
|
+
# - PyTorch/onnxruntime init (~1-3s even after download)
|
|
17
|
+
# Caching avoids paying this cost on every search_codebase call — first
|
|
18
|
+
# call is still slow but subsequent calls are instant.
|
|
19
|
+
_chroma_cache: dict = {"client": None, "embed_fn": None, "db_dir": None}
|
|
20
|
+
|
|
21
|
+
|
|
12
22
|
def _get_chroma_client():
|
|
13
23
|
try:
|
|
14
24
|
import chromadb
|
|
@@ -20,12 +30,48 @@ def _get_chroma_client():
|
|
|
20
30
|
if not db_dir.exists():
|
|
21
31
|
return None, None
|
|
22
32
|
|
|
33
|
+
# Reuse cached client + embed_fn if we're hitting the same project's index
|
|
34
|
+
# (PersistentClient is tied to a specific path; invalidate if path changes).
|
|
35
|
+
if (
|
|
36
|
+
_chroma_cache["client"] is not None
|
|
37
|
+
and _chroma_cache["embed_fn"] is not None
|
|
38
|
+
and _chroma_cache["db_dir"] == str(db_dir)
|
|
39
|
+
):
|
|
40
|
+
return _chroma_cache["client"], _chroma_cache["embed_fn"]
|
|
41
|
+
|
|
23
42
|
client = chromadb.PersistentClient(path=str(db_dir))
|
|
24
43
|
embed_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
|
|
25
44
|
model_name="all-MiniLM-L6-v2"
|
|
26
45
|
)
|
|
46
|
+
_chroma_cache["client"] = client
|
|
47
|
+
_chroma_cache["embed_fn"] = embed_fn
|
|
48
|
+
_chroma_cache["db_dir"] = str(db_dir)
|
|
27
49
|
return client, embed_fn
|
|
28
50
|
|
|
51
|
+
|
|
52
|
+
def prewarm_embedding_model() -> None:
|
|
53
|
+
"""Pre-load the embedding model in a background thread at server startup.
|
|
54
|
+
|
|
55
|
+
SentenceTransformerEmbeddingFunction triggers a ~90MB model download on
|
|
56
|
+
first use and 1-3s of PyTorch init. If we wait until the first
|
|
57
|
+
search_codebase() call, Antigravity's ~30s MCP timeout can kill the query.
|
|
58
|
+
|
|
59
|
+
Called from server.main() and http_server.run_http_server() via a daemon
|
|
60
|
+
thread — the server becomes ready immediately; search gets warmed up in
|
|
61
|
+
parallel. Safe to call multiple times (cached after first successful load).
|
|
62
|
+
"""
|
|
63
|
+
import threading
|
|
64
|
+
|
|
65
|
+
def _warmup():
|
|
66
|
+
try:
|
|
67
|
+
_get_chroma_client() # populates _chroma_cache
|
|
68
|
+
except Exception:
|
|
69
|
+
# Failure is non-fatal — search_codebase will retry on next call
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
t = threading.Thread(target=_warmup, daemon=True, name="codevira-embed-prewarm")
|
|
73
|
+
t.start()
|
|
74
|
+
|
|
29
75
|
def search_codebase(description: str, top_k: int = 5, include_content: bool = False) -> dict[str, Any]:
|
|
30
76
|
"""Semantic search over the codebase.
|
|
31
77
|
|
|
@@ -36,6 +82,39 @@ def search_codebase(description: str, top_k: int = 5, include_content: bool = Fa
|
|
|
36
82
|
Pass include_content=True only when you explicitly need the chunk source
|
|
37
83
|
inline (can be 500-3000 tokens per match).
|
|
38
84
|
"""
|
|
85
|
+
# Fast path: if another thread is still pre-warming the embedding model,
|
|
86
|
+
# return a "warming" status immediately instead of blocking for 30s+ and
|
|
87
|
+
# triggering the MCP client's timeout. Agent retries get served once
|
|
88
|
+
# warmup is done.
|
|
89
|
+
if _chroma_cache["embed_fn"] is None:
|
|
90
|
+
# Cache miss. Try to populate it (fast if model is already downloaded
|
|
91
|
+
# and cached on disk; slow only the first time ever across any project).
|
|
92
|
+
# Wrap in a short timeout so we don't block the MCP thread.
|
|
93
|
+
import threading as _th
|
|
94
|
+
load_done = _th.Event()
|
|
95
|
+
load_err = [None]
|
|
96
|
+
|
|
97
|
+
def _load():
|
|
98
|
+
try:
|
|
99
|
+
_get_chroma_client()
|
|
100
|
+
except Exception as e:
|
|
101
|
+
load_err[0] = e
|
|
102
|
+
finally:
|
|
103
|
+
load_done.set()
|
|
104
|
+
|
|
105
|
+
_th.Thread(target=_load, daemon=True, name="codevira-embed-sync-load").start()
|
|
106
|
+
# Wait up to 10 seconds — enough for warm-cache loads, short of MCP timeout
|
|
107
|
+
if not load_done.wait(timeout=10.0):
|
|
108
|
+
return {
|
|
109
|
+
"status": "warming",
|
|
110
|
+
"message": (
|
|
111
|
+
"Semantic search model is loading (first-time setup downloads ~90MB). "
|
|
112
|
+
"Try this query again in 30-60 seconds. Other tools work normally."
|
|
113
|
+
),
|
|
114
|
+
}
|
|
115
|
+
if load_err[0] is not None:
|
|
116
|
+
return {"error": f"Embedding model load failed: {load_err[0]}"}
|
|
117
|
+
|
|
39
118
|
client, embed_fn = _get_chroma_client()
|
|
40
119
|
if not client:
|
|
41
120
|
# v1.6: Check if auto-init is running and return a friendly status
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codevira"
|
|
7
|
-
version = "1.7.
|
|
7
|
+
version = "1.7.1"
|
|
8
8
|
description = "Persistent adaptive memory for AI coding agents — MCP server with context graph, semantic search, adaptive learning, roadmap tracking, and cross-tool continuity."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -330,7 +330,8 @@ class TestWriteMetadata:
|
|
|
330
330
|
assert meta["path_key"] == "test_key"
|
|
331
331
|
assert meta["git_remote"] == "git@github.com:test/repo.git"
|
|
332
332
|
assert meta["original_path"] == str(project_root)
|
|
333
|
-
|
|
333
|
+
from mcp_server import __version__
|
|
334
|
+
assert meta["version"] == __version__
|
|
334
335
|
assert meta["auto_initialized"] is True
|
|
335
336
|
assert "created_at" in meta
|
|
336
337
|
|
|
@@ -237,7 +237,8 @@ class TestMigrateToCentralized:
|
|
|
237
237
|
meta = json.loads(meta_file.read_text())
|
|
238
238
|
assert meta["path_key"] == key
|
|
239
239
|
assert meta["original_path"] == str(project)
|
|
240
|
-
|
|
240
|
+
from mcp_server import __version__
|
|
241
|
+
assert meta["version"] == __version__
|
|
241
242
|
assert "migrated_at" in meta
|
|
242
243
|
|
|
243
244
|
def test_metadata_contains_git_remote(self, tmp_path, monkeypatch):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|