codevira 1.6.0__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.
Files changed (58) hide show
  1. codevira-1.6.0.dist-info/LICENSE +21 -0
  2. codevira-1.6.0.dist-info/METADATA +477 -0
  3. codevira-1.6.0.dist-info/RECORD +58 -0
  4. codevira-1.6.0.dist-info/WHEEL +5 -0
  5. codevira-1.6.0.dist-info/entry_points.txt +2 -0
  6. codevira-1.6.0.dist-info/top_level.txt +2 -0
  7. indexer/__init__.py +1 -0
  8. indexer/chunker.py +428 -0
  9. indexer/global_db.py +197 -0
  10. indexer/graph_generator.py +380 -0
  11. indexer/index_codebase.py +588 -0
  12. indexer/outcome_tracker.py +172 -0
  13. indexer/rule_learner.py +186 -0
  14. indexer/sqlite_graph.py +640 -0
  15. indexer/treesitter_parser.py +423 -0
  16. mcp_server/__init__.py +1 -0
  17. mcp_server/__main__.py +20 -0
  18. mcp_server/auto_init.py +257 -0
  19. mcp_server/cli.py +622 -0
  20. mcp_server/crash_logger.py +236 -0
  21. mcp_server/data/__init__.py +1 -0
  22. mcp_server/data/agents/builder.md +84 -0
  23. mcp_server/data/agents/developer.md +111 -0
  24. mcp_server/data/agents/documenter.md +138 -0
  25. mcp_server/data/agents/orchestrator.md +96 -0
  26. mcp_server/data/agents/planner.md +106 -0
  27. mcp_server/data/agents/reviewer.md +82 -0
  28. mcp_server/data/agents/tester.md +83 -0
  29. mcp_server/data/config.example.yaml +33 -0
  30. mcp_server/data/rules/coding-standards.md +48 -0
  31. mcp_server/data/rules/engineering-excellence.md +28 -0
  32. mcp_server/data/rules/git-cicd-governance.md +32 -0
  33. mcp_server/data/rules/git_commits.md +130 -0
  34. mcp_server/data/rules/incremental-updates.md +5 -0
  35. mcp_server/data/rules/master_rule.md +187 -0
  36. mcp_server/data/rules/multi-language.md +19 -0
  37. mcp_server/data/rules/persistence.md +21 -0
  38. mcp_server/data/rules/resilience-observability.md +17 -0
  39. mcp_server/data/rules/smoke-testing.md +48 -0
  40. mcp_server/data/rules/testing-standards.md +23 -0
  41. mcp_server/detect.py +284 -0
  42. mcp_server/gitignore.py +284 -0
  43. mcp_server/global_sync.py +187 -0
  44. mcp_server/http_server.py +341 -0
  45. mcp_server/ide_inject.py +444 -0
  46. mcp_server/launchd.py +156 -0
  47. mcp_server/migrate.py +215 -0
  48. mcp_server/paths.py +256 -0
  49. mcp_server/prompts.py +136 -0
  50. mcp_server/server.py +1049 -0
  51. mcp_server/tools/__init__.py +0 -0
  52. mcp_server/tools/changesets.py +223 -0
  53. mcp_server/tools/code_reader.py +335 -0
  54. mcp_server/tools/graph.py +637 -0
  55. mcp_server/tools/learning.py +238 -0
  56. mcp_server/tools/playbook.py +89 -0
  57. mcp_server/tools/roadmap.py +599 -0
  58. mcp_server/tools/search.py +145 -0
