import json def test_init_creates_db(tmp_pyra_home): from pyra.memory import database assert database._DB_PATH.exists() def test_upsert_and_list(tmp_pyra_home): from pyra.memory import database database.upsert( "user/profile.md", content="# Profile\n\nI am a developer.", category="user", size_bytes=30, modified="2026-05-18T10:00:00", summary="Developer profile", keywords=["developer", "profile"], ) rows = database.list_all() assert len(rows) == 1 row = rows[0] assert row["path"] == "user/profile.md" assert row["category"] == "user" assert row["summary"] == "Developer profile" assert row["keywords"] == ["developer", "profile"] def test_upsert_overwrites(tmp_pyra_home): from pyra.memory import database database.upsert("context/notes.md", content="old", category="context", modified="2026-05-18T10:00:00") database.upsert("context/notes.md", content="new", category="context", summary="updated", modified="2026-05-18T11:00:00") rows = database.list_all() assert len(rows) == 1 assert rows[0]["summary"] == "updated" def test_remove(tmp_pyra_home): from pyra.memory import database database.upsert("knowledge/facts.md", content="Some facts.", category="knowledge", modified="2026-05-18T10:00:00") assert len(database.list_all()) == 1 database.remove("knowledge/facts.md") assert len(database.list_all()) == 0 def test_search_fts(tmp_pyra_home): from pyra.memory import database database.upsert("user/profile.md", content="I enjoy building AI tools.", category="user", modified="2026-05-18T10:00:00", summary="Personal bio", keywords=["AI", "tools"]) database.upsert("knowledge/cooking.md", content="Pasta recipes and techniques.", category="knowledge", modified="2026-05-18T10:00:00", summary="Cooking notes", keywords=["pasta", "cooking"]) results = database.search("AI tools") assert len(results) == 1 assert results[0]["file"] == "user/profile.md" assert results[0]["summary"] == "Personal bio" assert "AI" in results[0]["keywords"] def test_search_no_match(tmp_pyra_home): from pyra.memory import database database.upsert("user/profile.md", content="Hello world.", category="user", modified="2026-05-18T10:00:00") results = database.search("xyzzy") assert results == [] def test_search_invalid_query_returns_empty(tmp_pyra_home): from pyra.memory import database database.upsert("user/profile.md", content="Hello world.", category="user", modified="2026-05-18T10:00:00") # FTS5 special chars that could raise OperationalError are handled gracefully results = database.search('"unclosed quote') assert isinstance(results, list) def test_migrate_from_files(tmp_pyra_home): from pyra.memory.writer import write_memory from pyra.memory import database write_memory("user/note.md", "Migration test content.") # Wipe DB to simulate fresh state before migration database.remove("user/note.md") assert database.list_all() == [] # Manually call migrate — it should re-populate from the .md file database.migrate_from_files() rows = database.list_all() assert any(r["path"] == "user/note.md" for r in rows) def test_list_memories_uses_db(tmp_pyra_home): from pyra.memory.writer import write_memory from pyra.memory.reader import list_memories write_memory("context/project.md", "# Project\n\nActive tasks.") memories = list_memories() names = [m.name for m in memories] assert "context/project.md" in names def test_lookup_memories_uses_fts(tmp_pyra_home): from pyra.memory.writer import write_memory from pyra.memory.reader import lookup_memories write_memory( "knowledge/python.md", "Python is a high-level programming language.", summary="Python overview", keywords=["python", "programming"], ) results = lookup_memories("programming language") assert len(results) >= 1 assert results[0]["file"] == "knowledge/python.md"