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.
- codevira-1.6.0.dist-info/LICENSE +21 -0
- codevira-1.6.0.dist-info/METADATA +477 -0
- codevira-1.6.0.dist-info/RECORD +58 -0
- codevira-1.6.0.dist-info/WHEEL +5 -0
- codevira-1.6.0.dist-info/entry_points.txt +2 -0
- codevira-1.6.0.dist-info/top_level.txt +2 -0
- indexer/__init__.py +1 -0
- indexer/chunker.py +428 -0
- indexer/global_db.py +197 -0
- indexer/graph_generator.py +380 -0
- indexer/index_codebase.py +588 -0
- indexer/outcome_tracker.py +172 -0
- indexer/rule_learner.py +186 -0
- indexer/sqlite_graph.py +640 -0
- indexer/treesitter_parser.py +423 -0
- mcp_server/__init__.py +1 -0
- mcp_server/__main__.py +20 -0
- mcp_server/auto_init.py +257 -0
- mcp_server/cli.py +622 -0
- mcp_server/crash_logger.py +236 -0
- mcp_server/data/__init__.py +1 -0
- mcp_server/data/agents/builder.md +84 -0
- mcp_server/data/agents/developer.md +111 -0
- mcp_server/data/agents/documenter.md +138 -0
- mcp_server/data/agents/orchestrator.md +96 -0
- mcp_server/data/agents/planner.md +106 -0
- mcp_server/data/agents/reviewer.md +82 -0
- mcp_server/data/agents/tester.md +83 -0
- mcp_server/data/config.example.yaml +33 -0
- mcp_server/data/rules/coding-standards.md +48 -0
- mcp_server/data/rules/engineering-excellence.md +28 -0
- mcp_server/data/rules/git-cicd-governance.md +32 -0
- mcp_server/data/rules/git_commits.md +130 -0
- mcp_server/data/rules/incremental-updates.md +5 -0
- mcp_server/data/rules/master_rule.md +187 -0
- mcp_server/data/rules/multi-language.md +19 -0
- mcp_server/data/rules/persistence.md +21 -0
- mcp_server/data/rules/resilience-observability.md +17 -0
- mcp_server/data/rules/smoke-testing.md +48 -0
- mcp_server/data/rules/testing-standards.md +23 -0
- mcp_server/detect.py +284 -0
- mcp_server/gitignore.py +284 -0
- mcp_server/global_sync.py +187 -0
- mcp_server/http_server.py +341 -0
- mcp_server/ide_inject.py +444 -0
- mcp_server/launchd.py +156 -0
- mcp_server/migrate.py +215 -0
- mcp_server/paths.py +256 -0
- mcp_server/prompts.py +136 -0
- mcp_server/server.py +1049 -0
- mcp_server/tools/__init__.py +0 -0
- mcp_server/tools/changesets.py +223 -0
- mcp_server/tools/code_reader.py +335 -0
- mcp_server/tools/graph.py +637 -0
- mcp_server/tools/learning.py +238 -0
- mcp_server/tools/playbook.py +89 -0
- mcp_server/tools/roadmap.py +599 -0
- 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
|
+
}
|