@@ -0,0 +1,145 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ from mcp_server.paths import get_data_dir, get_project_root
9
+ from mcp_server.tools.graph import get_impact
10
+ from indexer.sqlite_graph import SQLiteGraph
11
+
12
+ def _get_db() -> SQLiteGraph:
13
+ db_path = get_data_dir() / "graph" / "graph.db"
14
+ return SQLiteGraph(db_path)
15
+
16
+ def _get_chroma_client():
17
+ try:
18
+ import chromadb
19
+ from chromadb.utils import embedding_functions
20
+ except ImportError:
21
+ return None, None
22
+
23
+ db_dir = get_data_dir() / "codeindex"
24
+ if not db_dir.exists():
25
+ return None, None
26
+
27
+ client = chromadb.PersistentClient(path=str(db_dir))
28
+ embed_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
29
+ model_name="all-MiniLM-L6-v2"
30
+ )
31
+ return client, embed_fn
32
+
33
+ def search_codebase(description: str, top_k: int = 5) -> dict[str, Any]:
34
+ client, embed_fn = _get_chroma_client()
35
+ if not client:
36
+ # v1.6: Check if auto-init is running and return a friendly status
37
+ try:
38
+ from mcp_server.auto_init import get_init_progress
39
+ prog = get_init_progress()
40
+ if prog["status"] in ("initializing", "indexing"):
41
+ return {
42
+ "status": "indexing",
43
+ "message": "Semantic index is being built in the background. Try again in a few seconds.",
44
+ "indexing_progress": prog,
45
+ }
46
+ except Exception:
47
+ pass
48
+ return {
49
+ "error": "Semantic index not found.",
50
+ "hint": "Install search deps with: pip install 'codevira[search]', then run: codevira index --full",
51
+ }
52
+
53
+ try:
54
+ collection = client.get_collection("codebase_index", embedding_function=embed_fn)
55
+ results = collection.query(query_texts=[description], n_results=top_k)
56
+
57
+ matches = []
58
+ if results["documents"] and results["documents"][0]:
59
+ for i in range(len(results["documents"][0])):
60
+ doc = results["documents"][0][i]
61
+ meta = results["metadatas"][0][i]
62
+ matches.append({
63
+ "file_path": meta["file_path"],
64
+ "chunk_type": meta["chunk_type"],
65
+ "name": meta["name"],
66
+ "content": doc,
67
+ "relevance_score": 1.0 - (results["distances"][0][i] if "distances" in results else 0),
68
+ })
69
+ return {
70
+ "query": description,
71
+ "matches": matches,
72
+ "hint": "Use get_code(file_path, symbol) to read full source.",
73
+ }
74
+ except Exception as e:
75
+ try:
76
+ from mcp_server.crash_logger import log_crash
77
+ log_crash(e, context="search_codebase")
78
+ except Exception:
79
+ pass
80
+ return {"error": f"Search failed: {e}"}
81
+
82
+ def write_session_log(session_id: str, task: str, phase: str, files_changed: list[str], decisions: list[dict], next_steps: list[str]) -> dict[str, str]:
83
+ """Write a structured session log to SQLite Memory."""
84
+ db = _get_db()
85
+ db.log_session(session_id, task, phase, decisions)
86
+ db.close()
87
+
88
+ # v1.5: Export qualifying learnings to global memory
89
+ try:
90
+ from mcp_server.global_sync import export_project_to_global
91
+ export_project_to_global()
92
+ except Exception as e:
93
+ try:
94
+ from mcp_server.crash_logger import log_crash
95
+ log_crash(e, context="write_session_log: global export")
96
+ except Exception:
97
+ pass
98
+
99
+ return {"status": f"Session {session_id} logged to SQLite Memory."}
100
+
101
+ def search_decisions(query: str, limit: int = 10, session_id: str | None = None) -> dict[str, Any]:
102
+ db = _get_db()
103
+ results = db.search_decisions(query, limit, session_id)
104
+ db.close()
105
+
106
+ return {
107
+ "query": query,
108
+ "results": results,
109
+ "hint": "Use these past decisions to avoid repeating mistakes."
110
+ }
111
+
112
+ def get_history(file_path: str) -> dict[str, Any]:
113
+ db = _get_db()
114
+ sql = '''
115
+ SELECT d.decision, d.context, s.summary, d.created_at, d.session_id
116
+ FROM decisions d
117
+ JOIN sessions s ON d.session_id = s.session_id
118
+ WHERE d.file_path = ? OR s.summary LIKE ?
119
+ ORDER BY d.created_at DESC
120
+ '''
121
+ cur = db.conn.execute(sql, (file_path, f'%{file_path}%'))
122
+ results = [dict(r) for r in cur.fetchall()]
123
+ db.close()
124
+
125
+ return {
126
+ "file_path": file_path,
127
+ "history": results,
128
+ }
129
+
130
+ def refresh_index(file_paths: list[str]) -> dict:
131
+ from indexer.index_codebase import cmd_incremental
132
+ requested_files = file_paths or None
133
+ cmd_incremental(quiet=True, file_paths=requested_files)
134
+
135
+ if requested_files:
136
+ return {
137
+ "status": f"Index refreshed for {len(requested_files)} requested file(s).",
138
+ "file_paths": requested_files,
139
+ "mode": "targeted",
140
+ }
141
+
142
+ return {
143
+ "status": "Index refreshed for all changed files.",
144
+ "mode": "incremental",
145
+ }