""" 记忆系统插件 — 包装 xcli_core/memory.py 中的 MemoryManager 使 AI 可以通过工具接口读写日记、搜索记忆、管理聊天记录、操作永久性记忆 """ import os import sys # 添加项目根目录到 path current_dir = os.path.dirname(os.path.abspath(__file__)) project_root = os.path.dirname(current_dir) sys.path.insert(0, project_root) from xcli_core.memory import MemoryManager class Liugin: """持久化记忆系统 — AI 可读写永久记忆、日记、搜索历史对话""" def __init__(self): self.cli = None self.memory = None self.usage = """持久化记忆系统工具 操作: diary <内容> - 写当日日记 diary_ai <内容> - AI 写观察日记(标记为 AI 观察) remember <内容> - 记录到长期记忆 (MEMORY.md 备忘 section) search <关键词> - 全局搜索(日记+记忆+聊天记录) context - 查看当前注入的记忆上下文 diary_list - 列出所有日记文件 diary_read <日期> - 读取指定日期的日记(如 2026-04-27) 永久性记忆 (MEMORY.md) 操作: memory_read - 读取整个 MEMORY.md memory_write <内容> - 追加到 MEMORY.md 备忘 section memory_sections - 列出所有记忆分类(section) memory_read_section <名称> - 读取指定 section 的内容 memory_write_section <名称> <内容> - 写入/覆盖指定 section(不存在则新建) memory_delete_section <名称> - 删除指定 section 聊天记录: chat_list - 列出最近的聊天记录 chat_search <关键词> - 在聊天记录中搜索 JSON 格式示例: {"action": "use_tool", "tool": "memory_plugin", "args": "remember 用户偏好深色主题"} {"action": "use_tool", "tool": "memory_plugin", "args": "memory_write_section 用户偏好 - 喜欢简洁的代码风格\n- 使用 Python 3.10+"} {"action": "use_tool", "tool": "memory_plugin", "args": "memory_read_section 用户偏好"} {"action": "use_tool", "tool": "memory_plugin", "args": "search 定时任务"} """ def set_cli(self, cli): self.cli = cli project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) self.memory = MemoryManager(project_dir) cli.memory_manager = self.memory def get_tool_info(self): return { "name": "memory_plugin", "description": "持久化记忆系统 — AI 可读写永久记忆(MEMORY.md)、写日记、搜索历史对话。支持按 section 分类存储和修改记忆。", "keywords": ["记忆", "memory", "日记", "diary", "搜索", "search", "历史", "history", "remember", "聊天记录", "chat", "上下文", "context", "压缩", "compress", "永久", "persistent", "存储", "store", "读取", "read", "修改", "modify"], "usage": self.usage } def handle(self, args: str) -> str: if not self.memory: return "错误:记忆系统未初始化" if not args or not args.strip(): return self._help() parts = args.strip().split(None, 1) action = parts[0].lower() rest = parts[1].strip() if len(parts) > 1 else "" handlers = { "diary": self._diary, "diary_ai": self._diary_ai, "remember": self._remember, "search": self._search, "context": self._context, "diary_list": self._diary_list, "diary_read": self._diary_read, "chat_list": self._chat_list, "chat_search": self._chat_search, "memory_read": self._memory_read, "memory_write": self._memory_write, "memory_sections": self._memory_sections, "memory_read_section": self._memory_read_section, "memory_write_section": self._memory_write_section, "memory_delete_section": self._memory_delete_section, "help": lambda _: self._help(), } handler = handlers.get(action) if not handler: return f"未知操作: {action}\n" + self._help() return handler(rest) # ── 日记 ── def _diary(self, content: str) -> str: if not content: return "错误:请提供日记内容\n用法: diary <内容>" self.memory.write_diary(content) return f"日记已写入 {self.memory._today_file()}" def _diary_ai(self, content: str) -> str: if not content: return "错误:请提供 AI 观察内容\n用法: diary_ai <内容>" self.memory.write_ai_diary(content) return "AI 观察日记已写入" def _diary_list(self, _: str) -> str: files = self.memory.list_diary_files() if not files: return "还没有日记文件" return "日记文件:\n" + "\n".join(f" {f}" for f in files[:20]) def _diary_read(self, date_str: str) -> str: if not date_str: return "错误:请提供日期\n用法: diary_read <日期,如 2026-04-27>" content = self.memory.load_diary(date_str) return content if content else f"没有找到 {date_str} 的日记" # ── 永久性记忆 (MEMORY.md) ── def _remember(self, content: str) -> str: """快速记录到备忘 section""" if not content: return "错误:请提供要记住的内容\n用法: remember <内容>" self.memory.append_memory("备忘", f"- {content}") return "已记录到 MEMORY.md 长期记忆 (备忘 section)" def _memory_read(self, _: str) -> str: content = self.memory.load_memory() return content if content else "MEMORY.md 为空" def _memory_write(self, content: str) -> str: """追加到备忘 section""" if not content: return "错误:请提供内容\n用法: memory_write <内容>" self.memory.append_memory("备忘", f"- {content}") return "已追加到 MEMORY.md (备忘 section)" def _memory_sections(self, _: str) -> str: """列出所有 section""" sections = self.memory.list_memory_sections() if not sections: return "MEMORY.md 为空,没有任何 section" return "MEMORY.md 中的 section:\n" + "\n".join(f" {i+1}. {s}" for i, s in enumerate(sections)) def _memory_read_section(self, section: str) -> str: """读取指定 section""" if not section: return "错误:请提供 section 名称\n用法: memory_read_section <名称>" content = self.memory.read_memory_section(section) if not content: return f"section '{section}' 不存在或为空" return f"## {section}\n{content}" def _memory_write_section(self, args: str) -> str: """写入/覆盖指定 section""" if not args: return "错误:请提供 section 名称和内容\n用法: memory_write_section <名称> <内容>" parts = args.split(None, 1) section = parts[0] content = parts[1] if len(parts) > 1 else "" if not content: return "错误:请提供内容\n用法: memory_write_section <名称> <内容>" self.memory.write_memory_section(section, content) return f"已写入 MEMORY.md section '{section}'" def _memory_delete_section(self, section: str) -> str: """删除指定 section""" if not section: return "错误:请提供 section 名称\n用法: memory_delete_section <名称>" if self.memory.delete_memory_section(section): return f"已删除 MEMORY.md section '{section}'" return f"section '{section}' 不存在" # ── 搜索 ── def _search(self, keyword: str) -> str: if not keyword: return "错误:请提供搜索关键词\n用法: search <关键词>" results = self.memory.search_memory(keyword) if not results: return f"未找到与 '{keyword}' 相关的记忆" lines = [f"搜索 '{keyword}' 的结果 ({len(results)} 条):"] for r in results: source = r.get("source", "") snippet = r.get("snippet", "") role = r.get("role", "") line_num = r.get("line", "") prefix = f"[{role}] " if role else "" line_info = f" (L{line_num})" if line_num else "" lines.append(f" {source}{line_info}: {prefix}{snippet}") return "\n".join(lines) def _context(self, _: str) -> str: ctx = self.memory.build_memory_context() return ctx if ctx else "当前没有记忆上下文" # ── 聊天记录 ── def _chat_list(self, _: str) -> str: chats = self.memory.list_chats() if not chats: return "没有保存的聊天记录" lines = ["最近的聊天记录:"] for c in chats: lines.append(f" {c['name']} ({c['time']}, {c['size_kb']}KB)") return "\n".join(lines) def _chat_search(self, keyword: str) -> str: if not keyword: return "错误:请提供关键词\n用法: chat_search <关键词>" results = self.memory.search_chats(keyword) if not results: return f"未在聊天记录中找到 '{keyword}'" lines = [f"聊天记录搜索 '{keyword}':"] for r in results: name = r.get("name", r.get("file", "")) lines.append(f" {name} [{r.get('role', '')}]: {r.get('snippet', '')}") return "\n".join(lines) def _help(self) -> str: return """记忆系统用法: 日记: diary <内容> - 写当日日记 diary_ai <内容> - AI 写观察日记 diary_list - 列出日记 diary_read <日期> - 读取日记 永久性记忆 (MEMORY.md): remember <内容> - 快速记到备忘 memory_read - 读取整个 MEMORY.md memory_write <内容> - 追加到备忘 memory_sections - 列出所有 section memory_read_section <名称> - 读取指定 section memory_write_section <名称> <内容> - 写入/覆盖 section memory_delete_section <名称> - 删除 section 搜索: search <关键词> - 全局搜索 chat_search <关键词> - 搜索聊天记录 context - 查看记忆上下文"""