Merge pull request #1834 from AndyMik90/fix/memory-falkordb-to-ladybug

fix(memory): complete FalkorDB to LadybugDB migration in memory system
This commit is contained in:
Andy
2026-02-20 11:58:09 +01:00
committed by GitHub
7 changed files with 60 additions and 27 deletions
+13 -3
View File
@@ -635,10 +635,20 @@ def get_graphiti_status() -> dict:
try:
# Attempt to import the main graphiti_memory module
import graphiti_core # noqa: F401
from graphiti_core.driver.falkordb_driver import FalkorDriver # noqa: F401
# If we got here, packages are importable
status["available"] = True # pragma: no cover
# Try LadybugDB first (preferred for Python 3.12+), fall back to kuzu
try:
import real_ladybug # noqa: F401
except ImportError:
try:
import kuzu # noqa: F401
except ImportError:
status["available"] = False
status["reason"] = (
"Graph database backend not installed (need real_ladybug or kuzu)"
)
return status
status["available"] = True
except ImportError as e:
status["available"] = False
status["reason"] = f"Graphiti packages not installed: {e}"
@@ -81,16 +81,16 @@ def mock_graphiti_core():
@pytest.fixture
def mock_falkor_driver():
"""Mock graphiti_core.driver.falkordb_driver.FalkorDriver.
def mock_kuzu_driver():
"""Mock graphiti_core.driver.kuzu_driver.KuzuDriver.
Prevents actual FalkorDB connections during tests.
Prevents actual LadybugDB/kuzu connections during tests.
Yields:
tuple: (mock_driver_class, mock_driver_instance)
"""
with patch(
"integrations.graphiti.queries_pkg.graphiti.graphiti_core.driver.falkordb_driver.FalkorDriver"
"integrations.graphiti.queries_pkg.graphiti.graphiti_core.driver.kuzu_driver.KuzuDriver"
) as mock_driver:
mock_instance = MagicMock()
mock_driver.return_value = mock_instance
@@ -15,7 +15,7 @@ Tests cover:
import json
import os
from pathlib import Path
from unittest.mock import patch
from unittest.mock import MagicMock, patch
import pytest
from integrations.graphiti.config import (
@@ -1054,20 +1054,48 @@ class TestModuleLevelFunctions:
assert "OPENAI_API_KEY" in status["errors"][0]
def test_get_graphiti_status_invalid_config_sets_reason(self, clean_env):
"""Test get_graphiti_status sets reason when config is invalid.
"""Test get_graphiti_status with validation errors (embedder misconfigured).
This tests lines 628-629 where the reason is set from validation errors.
When packages are installed but embedder config has errors, available should
still be True (embedder is optional - keyword search fallback exists).
Validation errors are reported in the errors list for informational purposes.
"""
os.environ["GRAPHITI_ENABLED"] = "true"
os.environ["GRAPHITI_EMBEDDER_PROVIDER"] = "voyage"
status = get_graphiti_status()
# Mock imports to ensure test is independent of environment
with patch.dict(
"sys.modules",
{"graphiti_core": MagicMock(), "real_ladybug": MagicMock()},
):
status = get_graphiti_status()
assert status["enabled"] is True
# available depends on whether mocked packages are resolved correctly;
# sys.modules patching should make imports succeed, but guard against
# environment quirks (consistent with test_get_graphiti_status_enabled)
assert status["available"] is True
assert len(status["errors"]) > 0
assert "VOYAGE_API_KEY" in status["errors"][0]
def test_get_graphiti_status_no_graph_backend(self, clean_env):
"""Test get_graphiti_status when graphiti_core exists but no graph DB backend.
This tests the error path in config.py lines 645-650 where graphiti_core
imports successfully but neither real_ladybug nor kuzu is available.
"""
os.environ["GRAPHITI_ENABLED"] = "true"
# Mock graphiti_core as present, but ensure real_ladybug and kuzu are absent
with patch.dict(
"sys.modules",
{"graphiti_core": MagicMock(), "real_ladybug": None, "kuzu": None},
):
status = get_graphiti_status()
assert status["enabled"] is True
assert status["available"] is False
# When config is invalid, reason should be set from errors
assert status["reason"] != ""
assert len(status["errors"]) > 0
assert "real_ladybug or kuzu" in status["reason"]
@pytest.mark.slow
def test_get_graphiti_status_with_graphiti_installed(self, clean_env):
@@ -1089,9 +1117,9 @@ class TestModuleLevelFunctions:
assert "reason" in status
assert "errors" in status
# Note: Line 641 (status["available"] = True) requires falkordb to be installed.
# Since falkordb is not installed in the test environment, that line is marked
# with pragma: no cover. The except clause (lines 642-644) is tested here.
# Note: Line 644 (status["available"] = True) requires LadybugDB/kuzu to be installed.
# Since LadybugDB/kuzu may not be installed in all test environments, that line
# may be marked with pragma: no cover. The except clause is tested here.
def test_get_available_providers_empty(self, clean_env):
"""Test get_available_providers with no credentials."""
@@ -264,7 +264,7 @@ class TestTestGraphitiConnection:
# Mock graphiti_core imports to succeed
mock_graphiti = MagicMock()
mock_falkordb_driver = MagicMock()
mock_kuzu_driver = MagicMock()
# Mock provider creation to raise ProviderError
with patch("graphiti_providers.create_llm_client") as mock_create_llm:
@@ -275,7 +275,7 @@ class TestTestGraphitiConnection:
{
"graphiti_core": MagicMock(Graphiti=mock_graphiti),
"graphiti_core.driver": MagicMock(),
"graphiti_core.driver.falkordb_driver": mock_falkordb_driver,
"graphiti_core.driver.kuzu_driver": mock_kuzu_driver,
"graphiti_providers": MagicMock(
ProviderError=ProviderError,
create_embedder=MagicMock(),
@@ -160,7 +160,7 @@ class TestTestGraphitiConnection:
"""Tests for the test_graphiti_connection async function.
Note: The function now uses embedded LadybugDB via patched KuzuDriver
instead of remote FalkorDB with host/port credentials.
instead of remote database with host/port credentials.
"""
@pytest.mark.asyncio
@@ -2,11 +2,6 @@
"project_root": "/Users/andremikalsen/Documents/Coding/autonomous-coding",
"project_type": "single",
"services": {},
"infrastructure": {
"docker_compose": "docker-compose.yml",
"docker_services": [
"falkordb"
]
},
"infrastructure": {},
"conventions": {}
}
+1 -1
View File
@@ -136,7 +136,7 @@ Examples:
python spec_runner.py --task "Update text" --complexity simple
# Complex integration (auto-detected)
python spec_runner.py --task "Add Graphiti memory integration with FalkorDB"
python spec_runner.py --task "Add Graphiti memory integration with LadybugDB"
# Interactive mode
python spec_runner.py --interactive