Spaces:
Sleeping
Sleeping
| """Per-user (client/localStorage) memory: pure helpers, parsers, UI handlers, | |
| and per-request injection into the agent prompt. Stub mode; no network.""" | |
| import os | |
| from datetime import datetime | |
| os.environ.setdefault("USE_STUB_EXTRACTOR", "1") | |
| from server import agent, memory # noqa: E402 | |
| from server.schema import ActionPlan, Event # noqa: E402 | |
| from ui import blocks # noqa: E402 | |
| # --- pure helpers ----------------------------------------------------------- | |
| def test_facts_to_recall_and_merge(): | |
| facts = memory.merge_facts([], [("Dana is the coach", "contact"), "you decline Mondays"]) | |
| assert len(facts) == 2 | |
| # dedup + weight bump | |
| facts = memory.merge_facts(facts, ["Dana is the coach"]) | |
| dana = [f for f in facts if "Dana" in f["text"]][0] | |
| assert dana["weight"] == 2 | |
| block = memory.facts_to_recall(facts) | |
| assert "What I know about you" in block and "Dana is the coach" in block | |
| assert memory.facts_to_recall([]) == "" | |
| def test_learn_from_plan_returns_contacts(): | |
| plan = ActionPlan(reasoning="x", events=[Event(title="Game", start="2026-06-12T10:00", attendees=["Coach Dana"])]) | |
| learned = memory.learn_from_plan(plan) | |
| assert any("Coach Dana" in t for t in learned) | |
| # --- per-request injection (the whole point) -------------------------------- | |
| def test_build_messages_uses_passed_memory(): | |
| msgs = agent.build_messages("hi", datetime(2026, 6, 12, 9, 0), [], None, | |
| memory_block="What I know about you (memory):\n- Dana is the coach") | |
| blob = str(msgs) | |
| assert "Dana is the coach" in blob | |
| # --- UI client handlers ----------------------------------------------------- | |
| def test_mem_remember_and_forget_roundtrip(): | |
| mem, status = blocks._mem_remember("you decline Mondays", "preference", "[]") | |
| facts = blocks._facts_load(mem) | |
| assert facts and facts[0]["text"] == "you decline Mondays" | |
| fid = facts[0]["id"] | |
| mem2, status2 = blocks._mem_forget(fid, mem) | |
| assert blocks._facts_load(mem2) == [] | |
| assert "Forgotten" in status2 | |
| def test_onboard_writes_facts(): | |
| mem, vis, msg = blocks._on_onboard("Dana = soccer coach\nMr. Lee = teacher", 30, "Mondays", "[]") | |
| texts = [f["text"] for f in blocks._facts_load(mem)] | |
| assert any("Dana is the soccer coach" in t for t in texts) | |
| assert any("teacher" in t for t in texts) | |
| assert any("30 minutes" in t for t in texts) | |
| assert any("Mondays" in t for t in texts) | |
| # --- file import parsers ---------------------------------------------------- | |
| def test_parse_vcf_csv_ics(tmp_path): | |
| vcf = tmp_path / "c.vcf" | |
| vcf.write_text("BEGIN:VCARD\nFN:Coach Dana\nEND:VCARD\nBEGIN:VCARD\nFN:Mr. Lee\nEND:VCARD\n") | |
| names, _ = blocks._parse_memory_file(str(vcf)) | |
| assert "Coach Dana" in names and "Mr. Lee" in names | |
| csv = tmp_path / "c.csv" | |
| csv.write_text("name,phone\nAlex Kim,123\nJamie Fox,456\n") | |
| names, _ = blocks._parse_memory_file(str(csv)) | |
| assert "Alex Kim" in names and "Jamie Fox" in names | |
| ics = tmp_path / "cal.ics" | |
| ics.write_text("BEGIN:VEVENT\nSUMMARY:Soccer practice\nATTENDEE;CN=Coach Dana:mailto:d@x.com\nEND:VEVENT\n") | |
| names, prefs = blocks._parse_memory_file(str(ics)) | |
| assert "Coach Dana" in names | |
| assert any("Soccer practice" in p[0] for p in prefs) | |
| def test_import_file_merges_into_memory(tmp_path): | |
| vcf = tmp_path / "c.vcf" | |
| vcf.write_text("BEGIN:VCARD\nFN:Coach Dana\nEND:VCARD\n") | |
| mem, status = blocks._import_file(str(vcf), "[]") | |
| assert any("Coach Dana" in f["text"] for f in blocks._facts_load(mem)) | |
| assert "Imported" in status | |
| def test_import_gcal_unchecked_is_graceful(): | |
| mem, status = blocks._import_gcal(False, "[]") | |
| assert "Tick the box" in status | |