"""Memory and Knowledge Management Tools""" import os import json import time from typing import Dict, List, Optional, Any from config import Config from utils import Logger class MemoryTools: """Persistent memory storage and retrieval""" def __init__(self, memory_file: str = None): self.memory_file = memory_file or Config.MEMORY_FILE self.logger = Logger() self._ensure_memory() def _ensure_memory(self): """Ensure memory file exists""" if not os.path.exists(self.memory_file): with open(self.memory_file, "w") as f: json.dump({ "facts": [], "conversations": [], "tasks": [], "preferences": {}, "created_at": time.time() }, f) def _load(self) -> Dict: """Load memory from disk""" try: with open(self.memory_file, "r") as f: return json.load(f) except: return {"facts": [], "conversations": [], "tasks": [], "preferences": {}} def _save(self, data: Dict): """Save memory to disk""" with open(self.memory_file, "w") as f: json.dump(data, f, indent=2, ensure_ascii=False) def memory_save(self, category: str, key: str, value: Any, tags: List[str] = None, ttl: int = 0) -> Dict: """Save information to memory""" try: memory = self._load() entry = { "key": key, "value": value, "tags": tags or [], "created": time.time(), "ttl": ttl, "accessed": 0 } if category == "fact": memory["facts"] = [f for f in memory["facts"] if f["key"] != key] memory["facts"].append(entry) elif category == "task": memory["tasks"].append(entry) elif category == "preference": memory["preferences"][key] = value elif category == "conversation": memory["conversations"].append({ **entry, "role": value.get("role", "unknown"), "content": value.get("content", "") }) self._save(memory) self.logger.log("memory_save", {"category": category, "key": key}) return { "success": True, "category": category, "key": key, "stored": True } except Exception as e: return {"success": False, "error": str(e)} def memory_search(self, query: str = "", category: str = "", tags: List[str] = None, limit: int = 10, time_range: str = "") -> Dict: """Search memory""" try: memory = self._load() results = [] cutoff = 0 if time_range == "today": cutoff = time.time() - 86400 elif time_range == "week": cutoff = time.time() - 604800 elif time_range == "month": cutoff = time.time() - 2592000 categories = [category] if category else ["facts", "tasks", "conversations"] for cat in categories: items = memory.get(cat, []) for item in items: if cutoff and item.get("created", 0) < cutoff: continue if tags and not any(t in item.get("tags", []) for t in tags): continue score = 0 if query: query_lower = query.lower() if query_lower in item.get("key", "").lower(): score += 10 if query_lower in str(item.get("value", "")).lower(): score += 5 for tag in item.get("tags", []): if query_lower in tag.lower(): score += 3 if not query or score > 0: results.append({ "category": cat, "score": score, **item }) if query: results.sort(key=lambda x: x["score"], reverse=True) else: results.sort(key=lambda x: x.get("created", 0), reverse=True) for r in results[:limit]: r["accessed"] = r.get("accessed", 0) + 1 self._save(memory) self.logger.log("memory_search", {"query": query, "results": len(results)}) return { "success": True, "query": query, "results": results[:limit], "total": len(results) } except Exception as e: return {"success": False, "error": str(e)} def memory_delete(self, key: str = "", category: str = "", older_than: int = 0, confirm: bool = True) -> Dict: """Delete memory entries""" try: if confirm and not key.startswith("_auto_"): from utils import UI if not UI.confirm(f"Delete memory entries matching '{key}'?"): return {"success": False, "error": "User cancelled"} memory = self._load() deleted = 0 if key: for cat in memory: if isinstance(memory[cat], list): original = len(memory[cat]) memory[cat] = [i for i in memory[cat] if i.get("key") != key] deleted += original - len(memory[cat]) if older_than: cutoff = time.time() - older_than for cat in memory: if isinstance(memory[cat], list): original = len(memory[cat]) memory[cat] = [i for i in memory[cat] if i.get("created", 0) > cutoff] deleted += original - len(memory[cat]) self._save(memory) return { "success": True, "deleted": deleted, "criteria": {"key": key, "category": category, "older_than": older_than} } except Exception as e: return {"success": False, "error": str(e)} def memory_stats(self) -> Dict: """Get memory statistics""" try: memory = self._load() return { "success": True, "facts": len(memory.get("facts", [])), "tasks": len(memory.get("tasks", [])), "conversations": len(memory.get("conversations", [])), "preferences": len(memory.get("preferences", {})), "file_size": os.path.getsize(self.memory_file) if os.path.exists(self.memory_file) else 0 } except Exception as e: return {"success": False, "error": str(e)}