Coverage for memory / long_term.py: 22%
59 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-29 02:55 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-29 02:55 +0800
1"""
2中期记忆模块
4使用 Markdown 文件存储重要信息,Agent 可以主动写入和读取。
5特点:
6- 持久化存储在本地文件
7- Agent 可以主动管理记忆
8- 启动时自动加载并注入到 system prompt
9"""
11from pathlib import Path
12from datetime import datetime
13from qrclaw.logger import get_logger
15logger = get_logger("qrclaw.memory.long_term")
18class LongTermMemory:
19 """长期记忆管理器"""
21 def __init__(self, memory_file: Path):
22 """
23 初始化长期记忆。
25 Args:
26 memory_file: 记忆文件路径(由 Workspace 提供)
27 """
28 self.memory_file = memory_file
29 self._ensure_file()
30 logger.info(f"中期记忆初始化: {self.memory_file}")
32 def _ensure_file(self):
33 """确保记忆文件存在"""
34 self.memory_file.parent.mkdir(parents=True, exist_ok=True)
35 if not self.memory_file.exists():
36 self.memory_file.write_text("# QRClaw 中期记忆\n\n", encoding="utf-8")
37 logger.debug("创建中期记忆文件")
39 def load(self) -> str:
40 """
41 加载记忆内容
43 Returns:
44 str: 记忆内容(Markdown 格式)
45 """
46 try:
47 content = self.memory_file.read_text(encoding="utf-8")
48 logger.info(f"加载中期记忆: {len(content)} 字符")
49 return content
50 except Exception as e:
51 logger.error(f"加载中期记忆失败: {e}", exc_info=True)
52 return ""
54 def save(self, content: str) -> bool:
55 """
56 保存记忆内容(覆盖)
58 Args:
59 content: 要保存的内容
61 Returns:
62 bool: 是否成功
63 """
64 try:
65 self.memory_file.write_text(content, encoding="utf-8")
66 logger.info(f"保存中期记忆: {len(content)} 字符")
67 return True
68 except Exception as e:
69 logger.error(f"保存中期记忆失败: {e}", exc_info=True)
70 return False
72 def append(self, content: str, title: str = None) -> bool:
73 """
74 追加记忆内容
76 Args:
77 content: 要追加的内容
78 title: 可选的标题
80 Returns:
81 bool: 是否成功
82 """
83 try:
84 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
86 # 构建追加内容
87 append_text = f"\n---\n\n"
88 if title:
89 append_text += f"## {title}\n\n"
90 append_text += f"**时间**: {timestamp}\n\n"
91 append_text += f"{content}\n"
93 # 追加到文件
94 with open(self.memory_file, "a", encoding="utf-8") as f:
95 f.write(append_text)
97 logger.info(f"追加中期记忆: {title or '无标题'}, {len(content)} 字符")
98 return True
99 except Exception as e:
100 logger.error(f"追加中期记忆失败: {e}", exc_info=True)
101 return False
103 def clear(self) -> bool:
104 """
105 清空记忆(保留标题)
107 Returns:
108 bool: 是否成功
109 """
110 try:
111 self.memory_file.write_text("# QRClaw 中期记忆\n\n", encoding="utf-8")
112 logger.info("清空中期记忆")
113 return True
114 except Exception as e:
115 logger.error(f"清空中期记忆失败: {e}", exc_info=True)
116 return False
118 def exists(self) -> bool:
119 """检查记忆文件是否存在"""
120 return self.memory_file.exists()
122 def size(self) -> int:
123 """获取记忆文件大小(字符数)"""
124 if self.exists():
125 return len(self.load())
126 return 0