Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e24df66
Enrich Neo4j symbol nodes with signature and docstring
m1rl0k Jan 19, 2026
ad011b8
Update base.py
m1rl0k Jan 19, 2026
c7d8c7e
Improve symbol resolution and edge enrichment in graph backend
m1rl0k Jan 19, 2026
64aed19
Pass import_map to call edge extraction functions
m1rl0k Jan 19, 2026
060728f
Add class inheritance edge extraction and querying
m1rl0k Jan 19, 2026
ce2b5ef
Improve env loading and Rust inheritance handling
m1rl0k Jan 19, 2026
0e85c81
Update config.py
m1rl0k Jan 19, 2026
4447e54
Improve robustness and thread safety in graph and upload clients
m1rl0k Jan 19, 2026
41a7b67
Update GDS PageRank to use new aggregation syntax
m1rl0k Jan 19, 2026
5d5ea22
Improve error handling and logging across graph and Qdrant scripts
m1rl0k Jan 19, 2026
be5212b
Update backend.py
m1rl0k Jan 19, 2026
7fea14e
Replace deprecated get_event_loop with get_running_loop
m1rl0k Jan 19, 2026
ce31e70
Add logging for exception handling in scripts
m1rl0k Jan 19, 2026
ad12993
Add logging for suppressed exceptions across codebase
m1rl0k Jan 19, 2026
36f9790
Add get_results helper and update tests for result extraction
m1rl0k Jan 19, 2026
a996fcf
Refactor TOON encoder and improve backfill logic
m1rl0k Jan 19, 2026
8a4b0f7
Defer pseudo-tag generation and add post-index backfill
m1rl0k Jan 19, 2026
c4bcb46
Add fixture to clean module pollution after tests
m1rl0k Jan 19, 2026
a0f8cf1
Add transaction timeouts and improve Neo4j cleanup
m1rl0k Jan 19, 2026
8b1365f
Improve thread safety and error logging in graph modules
m1rl0k Jan 19, 2026
0332f94
Add robust error handling and stricter argument checks
m1rl0k Jan 19, 2026
dbd6950
Add detailed exception logging throughout workspace_state.py
m1rl0k Jan 19, 2026
ff9e318
Add detailed debug logging for exception handling
m1rl0k Jan 19, 2026
c05c419
Add debug log for OrderedDict import fallback
m1rl0k Jan 19, 2026
a626180
Add detailed debug logging for exception handling
m1rl0k Jan 19, 2026
fdc85a0
Update hybrid_search.py
m1rl0k Jan 19, 2026
3d7a9af
Add detailed exception logging across MCP scripts
m1rl0k Jan 19, 2026
c064e13
Improve exception logging and add kwargs extraction utility
m1rl0k Jan 19, 2026
433f45b
Update search_history.py
m1rl0k Jan 19, 2026
db1a627
Update context_answer.py
m1rl0k Jan 19, 2026
c07fb3f
Improve exception logging for debugging
m1rl0k Jan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions docker-compose.neo4j.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,34 @@
#
# This adds Neo4j as an alternative graph backend for symbol relationships.
# Provides advanced graph traversals, path finding, and relationship analytics.
# Includes Graph Data Science (GDS) library for PageRank, community detection, etc.
#
# Enable via: NEO4J_GRAPH=1 in your .env file
#
# Browser: http://localhost:7474 (login: neo4j / contextengine)
# Bolt: bolt://localhost:7687

services:
# Neo4j Graph Database
# Neo4j Graph Database with Graph Data Science
neo4j:
image: neo4j:5.15-community
image: neo4j:5.26.0-community
container_name: neo4j-graph
ports:
- "7474:7474" # HTTP browser interface
- "7687:7687" # Bolt protocol
volumes:
- neo4j_data:/data
- neo4j_logs:/logs
- neo4j_plugins:/plugins
environment:
- NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:-contextengine}
- NEO4J_PLUGINS=["apoc"]
- NEO4J_dbms_security_procedures_unrestricted=apoc.*
- NEO4J_PLUGINS=["apoc", "graph-data-science"]
- NEO4J_dbms_security_procedures_unrestricted=apoc.*,gds.*
- NEO4J_dbms_security_procedures_allowlist=apoc.*,gds.*
# Neo4j 5.x uses server.memory.* instead of dbms.memory.*
- NEO4J_server_memory_pagecache_size=512M
- NEO4J_server_memory_heap_initial__size=1G
- NEO4J_server_memory_heap_max__size=1G
- NEO4J_server_memory_pagecache_size=1G
- NEO4J_server_memory_heap_initial__size=2G
- NEO4J_server_memory_heap_max__size=2G
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:7474 || exit 1"]
interval: 10s
Expand Down Expand Up @@ -88,4 +91,6 @@ volumes:
driver: local
neo4j_logs:
driver: local
neo4j_plugins:
driver: local

