From 8a69d4354e5744ff88237ac28b51087318cec378 Mon Sep 17 00:00:00 2001 From: saboteur7 Date: Fri, 30 Jan 2026 19:10:37 +0800 Subject: [PATCH] feat: Optimize the first dialogue and memory --- agent/memory/manager.py | 18 +- agent/memory/summarizer.py | 11 +- agent/prompt/builder.py | 392 ++++++++-------------------- agent/prompt/workspace.py | 66 ++--- agent/tools/memory/memory_get.py | 2 +- agent/tools/memory/memory_search.py | 2 +- 6 files changed, 156 insertions(+), 335 deletions(-) diff --git a/agent/memory/manager.py b/agent/memory/manager.py index 884f163..7f0b983 100644 --- a/agent/memory/manager.py +++ b/agent/memory/manager.py @@ -248,8 +248,8 @@ class MemoryManager: memory_dir = self.config.get_memory_dir() workspace_dir = self.config.get_workspace() - # Scan memory/MEMORY.md - memory_file = memory_dir / "MEMORY.md" + # Scan MEMORY.md (workspace root) + memory_file = Path(workspace_dir) / "MEMORY.md" if memory_file.exists(): await self._sync_file(memory_file, "memory", "shared", None) @@ -452,7 +452,7 @@ class MemoryManager: **背景知识**: 下方包含核心长期记忆,可直接使用。需要查找历史时,用 memory_search 搜索(搜索一次即可,不要重复)。 **存储记忆**: 当用户分享重要信息时(偏好、决策、事实等),主动用 write 工具存储: -- 长期信息 → memory/MEMORY.md +- 长期信息 → MEMORY.md - 当天笔记 → memory/{today_file} - 静默存储,仅在明确要求时确认 @@ -463,7 +463,7 @@ class MemoryManager: **Background Knowledge**: Core long-term memories below - use directly. For history, use memory_search once (don't repeat). **Store Memories**: When user shares important info (preferences, decisions, facts), proactively write: -- Durable info → memory/MEMORY.md +- Durable info → MEMORY.md - Daily notes → memory/{today_file} - Store silently; confirm only when explicitly requested @@ -482,8 +482,8 @@ class MemoryManager: Load bootstrap memory files for session start Following clawdbot's design: - - Only loads memory/MEMORY.md (long-term curated memory) - - Daily files (YYYY-MM-DD.md) are accessed via memory_search tool, not bootstrap + - Only loads MEMORY.md from workspace root (long-term curated memory) + - Daily files (memory/YYYY-MM-DD.md) are accessed via memory_search tool, not bootstrap - User-specific MEMORY.md is also loaded if user_id provided Returns memory content WITHOUT obvious headers so it blends naturally @@ -500,16 +500,16 @@ class MemoryManager: sections = [] - # 1. Load memory/MEMORY.md ONLY (long-term curated memory) + # 1. Load MEMORY.md from workspace root (long-term curated memory) # Following clawdbot: only MEMORY.md is bootstrap, daily files use memory_search - memory_file = memory_dir / "MEMORY.md" + memory_file = Path(workspace_dir) / "MEMORY.md" if memory_file.exists(): try: content = memory_file.read_text(encoding='utf-8').strip() if content: sections.append(content) except Exception as e: - print(f"Warning: Failed to read memory/MEMORY.md: {e}") + print(f"Warning: Failed to read MEMORY.md: {e}") # 2. Load user-specific MEMORY.md if user_id provided if user_id: diff --git a/agent/memory/summarizer.py b/agent/memory/summarizer.py index ca1ac30..020164e 100644 --- a/agent/memory/summarizer.py +++ b/agent/memory/summarizer.py @@ -17,7 +17,7 @@ class MemoryFlushManager: - Triggers when context approaches token limit - Runs a silent agent turn to write memories to disk - Uses memory/YYYY-MM-DD.md for daily notes - - Uses MEMORY.md for long-term curated memories + - Uses MEMORY.md (workspace root) for long-term curated memories """ def __init__( @@ -103,7 +103,7 @@ class MemoryFlushManager: def get_main_memory_file(self, user_id: Optional[str] = None) -> Path: """ - Get main memory file path: memory/MEMORY.md + Get main memory file path: MEMORY.md (workspace root) Args: user_id: Optional user ID for user-specific memory @@ -116,7 +116,8 @@ class MemoryFlushManager: user_dir.mkdir(parents=True, exist_ok=True) return user_dir / "MEMORY.md" else: - return self.memory_dir / "MEMORY.md" + # Return workspace root MEMORY.md + return Path(self.workspace_root) / "MEMORY.md" def create_flush_prompt(self) -> str: """ @@ -207,13 +208,13 @@ def create_memory_files_if_needed(workspace_dir: Path, user_id: Optional[str] = memory_dir = workspace_dir / "memory" memory_dir.mkdir(parents=True, exist_ok=True) - # Create main MEMORY.md in memory directory + # Create main MEMORY.md in workspace root if user_id: user_dir = memory_dir / "users" / user_id user_dir.mkdir(parents=True, exist_ok=True) main_memory = user_dir / "MEMORY.md" else: - main_memory = memory_dir / "MEMORY.md" + main_memory = Path(workspace_root) / "MEMORY.md" if not main_memory.exists(): # Create empty file or with minimal structure (no obvious "Memory" header) diff --git a/agent/prompt/builder.py b/agent/prompt/builder.py index 4e93feb..369f626 100644 --- a/agent/prompt/builder.py +++ b/agent/prompt/builder.py @@ -156,24 +156,14 @@ def _build_identity_section(base_persona: Optional[str], language: str) -> List[ def _build_tooling_section(tools: List[Any], language: str) -> List[str]: """构建工具说明section""" - if language == "zh": - lines = [ - "## 工具系统", - "", - "你可以使用以下工具来完成任务。工具名称是大小写敏感的,请严格按照列表中的名称调用。", - "", - "### 可用工具", - "", - ] - else: - lines = [ - "## Tooling", - "", - "You have access to the following tools. Tool names are case-sensitive.", - "", - "### Available Tools", - "", - ] + lines = [ + "## 工具系统", + "", + "你可以使用以下工具来完成任务。工具名称是大小写敏感的,请严格按照列表中的名称调用。", + "", + "### 可用工具", + "", + ] # 工具分类和排序 tool_categories = { @@ -213,10 +203,7 @@ def _build_tooling_section(tools: List[Any], language: str) -> List[str]: for category, tool_names in tool_categories.items(): category_tools = [(name, tool_map.get(name, "")) for name in tool_names if name in tool_map] if category_tools: - if language == "zh": - lines.append(f"**{category}**:") - else: - lines.append(f"**{category}**:") + lines.append(f"**{category}**:") for name, desc in category_tools: if desc: lines.append(f"- `{name}`: {desc}") @@ -227,10 +214,7 @@ def _build_tooling_section(tools: List[Any], language: str) -> List[str]: # 添加其他未分类的工具 if tool_map: - if language == "zh": - lines.append("**其他工具**:") - else: - lines.append("**Other Tools**:") + lines.append("**其他工具**:") for name, desc in sorted(tool_map.items()): if desc: lines.append(f"- `{name}`: {desc}") @@ -239,34 +223,19 @@ def _build_tooling_section(tools: List[Any], language: str) -> List[str]: lines.append("") # 工具使用指南 - if language == "zh": - lines.extend([ - "### 工具调用风格", - "", - "**默认规则**: 对于常规、低风险的工具调用,无需叙述,直接调用即可。", - "", - "**需要叙述的情况**:", - "- 多步骤、复杂的任务", - "- 敏感操作(如删除文件)", - "- 用户明确要求解释过程", - "", - "**叙述要求**: 保持简洁、有价值,避免重复显而易见的步骤。使用自然的人类语言。", - "", - ]) - else: - lines.extend([ - "### Tool Call Style", - "", - "**Default**: Do not narrate routine, low-risk tool calls (just call the tool).", - "", - "**Narrate when**:", - "- Multi-step, complex work", - "- Sensitive actions (e.g., deletions)", - "- User explicitly asks", - "", - "**Keep narration brief and value-dense**. Use plain human language.", - "", - ]) + lines.extend([ + "### 工具调用风格", + "", + "**默认规则**: 对于常规、低风险的工具调用,无需叙述,直接调用即可。", + "", + "**需要叙述的情况**:", + "- 多步骤、复杂的任务", + "- 敏感操作(如删除文件)", + "- 用户明确要求解释过程", + "", + "**完成后**: 工具调用完成后,给用户一个简短、自然的确认或回复,不要直接结束对话。", + "", + ]) return lines @@ -285,32 +254,18 @@ def _build_skills_section(skill_manager: Any, tools: Optional[List[Any]], langua read_tool_name = tool_name break - if language == "zh": - lines = [ - "## 技能系统", - "", - "在回复之前:扫描下方 中的 条目。", - "", - f"- 如果恰好有一个技能明确适用:使用 `{read_tool_name}` 工具读取其 路径下的 SKILL.md 文件,然后遵循它。", - "- 如果多个技能都适用:选择最具体的一个,然后读取并遵循。", - "- 如果没有明确适用的:不要读取任何 SKILL.md。", - "", - "**约束**: 永远不要一次性读取多个技能;只在选择后再读取。", - "", - ] - else: - lines = [ - "## Skills", - "", - "Before replying: scan entries.", - "", - f"- If exactly one skill clearly applies: read its SKILL.md at with `{read_tool_name}`, then follow it.", - "- If multiple could apply: choose the most specific one, then read/follow it.", - "- If none clearly apply: do not read any SKILL.md.", - "", - "**Constraints**: never read more than one skill up front; only read after selecting.", - "", - ] + lines = [ + "## 技能系统", + "", + "在回复之前:扫描下方 中的 条目。", + "", + f"- 如果恰好有一个技能明确适用:使用 `{read_tool_name}` 工具读取其 路径下的 SKILL.md 文件,然后遵循它。", + "- 如果多个技能都适用:选择最具体的一个,然后读取并遵循。", + "- 如果没有明确适用的:不要读取任何 SKILL.md。", + "", + "**约束**: 永远不要一次性读取多个技能;只在选择后再读取。", + "", + ] # 添加技能列表(通过skill_manager获取) try: @@ -338,56 +293,24 @@ def _build_memory_section(memory_manager: Any, tools: Optional[List[Any]], langu if not has_memory_tools: return [] - if language == "zh": - lines = [ - "## 记忆系统", - "", - "在回答关于以前的工作、决定、日期、人物、偏好或待办事项的任何问题之前:", - "", - "1. 使用 `memory_search` 在 MEMORY.md 和 memory/*.md 中搜索", - "2. 然后使用 `memory_get` 只拉取需要的行", - "3. 如果搜索后仍然信心不足,告诉用户你已经检查过了", - "", - "**记忆文件结构**:", - "- `memory/MEMORY.md`: 长期记忆,包含重要的背景信息", - "- `memory/YYYY-MM-DD.md`: 每日记忆,记录当天的对话和事件", - "", - "**存储记忆**:", - "- 当用户分享重要信息时(偏好、爱好、决策、事实等),**主动用 write 工具存储**", - "- 长期信息 → memory/MEMORY.md", - "- 当天笔记 → memory/YYYY-MM-DD.md", - "- 静默存储,仅在明确要求时确认", - "", - "**使用原则**:", - "- 自然使用记忆,就像你本来就知道", - "- 不要主动提起或列举记忆,除非用户明确询问", - "", - ] - else: - lines = [ - "## Memory System", - "", - "Before answering anything about prior work, decisions, dates, people, preferences, or todos:", - "", - "1. Run `memory_search` on MEMORY.md + memory/*.md", - "2. Then use `memory_get` to pull only the needed lines", - "3. If low confidence after search, say you checked", - "", - "**Memory File Structure**:", - "- `memory/MEMORY.md`: Long-term memory with important context", - "- `memory/YYYY-MM-DD.md`: Daily memories for each day", - "", - "**Store Memories**:", - "- When user shares important info (preferences, hobbies, decisions, facts), **proactively write**", - "- Durable info → memory/MEMORY.md", - "- Daily notes → memory/YYYY-MM-DD.md", - "- Store silently; confirm only when explicitly requested", - "", - "**Usage Principles**:", - "- Use memories naturally as if you always knew", - "- Don't mention or list unless user explicitly asks", - "", - ] + lines = [ + "## 记忆系统", + "", + "在回答关于以前的工作、决定、日期、人物、偏好或待办事项的任何问题之前:", + "", + "1. 使用 `memory_search` 在 MEMORY.md 和 memory/*.md 中搜索", + "2. 然后使用 `memory_get` 只拉取需要的行", + "3. 如果搜索后仍然信心不足,告诉用户你已经检查过了", + "", + "**记忆文件结构**:", + "- `MEMORY.md`: 长期记忆,包含重要的背景信息", + "- `memory/YYYY-MM-DD.md`: 每日记忆,记录当天的对话和事件", + "", + "**使用原则**:", + "- 自然使用记忆,就像你本来就知道", + "- 不要主动提起或列举记忆,除非用户明确询问", + "", + ] return lines @@ -397,38 +320,21 @@ def _build_user_identity_section(user_identity: Dict[str, str], language: str) - if not user_identity: return [] - if language == "zh": - lines = [ - "## 用户身份", - "", - ] - - if user_identity.get("name"): - lines.append(f"**用户姓名**: {user_identity['name']}") - if user_identity.get("nickname"): - lines.append(f"**称呼**: {user_identity['nickname']}") - if user_identity.get("timezone"): - lines.append(f"**时区**: {user_identity['timezone']}") - if user_identity.get("notes"): - lines.append(f"**备注**: {user_identity['notes']}") - - lines.append("") - else: - lines = [ - "## User Identity", - "", - ] - - if user_identity.get("name"): - lines.append(f"**Name**: {user_identity['name']}") - if user_identity.get("nickname"): - lines.append(f"**Call them**: {user_identity['nickname']}") - if user_identity.get("timezone"): - lines.append(f"**Timezone**: {user_identity['timezone']}") - if user_identity.get("notes"): - lines.append(f"**Notes**: {user_identity['notes']}") - - lines.append("") + lines = [ + "## 用户身份", + "", + ] + + if user_identity.get("name"): + lines.append(f"**用户姓名**: {user_identity['name']}") + if user_identity.get("nickname"): + lines.append(f"**称呼**: {user_identity['nickname']}") + if user_identity.get("timezone"): + lines.append(f"**时区**: {user_identity['timezone']}") + if user_identity.get("notes"): + lines.append(f"**备注**: {user_identity['notes']}") + + lines.append("") return lines @@ -441,82 +347,34 @@ def _build_docs_section(workspace_dir: str, language: str) -> List[str]: def _build_workspace_section(workspace_dir: str, language: str) -> List[str]: """构建工作空间section""" - if language == "zh": - lines = [ - "## 工作空间", - "", - f"你的工作目录是: `{workspace_dir}`", - "", - "除非用户明确指示,否则将此目录视为文件操作的全局工作空间。", - "", - "**重要说明 - 文件已自动加载**:", - "", - "以下文件在会话启动时**已经自动加载**到系统提示词的「项目上下文」section 中,你**无需再用 read 工具读取它们**:", - "", - "- ✅ `SOUL.md`: 已加载 - Agent的人格设定", - "- ✅ `USER.md`: 已加载 - 用户的身份信息", - "- ✅ `AGENTS.md`: 已加载 - 工作空间使用指南" - "", - "**首次对话**:", - "", - "如果这是你与用户的首次对话,并且你的人格设定和用户信息还是空白或初始状态,你应该:", - "", - "1. **以自然、友好的方式**打招呼并表达想要了解用户的意愿", - "2. 询问用户关于他们自己的信息(姓名、职业、偏好、时区等)", - "3. 询问用户希望你成为什么样的助理(性格、风格、称呼、专长等)", - "4. 使用 `write` 工具将信息保存到相应文件(USER.md 和 SOUL.md)", - "5. 之后可以随时使用 `edit` 工具更新这些配置", - "", - "**重要**: 在询问时保持自然对话风格,**不要提及文件名**(如 SOUL.md、USER.md 等技术细节),除非用户主动询问系统实现。用自然的表达如「了解你的信息」「设定我的性格」等。", - "", - "**记忆管理**:", - "", - "- 当用户说「记住这个」时,判断应该写入哪个文件:", - " - 关于你自己的配置 → SOUL.md", - " - 关于用户的信息 → USER.md", - " - 重要的背景信息 → memory/MEMORY.md", - " - 日常对话记录 → memory/YYYY-MM-DD.md", - "", - ] - else: - lines = [ - "## Workspace", - "", - f"Your working directory is: `{workspace_dir}`", - "", - "Treat this directory as the single global workspace for file operations unless explicitly instructed otherwise.", - "", - "**Workspace Files (Auto-loaded)**:", - "", - "The following user-editable files are automatically loaded and included in the Project Context below:", - "", - "- `SOUL.md`: Agent persona (your personality, style, and principles)", - "- `USER.md`: User identity (name, preferences, important dates)", - "- `AGENTS.md`: Workspace guidelines (your rules and workflows)", - "- `TOOLS.md`: Custom tool usage notes (configurations and tips)", - "- `MEMORY.md`: Long-term memory (important context and decisions)", - "", - "**First Conversation**:", - "", - "If this is your first conversation with the user, and your persona and user information are empty or contain placeholders, you should:", - "", - "1. **Greet naturally and warmly**, expressing your interest in learning about them", - "2. Ask about the user (name, job, preferences, timezone, etc.)", - "3. Ask what kind of assistant they want you to be (personality, style, name, expertise)", - "4. Use `write` tool to save the information to appropriate files (USER.md and SOUL.md)", - "5. Later, use `edit` tool to update these configurations as needed", - "", - "**Important**: Keep the conversation natural. **Do NOT mention file names** (like SOUL.md, USER.md, etc.) unless the user specifically asks about implementation details. Use natural expressions like \"learn about you\", \"configure my personality\", etc.", - "", - "**Memory Management**:", - "", - "- When user says 'remember this', decide which file to write to:", - " - About your configuration → SOUL.md", - " - About the user → USER.md", - " - Important context → memory/MEMORY.md", - " - Daily chat logs → memory/YYYY-MM-DD.md", - "", - ] + lines = [ + "## 工作空间", + "", + f"你的工作目录是: `{workspace_dir}`", + "", + "除非用户明确指示,否则将此目录视为文件操作的全局工作空间。", + "", + "**重要说明 - 文件已自动加载**:", + "", + "以下文件在会话启动时**已经自动加载**到系统提示词的「项目上下文」section 中,你**无需再用 read 工具读取它们**:", + "", + "- ✅ `SOUL.md`: 已加载 - Agent的人格设定", + "- ✅ `USER.md`: 已加载 - 用户的身份信息", + "- ✅ `AGENTS.md`: 已加载 - 工作空间使用指南", + "", + "**首次对话**:", + "", + "如果这是你与用户的首次对话,并且你的人格设定和用户信息还是空白或初始状态,你应该:", + "", + "1. **以自然、友好的方式**打招呼并表达想要了解用户的意愿", + "2. 询问用户关于他们自己的信息(姓名、职业、偏好、时区等)", + "3. 询问用户希望你成为什么样的助理(性格、风格、称呼、专长等)", + "4. 使用 `write` 工具将信息保存到相应文件(USER.md 和 SOUL.md)", + "5. 之后可以随时使用 `edit` 工具更新这些配置", + "", + "**重要**: 在询问时保持自然对话风格,**不要提及文件名**(如 SOUL.md、USER.md 等技术细节),除非用户主动询问系统实现。用自然的表达如「了解你的信息」「设定我的性格」等。", + "", + ] return lines @@ -532,28 +390,16 @@ def _build_context_files_section(context_files: List[ContextFile], language: str for f in context_files ) - if language == "zh": - lines = [ - "# 项目上下文", - "", - "以下项目上下文文件已被加载:", - "", - ] - - if has_soul: - lines.append("如果存在 `SOUL.md`,请体现其中定义的人格和语气。避免僵硬、模板化的回复;遵循其指导,除非有更高优先级的指令覆盖它。") - lines.append("") - else: - lines = [ - "# Project Context", - "", - "The following project context files have been loaded:", - "", - ] - - if has_soul: - lines.append("If `SOUL.md` is present, embody its persona and tone. Avoid stiff, generic replies; follow its guidance unless higher-priority instructions override it.") - lines.append("") + lines = [ + "# 项目上下文", + "", + "以下项目上下文文件已被加载:", + "", + ] + + if has_soul: + lines.append("如果存在 `SOUL.md`,请体现其中定义的人格和语气。避免僵硬、模板化的回复;遵循其指导,除非有更高优先级的指令覆盖它。") + lines.append("") # 添加每个文件的内容 for file in context_files: @@ -573,29 +419,21 @@ def _build_runtime_section(runtime_info: Dict[str, Any], language: str) -> List[ # Only include if there's actual runtime info to display runtime_parts = [] if runtime_info.get("model"): - runtime_parts.append(f"模型={runtime_info['model']}" if language == "zh" else f"model={runtime_info['model']}") + runtime_parts.append(f"模型={runtime_info['model']}") if runtime_info.get("workspace"): - runtime_parts.append(f"工作空间={runtime_info['workspace']}" if language == "zh" else f"workspace={runtime_info['workspace']}") + runtime_parts.append(f"工作空间={runtime_info['workspace']}") # Only add channel if it's not the default "web" if runtime_info.get("channel") and runtime_info.get("channel") != "web": - runtime_parts.append(f"渠道={runtime_info['channel']}" if language == "zh" else f"channel={runtime_info['channel']}") + runtime_parts.append(f"渠道={runtime_info['channel']}") if not runtime_parts: return [] - if language == "zh": - lines = [ - "## 运行时信息", - "", - "运行时: " + " | ".join(runtime_parts), - "" - ] - else: - lines = [ - "## Runtime", - "", - "Runtime: " + " | ".join(runtime_parts), - "" - ] + lines = [ + "## 运行时信息", + "", + "运行时: " + " | ".join(runtime_parts), + "" + ] return lines diff --git a/agent/prompt/workspace.py b/agent/prompt/workspace.py index 8d46030..9abbf75 100644 --- a/agent/prompt/workspace.py +++ b/agent/prompt/workspace.py @@ -47,8 +47,8 @@ def ensure_workspace(workspace_dir: str, create_templates: bool = True) -> Works soul_path = os.path.join(workspace_dir, DEFAULT_SOUL_FILENAME) user_path = os.path.join(workspace_dir, DEFAULT_USER_FILENAME) agents_path = os.path.join(workspace_dir, DEFAULT_AGENTS_FILENAME) - memory_path = os.path.join(workspace_dir, DEFAULT_MEMORY_FILENAME) - memory_dir = os.path.join(workspace_dir, "memory") + memory_path = os.path.join(workspace_dir, DEFAULT_MEMORY_FILENAME) # MEMORY.md 在根目录 + memory_dir = os.path.join(workspace_dir, "memory") # 每日记忆子目录 # 创建memory子目录 os.makedirs(memory_dir, exist_ok=True) @@ -197,9 +197,9 @@ def _get_soul_template() -> str: def _get_user_template() -> str: """用户身份信息模板""" - return """# USER.md - 关于我的用户 + return """# USER.md - 用户基本信息 -*了解你正在帮助的人。随着了解的深入,更新此文件。* +*这个文件只存放不会变的基本身份信息。爱好、偏好、计划等动态信息请写入 MEMORY.md。* ## 基本信息 @@ -214,24 +214,14 @@ def _get_user_template() -> str: - **邮箱**: - **其他**: -## 偏好设置 - -- **语言**: 中文 -- **工作时间**: *(例如: 9:00-18:00)* -- **提醒方式**: *(用户偏好的提醒方式)* - ## 重要日期 - **生日**: -- **其他重要日期**: - -## 上下文 - -*(用户关心什么?正在做什么项目?有什么习惯?什么会让他们开心?随着时间积累这些信息。)* +- **纪念日**: --- -**记住**: 你了解得越多,就能帮助得越好。但要尊重隐私 - 这是在了解一个人,而不是建立档案。 +**注意**: 这个文件存放静态的身份信息 """ @@ -270,18 +260,31 @@ def _get_agents_template() -> str: - **仅在主会话中加载**(与用户的直接聊天) - **不要在共享上下文中加载**(群聊、与其他人的会话) - 这是为了**安全** - 包含不应泄露给陌生人的个人上下文 -- 你可以在主会话中自由**读取、编辑和更新** MEMORY.md - 记录重要事件、想法、决定、观点、经验教训 - 这是你精选的记忆 - 精华,而不是原始日志 +- 用 `edit` 工具追加新的记忆内容 ### 📝 写下来 - 不要"记在心里"! - **记忆是有限的** - 如果你想记住某事,写入文件 - "记在心里"不会在会话重启后保留,文件才会 -- 当有人说"记住这个" → 更新 `memory/YYYY-MM-DD.md` 或相关文件 +- 当有人说"记住这个" → 更新 `MEMORY.md` 或 `memory/YYYY-MM-DD.md` - 当你学到教训 → 更新 AGENTS.md、TOOLS.md 或相关技能 - 当你犯错 → 记录下来,这样未来的你不会重复 - **文字 > 大脑** 📝 +### 存储规则 + +当用户分享信息时,根据类型选择存储位置: + +1. **静态身份 → USER.md**(仅限:姓名、职业、时区、联系方式、生日) +2. **动态记忆 → MEMORY.md**(爱好、偏好、决策、目标、项目、教训、待办事项) +3. **当天对话 → memory/YYYY-MM-DD.md**(今天聊的内容) + +**重要**: +- 爱好(唱歌、篮球等)→ MEMORY.md,不是 USER.md +- 近期计划(下周要做什么)→ MEMORY.md,不是 USER.md +- USER.md 只存放不会变的基本信息 + ## 安全 - 永远不要泄露私人数据 @@ -290,7 +293,7 @@ def _get_agents_template() -> str: ## 工具使用 -技能提供你的工具。当你需要一个时,查看它的 `SKILL.md`。在 `TOOLS.md` 中保留本地笔记(相机名称、SSH详情、语音偏好)。 +技能提供你的工具。当你需要一个时,查看它的 `SKILL.md`。 ## 让它成为你的 @@ -299,34 +302,13 @@ def _get_agents_template() -> str: def _get_memory_template() -> str: - """长期记忆模板""" + """长期记忆模板 - 创建一个空文件,由 Agent 自己填充""" return """# MEMORY.md - 长期记忆 -*这是你精选的长期记忆。重要的背景信息、决策和经验教训都记录在这里。* - -## 重要背景 - -*(记录与用户相关的重要背景信息)* - -## 关键决策 - -*(记录做过的重要决定及其原因)* - -## 经验教训 - -*(记录学到的教训和避免的陷阱)* - -## 项目和目标 - -*(记录正在进行的项目和长期目标)* +*这是你的长期记忆文件。记录重要的事件、决策、偏好、学到的教训。* --- -**使用指南**: -- 定期从每日记忆文件中提取重要内容更新到这里 -- 保持内容精炼和有价值 -- 移除过时或不再相关的信息 -- 这应该是精华的总结,而不是流水账 """ diff --git a/agent/tools/memory/memory_get.py b/agent/tools/memory/memory_get.py index 8abb207..d828386 100644 --- a/agent/tools/memory/memory_get.py +++ b/agent/tools/memory/memory_get.py @@ -22,7 +22,7 @@ class MemoryGetTool(BaseTool): "properties": { "path": { "type": "string", - "description": "Relative path to the memory file (e.g., 'memory/MEMORY.md', 'memory/2024-01-29.md')" + "description": "Relative path to the memory file (e.g., 'MEMORY.md', 'memory/2024-01-29.md')" }, "start_line": { "type": "integer", diff --git a/agent/tools/memory/memory_search.py b/agent/tools/memory/memory_search.py index c6a3e7a..d7b14df 100644 --- a/agent/tools/memory/memory_search.py +++ b/agent/tools/memory/memory_search.py @@ -85,7 +85,7 @@ class MemorySearchTool(BaseTool): return ToolResult.success( f"No memories found for '{query}'. " f"This is normal if no memories have been stored yet. " - f"You can store new memories by writing to memory/MEMORY.md or memory/YYYY-MM-DD.md files." + f"You can store new memories by writing to MEMORY.md or memory/YYYY-MM-DD.md files." ) # Format results