Add init_repo
This commit is contained in:
+87
-13
@@ -42,7 +42,7 @@ OLLAMA_BASE_URL = "http://127.0.0.1:11434"
|
||||
os.environ["OLLAMA_HOST"] = OLLAMA_BASE_URL
|
||||
os.environ["OLLAMA_API_BASE"] = OLLAMA_BASE_URL
|
||||
|
||||
CODEBASE_PATH = Path(os.environ.get("CODEBASE_PATH", "/home/popertots/Crussell")) # change as needed
|
||||
CODEBASE_PATH = Path(os.environ.get("CODEBASE_PATH", ".")) # change as needed
|
||||
VECTOR_DB_PATH = Path(os.environ.get("VECTOR_DB_PATH", "./chroma_db"))
|
||||
BM25_INDEX_PATH = Path(os.environ.get("BM25_INDEX_PATH", "./bm25_index.json"))
|
||||
RAGIGNORE_PATH = CODEBASE_PATH / ".ragignore"
|
||||
@@ -2244,6 +2244,92 @@ Example – read_file_lines_tool("src/auth/login.py", start=45, end=60) → full
|
||||
Note: This tool treats / as '/home/popertots/Crussell/' so adjust paths accordingly"""
|
||||
return EnhancedToon.file_content_results(read_file_lines(path, start, end), path)
|
||||
|
||||
@mcp.tool()
|
||||
def init_repo(git_url: str) -> str:
|
||||
"""What it does – Initialise the RAG stack with a brand‑new Git repository or update an existing one.
|
||||
|
||||
The function will:
|
||||
1. Clone the repo if it does not already exist locally,
|
||||
2. Pull the latest changes if it does,
|
||||
3. Reset the global `CODEBASE_PATH` to the local clone,
|
||||
4. Remove any stale index artefacts,
|
||||
5. Re‑build the vector/BM25 indexes with the same lock‑protected flow used by `rebuild_index`,
|
||||
6. Return a human‑readable status message.
|
||||
|
||||
Next steps:
|
||||
• Call `health_check` to confirm that the server is ready.
|
||||
• Use `search_codebase` or `find_code_references` to explore the new code.
|
||||
• Use `read_file_lines_tool` to inspect any hit in detail.
|
||||
"""
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
# ----- 1. Determine where to clone ---------------------------------
|
||||
repo_name = git_url.split('/')[-1]
|
||||
if repo_name.endswith('.git'):
|
||||
repo_name = repo_name[:-4]
|
||||
clone_dir = Path.cwd() / repo_name
|
||||
|
||||
# ----- 2. Clone / pull -----------------------------------------------
|
||||
try:
|
||||
if clone_dir.exists():
|
||||
# Existing repo → pull
|
||||
subprocess.run(
|
||||
["git", "-C", str(clone_dir), "pull"],
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
else:
|
||||
# New repo → clone
|
||||
subprocess.run(
|
||||
["git", "clone", git_url],
|
||||
cwd=str(Path.cwd()),
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
return f"❌ Failed to clone/pull {git_url}: {e.stderr.strip()}"
|
||||
|
||||
# ----- 3. Update the global CODEBASE_PATH --------------------------------
|
||||
global CODEBASE_PATH
|
||||
CODEBASE_PATH = clone_dir
|
||||
|
||||
# ----- 4. Remove stale indices ----------------------------------------
|
||||
for artefact in ("chroma_db", "bm25_index.json", "embeddings"):
|
||||
artefact_path = CODEBASE_PATH / artefact
|
||||
if artefact_path.exists():
|
||||
try:
|
||||
if artefact_path.is_dir():
|
||||
shutil.rmtree(artefact_path)
|
||||
else:
|
||||
artefact_path.unlink()
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not delete {artefact_path}: {e}")
|
||||
|
||||
# ----- 5. Re‑build the index (protected by the startup lock) ------------
|
||||
try:
|
||||
rebuild_index()
|
||||
except Exception as e:
|
||||
return f"❌ Index rebuild failed: {e}"
|
||||
|
||||
# ----- 6. Report success -----------------------------------------------
|
||||
branch_name = subprocess.check_output(
|
||||
["git", "-C", str(CODEBASE_PATH), "rev-parse", "--abbrev-ref", "HEAD"],
|
||||
text=True,
|
||||
).strip()
|
||||
git_hash = subprocess.check_output(
|
||||
["git", "-C", str(CODEBASE_PATH), "rev-parse", "HEAD"],
|
||||
text=True,
|
||||
).strip()
|
||||
|
||||
return f"✅ Initialized repository at {CODEBASE_PATH} on branch {branch_name} with hash {git_hash}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def rebuild_index() -> str:
|
||||
"""What it does – Re‑creates all embeddings, BM25, and metadata indexes after major code changes.
|
||||
@@ -2275,17 +2361,6 @@ Example – rebuild_index() → '✅ Index rebuilt (13.2 s); 11,234 chunks'"""
|
||||
# -----------------------------
|
||||
# Startup
|
||||
# -----------------------------
|
||||
def startup():
|
||||
with _startup_lock:
|
||||
if VECTOR_DB_PATH.exists() and BM25_INDEX_PATH.exists():
|
||||
try:
|
||||
load_indexes()
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed loading indexes: {e}; rebuilding")
|
||||
build_indexes()
|
||||
else:
|
||||
logger.info("No existing indexes found, building from scratch...")
|
||||
build_indexes()
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
"""Handle graceful shutdown on Ctrl+C."""
|
||||
@@ -2316,7 +2391,6 @@ if __name__ == "__main__":
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
|
||||
try:
|
||||
startup()
|
||||
logger.info("="*60)
|
||||
logger.info("🚀 MCP RAG Server is ready!")
|
||||
logger.info("Use 'python serve_http.py' for HTTP server")
|
||||
|
||||
Reference in New Issue
Block a user