| import os |
| import json |
| from datetime import datetime |
| from typing import List, Dict, Optional |
| from utils.logger import setup_logger |
| from utils.encryption import encryption_manager |
|
|
| logger = setup_logger("memory_store") |
|
|
| class MemoryStore: |
| def __init__(self, sessions_dir: str = "memory/sessions"): |
| self.sessions_dir = sessions_dir |
| if not os.path.exists(self.sessions_dir): |
| os.makedirs(self.sessions_dir) |
| logger.info(f"Created sessions directory: {self.sessions_dir}") |
|
|
| def _get_session_path(self, session_id: str) -> str: |
| return os.path.join(self.sessions_dir, f"{session_id}.json") |
|
|
| def _get_log_path(self, session_id: str) -> str: |
| return os.path.join(self.sessions_dir, f"{session_id}.log.json") |
|
|
| def save_interaction(self, session_id: str, user_text: str, assistant_text: str): |
| """Saves a turn to a delta log to avoid full file rewrite.""" |
| log_path = self._get_log_path(session_id) |
| |
| |
| log_data = encryption_manager.safe_read(log_path) |
| if not log_data: |
| log_data = [] |
|
|
| |
| log_data.append({ |
| "user": user_text, |
| "assistant": assistant_text, |
| "timestamp": datetime.now().isoformat() |
| }) |
| |
| |
| try: |
| encryption_manager.safe_write(log_path, log_data) |
| |
| |
| if len(log_data) >= 50: |
| self.consolidate(session_id) |
| |
| logger.info(f"Interaction logged (delta) for session {session_id}") |
| except Exception as e: |
| logger.error(f"Error saving delta log for {session_id}: {e}") |
|
|
| def consolidate(self, session_id: str): |
| """Merges delta log into main session file.""" |
| main_path = self._get_session_path(session_id) |
| log_path = self._get_log_path(session_id) |
| |
| main_data = encryption_manager.safe_read(main_path) or {"session_id": session_id, "history": []} |
| log_data = encryption_manager.safe_read(log_path) or [] |
| |
| if not log_data: |
| return |
|
|
| logger.info(f"Consolidating memory for session {session_id}...") |
| main_data["history"].extend(log_data) |
| |
| |
| |
| try: |
| encryption_manager.safe_write(main_path, main_data) |
| |
| |
| full_log_path = log_path + ".enc" |
| if os.path.exists(full_log_path): |
| os.remove(full_log_path) |
| logger.info(f"Consolidation complete for {session_id}") |
| except Exception as e: |
| logger.error(f"Consolidation failed for {session_id}: {e}") |
|
|
| def get_recent_history(self, session_id: str, limit: int = 3) -> List[Dict[str, str]]: |
| """Retrieves history by merging main file and delta log.""" |
| main_path = self._get_session_path(session_id) |
| log_path = self._get_log_path(session_id) |
| |
| history = [] |
| try: |
| main_data = encryption_manager.safe_read(main_path) |
| if main_data: |
| history.extend(main_data.get("history", [])) |
| |
| log_data = encryption_manager.safe_read(log_path) |
| if log_data: |
| history.extend(log_data) |
| |
| return history[-limit:] |
| except Exception as e: |
| logger.error(f"Error reading history for {session_id}: {e}") |
| return [] |
|
|