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.
Files changed (119) hide show
  1. {codevira-1.7.0 → codevira-1.7.1}/CHANGELOG.md +31 -0
  2. {codevira-1.7.0/codevira.egg-info → codevira-1.7.1}/PKG-INFO +2 -2
  3. {codevira-1.7.0 → codevira-1.7.1}/README.md +1 -1
  4. {codevira-1.7.0 → codevira-1.7.1/codevira.egg-info}/PKG-INFO +2 -2
  5. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/__init__.py +1 -1
  6. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/auto_init.py +9 -1
  7. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/cli.py +2 -1
  8. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/http_server.py +7 -0
  9. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/migrate.py +7 -2
  10. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/server.py +9 -0
  11. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/search.py +79 -0
  12. {codevira-1.7.0 → codevira-1.7.1}/pyproject.toml +1 -1
  13. {codevira-1.7.0 → codevira-1.7.1}/tests/test_auto_init.py +2 -1
  14. {codevira-1.7.0 → codevira-1.7.1}/tests/test_migrate.py +2 -1
  15. {codevira-1.7.0 → codevira-1.7.1}/LICENSE +0 -0
  16. {codevira-1.7.0 → codevira-1.7.1}/MANIFEST.in +0 -0
  17. {codevira-1.7.0 → codevira-1.7.1}/agents/builder.md +0 -0
  18. {codevira-1.7.0 → codevira-1.7.1}/agents/developer.md +0 -0
  19. {codevira-1.7.0 → codevira-1.7.1}/agents/documenter.md +0 -0
  20. {codevira-1.7.0 → codevira-1.7.1}/agents/orchestrator.md +0 -0
  21. {codevira-1.7.0 → codevira-1.7.1}/agents/planner.md +0 -0
  22. {codevira-1.7.0 → codevira-1.7.1}/agents/reviewer.md +0 -0
  23. {codevira-1.7.0 → codevira-1.7.1}/agents/tester.md +0 -0
  24. {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/SOURCES.txt +0 -0
  25. {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/dependency_links.txt +0 -0
  26. {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/entry_points.txt +0 -0
  27. {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/requires.txt +0 -0
  28. {codevira-1.7.0 → codevira-1.7.1}/codevira.egg-info/top_level.txt +0 -0
  29. {codevira-1.7.0 → codevira-1.7.1}/config.example.yaml +0 -0
  30. {codevira-1.7.0 → codevira-1.7.1}/docs/how-i-built-persistent-memory-for-ai-agents.md +0 -0
  31. {codevira-1.7.0 → codevira-1.7.1}/docs/linkedin-article-ai-agent-memory.md +0 -0
  32. {codevira-1.7.0 → codevira-1.7.1}/docs/linkedin-post-ai-agent-memory.md +0 -0
  33. {codevira-1.7.0 → codevira-1.7.1}/docs/medium-your-ai-coding-agent-has-amnesia.md +0 -0
  34. {codevira-1.7.0 → codevira-1.7.1}/docs/roadmap.md +0 -0
  35. {codevira-1.7.0 → codevira-1.7.1}/graph/_schema.yaml +0 -0
  36. {codevira-1.7.0 → codevira-1.7.1}/indexer/__init__.py +0 -0
  37. {codevira-1.7.0 → codevira-1.7.1}/indexer/chunker.py +0 -0
  38. {codevira-1.7.0 → codevira-1.7.1}/indexer/global_db.py +0 -0
  39. {codevira-1.7.0 → codevira-1.7.1}/indexer/graph_generator.py +0 -0
  40. {codevira-1.7.0 → codevira-1.7.1}/indexer/index_codebase.py +0 -0
  41. {codevira-1.7.0 → codevira-1.7.1}/indexer/outcome_tracker.py +0 -0
  42. {codevira-1.7.0 → codevira-1.7.1}/indexer/rule_learner.py +0 -0
  43. {codevira-1.7.0 → codevira-1.7.1}/indexer/sqlite_graph.py +0 -0
  44. {codevira-1.7.0 → codevira-1.7.1}/indexer/treesitter_parser.py +0 -0
  45. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/__main__.py +0 -0
  46. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/crash_logger.py +0 -0
  47. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/__init__.py +0 -0
  48. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/builder.md +0 -0
  49. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/developer.md +0 -0
  50. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/documenter.md +0 -0
  51. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/orchestrator.md +0 -0
  52. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/planner.md +0 -0
  53. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/reviewer.md +0 -0
  54. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/agents/tester.md +0 -0
  55. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/config.example.yaml +0 -0
  56. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/coding-standards.md +0 -0
  57. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/engineering-excellence.md +0 -0
  58. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/git-cicd-governance.md +0 -0
  59. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/git_commits.md +0 -0
  60. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/incremental-updates.md +0 -0
  61. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/master_rule.md +0 -0
  62. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/multi-language.md +0 -0
  63. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/persistence.md +0 -0
  64. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/resilience-observability.md +0 -0
  65. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/smoke-testing.md +0 -0
  66. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/data/rules/testing-standards.md +0 -0
  67. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/detect.py +0 -0
  68. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/gitignore.py +0 -0
  69. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/global_sync.py +0 -0
  70. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/ide_inject.py +0 -0
  71. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/launchd.py +0 -0
  72. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/log_retention.py +0 -0
  73. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/paths.py +0 -0
  74. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/prompts.py +0 -0
  75. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/__init__.py +0 -0
  76. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/changesets.py +0 -0
  77. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/code_reader.py +0 -0
  78. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/graph.py +0 -0
  79. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/learning.py +0 -0
  80. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/playbook.py +0 -0
  81. {codevira-1.7.0 → codevira-1.7.1}/mcp_server/tools/roadmap.py +0 -0
  82. {codevira-1.7.0 → codevira-1.7.1}/rules/coding-standards.md +0 -0
  83. {codevira-1.7.0 → codevira-1.7.1}/rules/engineering-excellence.md +0 -0
  84. {codevira-1.7.0 → codevira-1.7.1}/rules/git-cicd-governance.md +0 -0
  85. {codevira-1.7.0 → codevira-1.7.1}/rules/git_commits.md +0 -0
  86. {codevira-1.7.0 → codevira-1.7.1}/rules/incremental-updates.md +0 -0
  87. {codevira-1.7.0 → codevira-1.7.1}/rules/master_rule.md +0 -0
  88. {codevira-1.7.0 → codevira-1.7.1}/rules/persistence.md +0 -0
  89. {codevira-1.7.0 → codevira-1.7.1}/rules/resilience-observability.md +0 -0
  90. {codevira-1.7.0 → codevira-1.7.1}/rules/smoke-testing.md +0 -0
  91. {codevira-1.7.0 → codevira-1.7.1}/rules/testing-standards.md +0 -0
  92. {codevira-1.7.0 → codevira-1.7.1}/setup.cfg +0 -0
  93. {codevira-1.7.0 → codevira-1.7.1}/tests/test_chunker.py +0 -0
  94. {codevira-1.7.0 → codevira-1.7.1}/tests/test_cli.py +0 -0
  95. {codevira-1.7.0 → codevira-1.7.1}/tests/test_crash_logger.py +0 -0
  96. {codevira-1.7.0 → codevira-1.7.1}/tests/test_detect.py +0 -0
  97. {codevira-1.7.0 → codevira-1.7.1}/tests/test_gitignore.py +0 -0
  98. {codevira-1.7.0 → codevira-1.7.1}/tests/test_global_db.py +0 -0
  99. {codevira-1.7.0 → codevira-1.7.1}/tests/test_global_sync.py +0 -0
  100. {codevira-1.7.0 → codevira-1.7.1}/tests/test_graph_generator.py +0 -0
  101. {codevira-1.7.0 → codevira-1.7.1}/tests/test_http_server.py +0 -0
  102. {codevira-1.7.0 → codevira-1.7.1}/tests/test_ide_inject.py +0 -0
  103. {codevira-1.7.0 → codevira-1.7.1}/tests/test_index_codebase.py +0 -0
  104. {codevira-1.7.0 → codevira-1.7.1}/tests/test_launchd.py +0 -0
  105. {codevira-1.7.0 → codevira-1.7.1}/tests/test_log_retention.py +0 -0
  106. {codevira-1.7.0 → codevira-1.7.1}/tests/test_outcome_tracker.py +0 -0
  107. {codevira-1.7.0 → codevira-1.7.1}/tests/test_paths.py +0 -0
  108. {codevira-1.7.0 → codevira-1.7.1}/tests/test_prompts.py +0 -0
  109. {codevira-1.7.0 → codevira-1.7.1}/tests/test_rule_learner.py +0 -0
  110. {codevira-1.7.0 → codevira-1.7.1}/tests/test_server.py +0 -0
  111. {codevira-1.7.0 → codevira-1.7.1}/tests/test_sqlite_graph.py +0 -0
  112. {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_changesets.py +0 -0
  113. {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_code_reader.py +0 -0
  114. {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_graph.py +0 -0
  115. {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_learning.py +0 -0
  116. {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_playbook.py +0 -0
  117. {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_roadmap.py +0 -0
  118. {codevira-1.7.0 → codevira-1.7.1}/tests/test_tools_search.py +0 -0
  119. {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.0
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
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
45
45
  [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
46
46
  [![MCP](https://img.shields.io/badge/protocol-MCP-purple)](https://modelcontextprotocol.io)
47
- [![Version](https://img.shields.io/badge/version-1.7.0-orange)](CHANGELOG.md)
47
+ [![Version](https://img.shields.io/badge/version-1.7.1-orange)](CHANGELOG.md)
48
48
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](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
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
7
7
  [![MCP](https://img.shields.io/badge/protocol-MCP-purple)](https://modelcontextprotocol.io)
8
- [![Version](https://img.shields.io/badge/version-1.7.0-orange)](CHANGELOG.md)
8
+ [![Version](https://img.shields.io/badge/version-1.7.1-orange)](CHANGELOG.md)
9
9
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](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.0
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
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
45
45
  [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
46
46
  [![MCP](https://img.shields.io/badge/protocol-MCP-purple)](https://modelcontextprotocol.io)
47
- [![Version](https://img.shields.io/badge/version-1.7.0-orange)](CHANGELOG.md)
47
+ [![Version](https://img.shields.io/badge/version-1.7.1-orange)](CHANGELOG.md)
48
48
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](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.
@@ -14,4 +14,4 @@ internals — internal APIs may change between minor versions.
14
14
  from mcp_server.cli import main
15
15
 
16
16
  __all__ = ["main"]
17
- __version__ = "1.7.0"
17
+ __version__ = "1.7.1"
@@ -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": "1.6.0",
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 (v1.6)")
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
- _CODEVIRA_VERSION = "1.6.0"
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": _CODEVIRA_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.0"
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
- assert meta["version"] == "1.6.0"
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
- assert meta["version"] == "1.6.0"
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