Files
xiaoli-cli/plugins/memory_plugin.py
T
shuiyu1123 78fea7ccdd xiaoli-cli 7.0.0: 重构底层架构 + 移除工具截断
- 重构 core/ 底层 (7文件): app/runner/engine/parser/history/safety/display
- FC原生调用为主,prompt-JSON保底
- 移除所有工具返回截断 (ai_search/git_tools/cmd_executor/browser_auto/network_tools/sub_agent/tool_search)
- 删除无用文件 (旧服务器/WebUI/彩蛋/启动器等21个文件)
- 清理 constants.py 死代码
- 版本号更新为 7.0.0
2026-07-05 13:17:27 +08:00

254 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
记忆系统插件 — 包装 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 - 查看记忆上下文"""