Files
OpenJarvis/tests/memory/test_fact_store.py
T
Elliot Slusky c3a7ffebff fix(memory): recall auto-captured facts across sessions (#740)
* fix(memory): recall auto-captured facts

* fix(memory): harden recalled context injection

* fix(memory): preserve mixed context history

* fix(agents): preserve caller system context
2026-08-13 17:07:10 -07:00

177 lines
4.9 KiB
Python

"""Tests for the persistent fact store (openjarvis.memory.store)."""
from __future__ import annotations
import json
import pytest
from openjarvis.core.registry import FactStoreRegistry
from openjarvis.memory.store import (
LocalFactStore,
create_fact_store,
load_configured_facts,
)
def test_add_and_list(tmp_path):
store = LocalFactStore(tmp_path / "facts.jsonl")
assert store.add("User prefers concise answers") is True
assert store.add("User lives in Berlin") is True
facts = store.list()
assert [f.text for f in facts] == [
"User prefers concise answers",
"User lives in Berlin",
]
assert store.count() == 2
def test_add_dedupes_case_insensitive(tmp_path):
store = LocalFactStore(tmp_path / "facts.jsonl")
assert store.add("Likes coffee") is True
assert store.add("likes coffee") is False # duplicate
assert store.count() == 1
def test_add_skips_empty(tmp_path):
store = LocalFactStore(tmp_path / "facts.jsonl")
assert store.add("") is False
assert store.add(" ") is False
assert store.count() == 0
def test_add_many(tmp_path):
store = LocalFactStore(tmp_path / "facts.jsonl")
added = store.add_many(["a", "b", "a", "c"]) # one dupe
assert added == 3
assert store.count() == 3
def test_max_facts_evicts_oldest(tmp_path):
store = LocalFactStore(tmp_path / "facts.jsonl", max_facts=2)
store.add("first")
store.add("second")
store.add("third")
facts = [f.text for f in store.list()]
assert facts == ["second", "third"] # oldest dropped
def test_persistence_across_instances(tmp_path):
path = tmp_path / "facts.jsonl"
store = LocalFactStore(path)
store.add("durable fact")
reloaded = LocalFactStore(path)
assert [f.text for f in reloaded.list()] == ["durable fact"]
def test_clear(tmp_path):
path = tmp_path / "facts.jsonl"
store = LocalFactStore(path)
store.add("one")
store.add("two")
removed = store.clear()
assert removed == 2
assert store.count() == 0
# A fresh instance also sees an empty store.
assert LocalFactStore(path).count() == 0
def test_external_clear_does_not_resurrect_stale_facts(tmp_path):
"""A running store instance must not re-flush facts cleared elsewhere."""
path = tmp_path / "facts.jsonl"
running = LocalFactStore(path)
cli = LocalFactStore(path)
running.add("old fact")
assert cli.clear() == 1
running.add("new fact")
assert [f.text for f in LocalFactStore(path).list()] == ["new fact"]
def test_load_skips_malformed_lines(tmp_path):
path = tmp_path / "facts.jsonl"
path.write_text(
'{"text": "good fact"}\n'
"this is not json\n"
'{"text": ""}\n' # empty text ignored
'{"text": "another good"}\n',
encoding="utf-8",
)
store = LocalFactStore(path)
assert [f.text for f in store.list()] == ["good fact", "another good"]
def test_jsonl_round_trip_is_valid_json(tmp_path):
path = tmp_path / "facts.jsonl"
store = LocalFactStore(path)
store.add("fact one", source="auto")
lines = [
line for line in path.read_text(encoding="utf-8").splitlines() if line.strip()
]
assert len(lines) == 1
obj = json.loads(lines[0])
assert obj["text"] == "fact one"
assert obj["source"] == "auto"
assert "created_at" in obj
def test_create_fact_store_local(tmp_path):
store = create_fact_store("local", path=tmp_path / "f.jsonl", max_facts=5)
assert isinstance(store, LocalFactStore)
def test_create_fact_store_uses_fact_store_registry(tmp_path):
class CustomFactStore(LocalFactStore):
pass
FactStoreRegistry.register_value("custom", CustomFactStore)
store = create_fact_store("custom", path=tmp_path / "f.jsonl", max_facts=5)
assert isinstance(store, CustomFactStore)
def test_create_fact_store_default_path_uses_openjarvis_home(tmp_path, monkeypatch):
monkeypatch.setenv("OPENJARVIS_HOME", str(tmp_path))
store = create_fact_store("local")
assert isinstance(store, LocalFactStore)
assert store.path == tmp_path / "memory_facts.jsonl"
def test_create_fact_store_unknown_backend(tmp_path):
with pytest.raises(ValueError):
create_fact_store("cloud", path=tmp_path / "f.jsonl")
def test_load_configured_facts_reads_enabled_store(tmp_path):
from types import SimpleNamespace
path = tmp_path / "facts.jsonl"
LocalFactStore(path).add("User likes jazz", source="auto")
config = SimpleNamespace(
memory=SimpleNamespace(
enabled=True,
backend="local",
facts_path=str(path),
max_facts=1000,
)
)
assert [fact.text for fact in load_configured_facts(config)] == ["User likes jazz"]
def test_load_configured_facts_skips_disabled_memory():
from types import SimpleNamespace
config = SimpleNamespace(memory=SimpleNamespace(enabled=False))
assert load_configured_facts(config) == []