Working-in-a-Codemine / tools /neurograph_tool.py
Executor-Tyrant-Framework's picture
QB QC pass: fix broken PolicyEngine call, tighten exception handling
a0533c6
# ---- Changelog ----
# [2026-03-29] Chisel/TQB β€” Block C: NeurographTool
# What: search_conversations, search_code, search_testament, ingest_workspace extracted
# Why: PRD Block C β€” DRY the three identical search methods into one _search(), single responsibility
# How: _search(query, n, domain) is the single recall path; public methods format differently
# [2026-03-30] QB β€” Block D: Error handling hardening
# What: Specific exception types, logger instead of broad catches, fixed can_access_path call
# Why: PRD Block D β€” no broad except Exception, structured logging
# How: Catch (OSError, ValueError, KeyError) for NG ops; fix policy_engine.can_access_path signature
# -------------------
import logging
from pathlib import Path
from typing import Dict, List
logger = logging.getLogger("tools.neurograph")
class NeurographTool:
"""NeuroGraph-backed search and workspace ingestion."""
def __init__(self, repo_path: Path, ng, policy_engine=None):
self.repo_path = repo_path
self.ng = ng
self.policy_engine = policy_engine
def _search(self, query: str, n: int, domain: str) -> List[Dict]:
"""Single recall path β€” all search methods delegate here."""
try:
results = self.ng.recall(query, k=n, threshold=0.3)
if domain == "conversations":
return [{
"content": r.get("content", ""),
"similarity": r.get("similarity", 0),
"id": r.get("node_id", "")
} for r in results]
else:
# code and testament share the same format
return [{
"file": r.get("metadata", {}).get("source", "memory"),
"snippet": r.get("content", "")[:500]
} for r in results]
except (OSError, ValueError, KeyError, TypeError) as e:
logger.error("[neurograph] _search(%s) failed: %s: %s", domain, type(e).__name__, e, exc_info=True)
return [{"status": "error", "tool": "neurograph", "error": str(e), "type": type(e).__name__}]
def search_conversations(self, query: str, n: int = 5) -> List[Dict]:
"""Semantic recall from NeuroGraph memory."""
return self._search(query, n, "conversations")
def search_code(self, query: str, n: int = 5) -> List[Dict]:
"""Semantic code search via NeuroGraph recall."""
return self._search(query, n, "code")
def search_testament(self, query: str, n: int = 5) -> List[Dict]:
"""Search docs/markdown via NeuroGraph recall."""
return self._search(query, n, "testament")
def ingest_workspace(self) -> str:
try:
if self.policy_engine:
from policy_engine import check_tool_call
allowed, reason = check_tool_call("ingest_workspace", {}, self.repo_path)
if not allowed:
return {"status": "error", "tool": "neurograph", "error": reason, "type": "PermissionError"}
results = self.ng.ingest_directory(str(self.repo_path), extensions=[".py", ".md", ".txt"])
return f"Indexed {len(results)} files into NeuroGraph."
except (OSError, ValueError, TypeError) as e:
logger.error("[neurograph] ingest_workspace failed: %s: %s", type(e).__name__, e, exc_info=True)
return {"status": "error", "tool": "neurograph", "error": str(e), "type": type(e).__name__}