679 changes: 618 additions & 61 deletions plugins/neo4j_graph/backend.py

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions plugins/neo4j_graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class GraphEdge:
language: Optional[str] = None
caller_point_id: Optional[str] = None
callee_path: Optional[str] = None # Resolved path where callee is defined
# Symbol metadata (from Qdrant points)
caller_signature: Optional[str] = None
caller_docstring: Optional[str] = None

def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary for serialization.
Expand All @@ -74,6 +77,10 @@ def to_dict(self) -> Dict[str, Any]:
d["callee_path"] = self.callee_path
if self.caller_point_id:
d["caller_point_id"] = self.caller_point_id
if self.caller_signature:
d["caller_signature"] = self.caller_signature
if self.caller_docstring:
d["caller_docstring"] = self.caller_docstring
return d

@dataclass
Expand Down
75 changes: 67 additions & 8 deletions plugins/neo4j_graph/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ def cmd_backfill(args):
from qdrant_client import QdrantClient
from .backend import Neo4jGraphBackend

# Import edge extraction from ingest_adapter for consistent resolution
# Try to import ingest_adapter for proper symbol resolution
try:
from scripts.graph_backends.ingest_adapter import extract_call_edges, extract_import_edges
use_ingest_adapter = True
except ImportError:
# Fallback to local base if ingest_adapter not available
from .base import GraphEdge
extract_call_edges = None
extract_import_edges = None
use_ingest_adapter = False
print(" Warning: ingest_adapter not available, edges will have unresolved callee paths")

collection = args.collection
limit = args.limit
Expand Down Expand Up @@ -155,9 +155,14 @@ def cmd_backfill(args):

calls = meta.get("calls", []) or []
imports = meta.get("imports", []) or []

# Use ingest_adapter for consistent edge extraction with full resolution
if extract_call_edges is not None:
# import_map maps local names to qualified paths for resolution
# e.g., {"QdrantClient": "qdrant_client.QdrantClient"}
import_map = meta.get("import_map", {}) or {}
symbol_signature = meta.get("symbol_signature", "") or ""
symbol_docstring = meta.get("symbol_docstring", "") or ""

if use_ingest_adapter:
# Use ingest_adapter for proper symbol resolution
call_edges = extract_call_edges(
symbol_path=symbol_path,
calls=calls,
Expand All @@ -167,12 +172,16 @@ def cmd_backfill(args):
end_line=end_line,
language=language,
caller_point_id=str(p.id),
import_paths=import_map, # Pass import_map for resolution
collection=collection,
qdrant_client=client,
)
# Enrich edges with symbol metadata
for edge in call_edges:
edge.caller_signature = symbol_signature
edge.caller_docstring = symbol_docstring
edges.extend(call_edges)

if extract_import_edges is not None:
import_edges = extract_import_edges(
symbol_path=symbol_path,
imports=imports,
Expand All @@ -183,7 +192,48 @@ def cmd_backfill(args):
collection=collection,
qdrant_client=client,
)
# Enrich edges with symbol metadata
for edge in import_edges:
edge.caller_signature = symbol_signature
edge.caller_docstring = symbol_docstring
edges.extend(import_edges)
else:
# Fallback: Create edges directly without resolution
for callee in calls:
if callee and isinstance(callee, str):
edge_id = f"{symbol_path}:calls:{callee}"
edges.append(GraphEdge(
id=edge_id,
edge_type="calls",
caller_symbol=symbol_path,
callee_symbol=callee,
caller_path=path,
callee_path="", # Unknown - will be resolved if found
repo=repo,
language=language,
start_line=start_line,
end_line=end_line,
caller_signature=symbol_signature,
caller_docstring=symbol_docstring,
))

for imported in imports:
if imported and isinstance(imported, str):
edge_id = f"{symbol_path}:imports:{imported}"
edges.append(GraphEdge(
id=edge_id,
edge_type="imports",
caller_symbol=symbol_path,
callee_symbol=imported,
caller_path=path,
callee_path="",
repo=repo,
language=language,
start_line=start_line,
end_line=end_line,
caller_signature=symbol_signature,
caller_docstring=symbol_docstring,
))

total_points += 1

Expand All @@ -205,6 +255,15 @@ def cmd_backfill(args):
total_edges += count

print(f"\n✓ Backfilled {total_edges} edges from {total_points} points to Neo4j")

# Post-process: resolve unresolved edges to real definitions
print(" Resolving unresolved edges to real definitions...")
resolved = backend.resolve_unresolved_edges(collection)
if resolved > 0:
print(f" ✓ Resolved {resolved} edges")
else:
print(" (no edges could be resolved)")

return 0


Expand Down
Loading
Loading