mealgraph / tests /test_memory.py
moazeldegwy's picture
Simplify topology to 3 agents + 2 tools
1933348
"""Tests for the SQLite-backed three-tier long-term memory."""
from __future__ import annotations
from memory import LongTermMemory
def test_round_trip_semantic_facts() -> None:
mem = LongTermMemory()
fid = mem.remember_fact("user1", "dislike", "okra", source="user_stated")
assert fid > 0
facts = mem.recall_facts("user1")
assert len(facts) == 1
assert facts[0]["content"] == "okra"
assert facts[0]["fact_type"] == "dislike"
def test_filter_facts_by_type_and_substring() -> None:
mem = LongTermMemory()
mem.remember_fact("u1", "dislike", "okra")
mem.remember_fact("u1", "dislike", "kale")
mem.remember_fact("u1", "preference", "high-protein")
mem.remember_fact("u2", "dislike", "okra") # different user
dislikes = mem.recall_facts("u1", fact_type="dislike")
assert {f["content"] for f in dislikes} == {"okra", "kale"}
prefs = mem.recall_facts("u1", fact_type="preference")
assert prefs[0]["content"] == "high-protein"
okra_only = mem.recall_facts("u1", contains="okra")
assert len(okra_only) == 1
def test_user_isolation() -> None:
mem = LongTermMemory()
mem.remember_fact("alice", "allergy", "peanut")
mem.remember_fact("bob", "allergy", "shellfish")
assert {f["content"] for f in mem.recall_facts("alice")} == {"peanut"}
assert {f["content"] for f in mem.recall_facts("bob")} == {"shellfish"}
def test_forget_fact() -> None:
mem = LongTermMemory()
fid = mem.remember_fact("u", "dislike", "okra")
mem.forget_fact(fid)
assert mem.recall_facts("u") == []
def test_procedural_records_round_trip() -> None:
mem = LongTermMemory()
issues = [{"code": "calorie_deviation", "description": "x", "severity": "medium"}]
mem.remember_validation("u1", "1500 kcal plan", "revise", issues)
history = mem.recall_validations("u1")
assert len(history) == 1
assert history[0]["verdict"] == "revise"
assert history[0]["issues"] == issues
def test_episodic_session_round_trip() -> None:
mem = LongTermMemory()
payload = {"messages": [{"role": "user", "content": "hi"}], "memory": {"x": 1}}
mem.remember_session("u1", "session-A", payload)
sessions = mem.recall_sessions("u1")
assert len(sessions) == 1
assert sessions[0]["payload"] == payload
assert sessions[0]["session_id"] == "session-A"
def test_recall_limit_and_order() -> None:
mem = LongTermMemory()
for i in range(15):
mem.remember_fact("u", "note", f"fact-{i}")
facts = mem.recall_facts("u", limit=5)
assert len(facts) == 5
# newest first
assert facts[0]["content"] == "fact-14"
# NOTE: The KnowledgeAgent tests previously here have been removed.
# KnowledgeAgent itself was removed; citation-first retrieval now happens
# inside :class:`tools.WebSearchTool`, which returns citations natively
# from Gemini's ``grounding_metadata``. Its coverage lives in the live
# Gemini audit rather than the offline test suite.