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_HOST"] = OLLAMA_BASE_URL
|
||||||
os.environ["OLLAMA_API_BASE"] = 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"))
|
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"))
|
BM25_INDEX_PATH = Path(os.environ.get("BM25_INDEX_PATH", "./bm25_index.json"))
|
||||||
RAGIGNORE_PATH = CODEBASE_PATH / ".ragignore"
|
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"""
|
Note: This tool treats / as '/home/popertots/Crussell/' so adjust paths accordingly"""
|
||||||
return EnhancedToon.file_content_results(read_file_lines(path, start, end), path)
|
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()
|
@mcp.tool()
|
||||||
def rebuild_index() -> str:
|
def rebuild_index() -> str:
|
||||||
"""What it does – Re‑creates all embeddings, BM25, and metadata indexes after major code changes.
|
"""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
|
# 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):
|
def signal_handler(sig, frame):
|
||||||
"""Handle graceful shutdown on Ctrl+C."""
|
"""Handle graceful shutdown on Ctrl+C."""
|
||||||
@@ -2316,7 +2391,6 @@ if __name__ == "__main__":
|
|||||||
signal.signal(signal.SIGTERM, signal_handler)
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
startup()
|
|
||||||
logger.info("="*60)
|
logger.info("="*60)
|
||||||
logger.info("🚀 MCP RAG Server is ready!")
|
logger.info("🚀 MCP RAG Server is ready!")
|
||||||
logger.info("Use 'python serve_http.py' for HTTP server")
|
logger.info("Use 'python serve_http.py' for HTTP server")
|
||||||
|
|||||||
Reference in New Issue
Block a user