mm1 / src /memory /store.py
TheRealHubertus's picture
Upload 49 files
82372e5 verified
Raw
History Blame Contribute Delete
2.93 kB
from __future__ import annotations
import json
from pathlib import Path
from src.schemas import MemoryFact, UserMemory, now_iso
class MemoryStore:
def __init__(self, base_dir: str | Path = "data") -> None:
self.base_dir = Path(base_dir)
self.path = self.base_dir / "memory.json"
self.events_path = self.base_dir / "memory_events.jsonl"
self.base_dir.mkdir(parents=True, exist_ok=True)
(self.base_dir / "runs").mkdir(exist_ok=True)
if not self.path.exists():
self.save(UserMemory())
if not self.events_path.exists():
self.events_path.write_text("", encoding="utf-8")
def load(self) -> UserMemory:
try:
return UserMemory.from_dict(json.loads(self.path.read_text(encoding="utf-8")))
except (json.JSONDecodeError, FileNotFoundError):
return UserMemory()
def save(self, memory: UserMemory) -> None:
self.path.write_text(json.dumps(memory.to_dict(), indent=2), encoding="utf-8")
def append_event(self, action: str, fact: MemoryFact) -> None:
event = {"ts": now_iso(), "action": action, "fact": fact.to_dict()}
with self.events_path.open("a", encoding="utf-8") as handle:
handle.write(json.dumps(event) + "\n")
def add_candidates(self, facts: list[MemoryFact], auto_accept: bool = False) -> list[MemoryFact]:
memory = self.load()
existing = {(fact.kind, fact.text.lower(), fact.status) for fact in memory.facts}
added: list[MemoryFact] = []
for fact in facts:
fact.status = "accepted" if auto_accept else "candidate"
key = (fact.kind, fact.text.lower(), fact.status)
if key in existing:
continue
memory.facts.append(fact)
self.append_event("add_candidate", fact)
added.append(fact)
self.save(memory)
return added
def update_status(self, fact_id: str, status: str) -> UserMemory:
memory = self.load()
for fact in memory.facts:
if fact.id == fact_id:
fact.status = status
fact.updated_at = now_iso()
self.append_event(f"status:{status}", fact)
break
self.save(memory)
return memory
def edit_fact(self, fact_id: str, text: str, kind: str | None = None) -> UserMemory:
memory = self.load()
for fact in memory.facts:
if fact.id == fact_id:
fact.text = text.strip()
if kind:
fact.kind = kind.strip()
fact.updated_at = now_iso()
self.append_event("edit", fact)
break
self.save(memory)
return memory
def import_json(self, raw_json: str) -> UserMemory:
memory = UserMemory.from_dict(json.loads(raw_json))
self.save(memory)
return memory