Skill: skillforge-jojo/mflow-memory-cn (version 1.0.0)

--- name: mflow-memory-cn version: 1.0.0 description: | 中式智慧记忆引擎 — 基于M-flow知识图谱的长期记忆系统，融合中国人的优秀基因： **仁** — 以用户为中心，理解情感与意图 **义** — 识别责任与承诺，主动履行约定 **礼** — 懂分寸、知进退，适当时机适当行动 **智** — 深度关联推理，举一反三 **信** — 建立信任档案，言行一致追踪 相比原版M-flow，新增： - 关系亲密度评分（五伦系统） - 承诺追踪与提醒（君子一诺） - 情感温度感知（人情冷暖） - 时机判断系统（审时度势） - 集体智慧融合（和而不同） requiredBinaries: - docker requiredEnvVars: - LLM_API_KEY homepage: https://github.com/FlowElement-ai/m_flow extends: mflow-memory --- # 中式智慧记忆引擎 > "君子务本，本立而道生。" — 《论语》 为AI Agent注入中国人的优秀基因，让记忆不再是冷冰冰的数据存储，而是有温度、有智慧、有分寸的生命体。 ## 一、核心哲学：五常记忆法 ### 仁 (Ren) — 以人为本 记忆不只是存事实，更要存**人情**： - 用户说过的话，背后是什么**情感** - 用户的偏好，背后是什么**价值观** - 用户的决定，背后是什么**顾虑** ``` 记忆存储格式升级： { "content": "JOJO说不喜欢周末加班", "emotion": "疲惫+无奈", // 新增：情感标签 "value": "工作生活平衡", // 新增：价值观洞察 "concern": "担心错过家庭时间", // 新增：深层顾虑 "timestamp": "2026-04-22" } ``` ### 义 (Yi) — 一诺千金 中国人最重**承诺**。系统自动识别并追踪： - "我明天给你" → 提醒跟进 - "下次一定" → 记录待兑现 - "回头说" → 主动追问 ``` 承诺追踪系统： ├── 待兑现承诺 (Pending) │ ├── "4月底前完成NetPilot-AI" → 剩余X天 │ └── "闲鱼发布3个产品" → 未完成 ├── 已兑现承诺 (Fulfilled) → 建立信任 └── 逾期待解释 (Overdue) → 需要说明 ``` ### 礼 (Li) — 懂分寸 不是什么都记，不是什么时候都提： - **不该记的**：用户的私密抱怨（只存不主动提） - **不该提的**：用户已明确翻篇的事 - **该记但不该马上说的**：等合适时机 ``` 时机判断矩阵： ┌─────────────┬─────────────┬─────────────┐ │ 事项类型 │ 不提 │ 该提 │ ├─────────────┼─────────────┼─────────────┤ │ 正在处理 │ 刚说1分钟 │ 超过1小时 │ │ 承诺事项 │ 还在当天 │ 临近截止 │ │ 用户错误 │ 当众场合 │ 私下对话 │ │ 敏感话题 │ 用户回避 │ 主动询问 │ └─────────────┴─────────────┴─────────────┘ ``` ### 智 (Zhi) — 举一反三 记忆要能**推理**： - 用户A偏好 → 推测类似场景偏好 - 过去成功经验 → 复用到新问题 - 用户拒绝理由 → 预判未来选择 ``` 关联推理示例： JOJO之前说"不想要太复杂的工具" → 推理：新工具推荐优先简单方案 → 验证：推荐了简单版，JOJO接受了 → 更新：建立"简单偏好"权重+1 ``` ### 信 (Xin) — 言行一致 建立**信任档案**： - 用户说过的话，是否做到了 - 用户承诺的目标，进度如何 - 用户的真实偏好 vs 声称偏好 ``` 信任档案： ├── 言行一致性：85% │ ├── 说要早起 → 实际早起率 60% │ ├── 说要运动 → 实际运动率 40% │ └── 说要学X → 实际学习率 70% ├── 偏好真实性 │ ├── 声称"不在意" → 实际在意 │ └── 声称"随便" → 实际有偏好 └── 承诺履约率：73% ``` ## 二、记忆策略（中式升级版） ### 存储规则 **必存**（立即调用 `save_interaction`）： 1. 用户明确说"记住"、"别忘了" 2. 重要决定和理由（决策逻辑） 3. 承诺事项和时间节点 4. 用户偏好和背后原因 5. 项目关键节点和经验教训 **不存**： 1. 纯闲聊、问候、客套 2. 用户明确说"算了"、"不用记" 3. 重复已存储的信息 4. 明显的抱怨发泄（情绪性内容，不形成事实） ### 检索规则 **主动检索时机**： 1. 用户提到"之前"、"上次"、"记得吗" 2. 涉及用户偏好的决策时 3. 承诺事项临近截止时 4. 用户询问自己的进度/状态时 **检索方式升级**： - 原版：关键词匹配 - 升级版：**意图+情感+关联**三维检索 ``` 检索示例： 用户问："我之前说的那个项目怎么样了？" 原版搜索：["那个项目", "怎么样"] 升级搜索： - 意图：查询项目进度 - 情感：关心/期待 - 关联：找最近活跃项目 + 用户参与项目 - 结果：NetPilot-AI（用户发起，v0.4阶段） ``` ## 三、关系管理系统（五伦系统） 中国人讲究**关系**，不同关系不同对待： ``` 关系层级： ├── 核心圈（JOJO本人） │ └── 完全信任，主动服务，深度记忆 ├── 工作圈（项目相关人） │ └── 专业态度，任务导向，按需记忆 ├── 社交圈（群聊、公共场合） │ └── 谨慎发言，保护隐私，选择性记忆 └── 陌生圈 └── 基础礼貌，最小记忆 ``` **关系亲密度计算**： ``` intimacy = 交互次数×0.1 + 深度对话×0.3 + 情感分享×0.5 + 信任验证×0.4 ``` ## 四、时机感知系统 ### 审时度势 **不看时机乱说话 = 没眼力见** ``` 时机判断： ├── 时间时机 │ ├── 深夜（23:00-8:00）→ 除非紧急，静默 │ ├── 工作时段 → 专注工作提醒 │ └── 周末 → 生活话题优先 ├── 情绪时机 │ ├── 用户烦躁 → 简洁直接 │ ├── 用户兴奋 → 可以深入 │ └── 用户疲惫 → 少说多做 └── 场合时机 ├── 私聊 → 可以深度 ├── 群聊 → 谨慎发言 └── 公开 → 维护形象 ``` ### 人情温度计 感知对话的**温度**： - 热络（多问多答）→ 可以主动 - 平淡（一问一答）→ 完成任务即可 - 冷淡（敷衍简短）→ 少说多做 - 紧张（有冲突）→ 先缓解情绪 ## 五、集成原有M-flow工具 保留原版所有MCP工具，增强调用逻辑： | 原版工具 | 中式升级 | |---------|---------| | `save_interaction` | 增加：情感标签、价值洞察、承诺识别 | | `search` | 增加：意图理解、关联推理、时机判断 | | `query` | 增加：关系上下文、场合适配 | | `memorize` | 增加：经验提炼、教训总结 | | `prune` | 增加：分级清理（保留承诺相关） | ## 六、使用示例 ### 示例1：记住偏好 ``` JOJO: "我不喜欢太花哨的界面，简洁就好" 存储： { "content": "偏好简洁界面，不喜欢花哨", "emotion": "明确", "value": "效率优先", "preference_type": "UI风格", "weight": 0.9 // 高权重，影响后续推荐 } ``` ### 示例2：承诺追踪 ``` JOJO: "周末把那个报告发我" 自动识别： { "type": "承诺", "content": "发送报告", "deadline": "本周末", "status": "pending", "remind_before": "周六18:00" } 到期提醒： "JOJO，您说周末发报告，现在周六下午了，需要帮忙吗？" ``` ### 示例3：举一反三 ``` 历史记忆： - JOJO拒绝过"需要安装的桌面软件" - JOJO接受过"网页版工具" - JOJO偏好"一键启动" 新推荐逻辑： → 遇到新工具时，优先推荐：网页版/免安装/一键启动 → 自动过滤：需要复杂配置的方案 ``` ## 七、与原版M-flow的关系 ``` mflow-memory (原版) ↓ 继承 mflow-memory-cn (中式升级) ├── 保留：所有MCP工具 ├── 保留：知识图谱存储 ├── 新增：五常记忆法 ├── 新增：承诺追踪 ├── 新增：时机判断 └── 新增：关系管理 ``` ## 八、Setup 与原版相同，需要Docker： ```bash # 安装原版M-flow bash ~/.openclaw/skills/mflow-memory/scripts/setup.sh # 中式升级会自动增强存储逻辑 ``` ## 九、设计理念 > "温故而知新" — 记忆不只是回顾，更是为了更好地前行 这个升级版不只是技术增强，更是**文化融合**： - 西方技术：知识图谱、向量检索、语义理解 - 中国智慧：人情世故、审时度势、举一反三 让AI Agent既有**能力**，又有**情商**。 --- *Created by 马斯克 for JOJO | 2026-04-23*

path: core/main.py
content: """
mflow-memory-cn 中式智慧记忆引擎
主入口 — 整合所有模块，对外提供统一接口
"""

from datetime import datetime
from typing import Optional, Dict, List

from .memory_store import MemoryStore
from .promise_tracker import PromiseTracker
from .relationship_manager import RelationshipManager
from .timing_sensor import TimingSensor, TimeSlot, EmotionalState
from .wisdom_engine import WisdomEngine

class ChineseMemoryEngine:
    """
    中式智慧记忆引擎主类
    
    整合五大模块：
    - MemoryStore: 记忆存储（仁）
    - PromiseTracker: 承诺追踪（义）
    - RelationshipManager: 关系管理（五伦）
    - TimingSensor: 时机感知（礼）
    - WisdomEngine: 智慧推理（智）
    """
    
    def __init__(self, data_dir: Optional[str] = None):
        """初始化所有子模块"""
        self.memory = MemoryStore(data_dir)
        self.promise = PromiseTracker()
        self.relationship = RelationshipManager()
        self.timing = TimingSensor()
        self.wisdom = WisdomEngine()
        
        # 默认用户
        self.current_user = "JOJO"
    
    # ========== 记忆操作 ==========
    
    def remember(self, content: str,
                emotion: Optional[str] = None,
                value: Optional[str] = None,
                concern: Optional[str] = None,
                user_id: Optional[str] = None) -> str:
        """
        存储记忆（仁-Ren）
        
        自动：
        1. 识别情感
        2. 检测承诺
        3. 判断是否值得记住
        """
        uid = user_id or self.current_user
        
        # 时机感知：判断是否该存储
        should_store = True  # 默认存储，除非是纯闲聊
        
        # 记录互动
        self.relationship.record_interaction(uid, "normal")
        
        # 存储记忆
        memory_id = self.memory.save(
            content=content,
            user_id=uid,
            emotion=emotion,
            value=value,
            concern=concern
        )
        
        return memory_id
    
    def recall(self, query: str,
              user_id: Optional[str] = None) -> List[Dict]:
        """
        检索记忆（智-Zhi）
        
        升级版检索：
        1. 意图理解
        2. 关联推理
        3. 时机适配
        """
        uid = user_id or self.current_user
        
        # 基础搜索
        results = self.memory.search(query, uid)
        
        # 关联推理：举一反三
        inferred_prefs = self.wisdom.infer_preference(uid, query)
        
        return {
            "results": results,
            "inferred_preferences": inferred_prefs,
            "context": self.get_context(uid)
        }
    
    def get_context(self, user_id: Optional[str] = None) -> Dict:
        """获取用户上下文（用于注入对话）"""
        uid = user_id or self.current_user
        
        return self.memory.get_context(uid)
    
    # ========== 承诺操作 ==========
    
    def register_promise(self, content: str,
                       deadline: Optional[str] = None,
                       user_id: Optional[str] = None) -> str:
        """注册承诺（义-Yi）"""
        uid = user_id or self.current_user
        
        return self.promise.register(content, deadline, uid)
    
    def check_promises(self) -> Dict:
        """
        检查承诺状态
        
        返回：
        - pending: 待履行
        - overdue: 逾期
        - near_deadline: 临近截止
        """
        return {
            "pending": self.promise.get_pending(),
            "overdue": self.promise.get_overdue(),
            "near_deadline": self.promise.get_near_deadline(24),
            "stats": self.promise.get_stats(),
            "trust_score": self.promise.get_trust_score()
        }
    
    def fulfill_promise(self, promise_id: str):
        """标记承诺已履行"""
        self.promise.fulfill(promise_id)
        
        # 信任验证+1
        self.relationship.record_interaction(self.current_user, "trust")
    
    def get_reminders(self) -> List[str]:
        """获取待发送的提醒"""
        return self.promise.get_reminders()
    
    # ========== 关系操作 ==========
    
    def get_user_tier(self, user_id: Optional[str] = None) -> str:
        """获取用户关系层级"""
        uid = user_id or self.current_user
        tier = self.relationship.get_tier(uid)
        return self.relationship.TIERS[tier]["name"]
    
    def get_response_guide(self, user_id: Optional[str] = None) -> Dict:
        """
        获取回复指南
        
        基于关系层级和时机，返回合适的回复策略
        """
        uid = user_id or self.current_user
        
        # 获取关系风格
        rel_style = self.relationship.get_response_style(uid)
        
        # 获取时机风格
        time_style = self.timing.get_response_style()
        
        # 综合判断
        return {
            "tier": self.get_user_tier(uid),
            "intimacy": self.relationship.get_intimacy(uid),
            "should_be_proactive": rel_style["proactive"],
            "depth": rel_style["depth"],
            "can_advise": rel_style["advice"],
            "emotional_support": rel_style.get("emotional_support", False),
            "current_time_slot": self.timing.get_time_slot().value,
            "recommended_style": time_style["style"]
        }
    
    # ========== 时机操作 ==========
    
    def should_i_act(self, action_type: str,
                    is_user_initiated: bool = False) -> tuple[bool, str]:
        """
        判断是否该行动
        
        Args:
            action_type: 动作类型
            is_user_initiated: 是否用户主动
        """
        return self.timing.should_act(action_type, is_user_initiated)
    
    def get_timing_analysis(self) -> Dict:
        """获取完整时机分析"""
        return self.timing.analyze_context()
    
    # ========== 智慧操作 ==========
    
    def learn_from_feedback(self,
                          was_accepted: bool,
                          context: str,
                          action: str,
                          outcome: str):
        """
        从反馈中学习
        
        当用户接受或拒绝一个建议时调用
        """
        uid = self.current_user
        
        if was_accepted:
            self.wisdom.record_experience(uid, "success", context, action, outcome)
            self.relationship.record_interaction(uid, "trust")
        else:
            self.wisdom.record_experience(uid, "failure", context, action, outcome)
            self.wisdom.learn_rejection_pattern(uid, action, context)
    
    def predict_user_response(self, proposed_action: str) -> tuple[bool, str]:
        """
        预测用户反应
        
        基于历史拒绝模式
        """
        return self.wisdom.predict_rejection(self.current_user, proposed_action)
    
    def get_wisdom_report(self, user_id: Optional[str] = None) -> Dict:
        """获取智慧报告"""
        uid = user_id or self.current_user
        return self.wisdom.get_wisdom_summary(uid)
    
    # ========== 综合分析 ==========
    
    def analyze_before_response(self, user_message: str) -> Dict:
        """
        响应前综合分析
        
        在回复用户之前调用，返回完整的分析结果
        """
        # 1. 获取时机
        timing = self.timing.analyze_context()
        
        # 2. 获取用户关系
        rel_guide = self.get_response_guide()
        
        # 3. 检查承诺
        promise_status = self.check_promises()
        
        # 4. 尝试检索相关记忆
        recall = self.recall(user_message)
        
        # 5. 预测用户反应
        predicted_rejection = self.predict_user_response(user_message)
        
        return {
            "timing": timing,
            "relationship": rel_guide,
            "promises": promise_status,
            "relevant_memories": recall["results"][:3],
            "inferred_preferences": recall["inferred_preferences"],
            "rejection_risk": predicted_rejection,
            "recommendation": self._generate_response_recommendation(
                timing, rel_guide, promise_status, predicted_rejection
            )
        }
    
    def _generate_response_recommendation(self, timing, rel_guide, promises, rejection) -> str:
        """生成回复建议"""
        parts = []
        
        # 时机建议
        parts.append(f"[时机] {timing['recommendation']}")
        
        # 承诺提醒
        if promises["overdue"]:
            parts.append(f"[承诺] 有{len(promises['overdue'])}个逾期承诺需处理")
        elif promises["near_deadline"]:
            parts.append(f"[承诺] 有{len(promises['near_deadline'])}个承诺临近截止")
        
        # 拒绝风险
        if rejection[0]:
            parts.append(f"[注意] {rejection[1]}")
        
        return " | ".join(parts)
    
    # ========== 工具函数 ==========
    
    def get_full_report(self) -> Dict:
        """获取完整报告（用于定期总结）"""
        return {
            "engine": "mflow-memory-cn v1.0",
            "timestamp": datetime.now().isoformat(),
            "current_user": self.current_user,
            "relationship": {
                "tier": self.get_user_tier(),
                "intimacy": self.relationship.get_intimacy(self.current_user),
                "total_interactions": self.relationship._load_relationship(self.current_user).get("interaction_count", 0) if self.relationship._load_relationship(self.current_user) else 0
            },
            "promises": self.check_promises(),
            "wisdom": self.get_wisdom_report(),
            "timing": self.get_timing_analysis()
        }


# 便捷函数
def create_engine(data_dir: Optional[str] = None) -> ChineseMemoryEngine:
    """创建引擎实例"""
    return ChineseMemoryEngine(data_dir)


path: core/memory_store.py
content: """
记忆存储模块 (仁-Ren)
带情感标签的记忆存储，增强版M-flow

功能：
1. 标准记忆存储（继承M-flow格式）
2. 情感标签自动识别
3. 价值洞察提取
4. 承诺识别
5. 关联推理
"""

import json
import re
from datetime import datetime
from pathlib import Path
from typing import Optional, Dict, List, Any

class MemoryStore:
    """
    中式智慧记忆存储
    
    与原版M-flow兼容，但增加：
    - emotion: 情感标签
    - value: 价值观洞察
    - concern: 深层顾虑
    - promise: 承诺识别
    - weight: 权重
    """
    
    def __init__(self, data_dir: Optional[str] = None):
        if data_dir is None:
            data_dir = Path.home() / ".mflow-memory-cn" / "data"
        self.data_dir = Path(data_dir)
        self.data_dir.mkdir(parents=True, exist_ok=True)
        
        # 主记忆文件
        self.memories_file = self.data_dir / "memories.jsonl"
        self.emotions_file = self.data_dir / "emotions.jsonl"
        self.promises_file = self.data_dir / "promises.jsonl"
        
        # 承诺追踪器（实例化）
        from .promise_tracker import PromiseTracker
        self.promise_tracker = PromiseTracker(self.data_dir / "promises")
        
    # ========== 仁：以人为本 ==========
    
    def save(self, content: str, user_id: str = "default",
             emotion: Optional[str] = None,
             value: Optional[str] = None,
             concern: Optional[str] = None,
             metadata: Optional[Dict] = None) -> str:
        """
        保存记忆（仁-Ren：存储人情，不只存事实）
        
        Args:
            content: 记忆内容
            user_id: 用户标识
            emotion: 情感标签（如"疲惫"、"兴奋"、"担忧"）
            value: 价值观洞察（如"效率优先"、"家庭为重"）
            concern: 深层顾虑（如"担心错过截止日期"）
            metadata: 其他元数据
            
        Returns:
            memory_id: 记忆ID
        """
        # 自动情感识别（如果没有提供）
        if emotion is None:
            emotion = self._detect_emotion(content)
        
        # 自动承诺识别
        promise_data = self._detect_promise(content)
        
        # 构建记忆对象
        memory = {
            "id": self._generate_id(),
            "content": content,
            "user_id": user_id,
            "timestamp": datetime.now().isoformat(),
            # 仁扩展
            "emotion": emotion,
            "value": value,
            "concern": concern,
            # 元数据
            "metadata": metadata or {}
        }
        
        # 保存主记忆
        self._append_to_file(self.memories_file, memory)
        
        # 如果有情感标签，单独存储（用于情感分析）
        if emotion:
            self._append_to_file(self.emotions_file, {
                "memory_id": memory["id"],
                "emotion": emotion,
                "timestamp": memory["timestamp"]
            })
        
        # 如果识别到承诺，启动追踪
        if promise_data:
            self.promise_tracker.register(
                content=promise_data["promise"],
                deadline=promise_data.get("deadline"),
                context=content
            )
            
        return memory["id"]
    
    def search(self, query: str, user_id: str = "default",
               include_emotions: bool = True,
               time_range: Optional[tuple] = None) -> List[Dict]:
        """
        搜索记忆（智-Zhi：举一反三，关联推理）
        
        升级点：
        - 原版：关键词匹配
        - 升级版：意图理解 + 情感 + 关联 三维检索
        """
        memories = self._load_memories(user_id)
        
        # 时间过滤
        if time_range:
            start, end = time_range
            memories = [m for m in memories 
                       if start <= m.get("timestamp", "") <= end]
        
        # 意图理解 + 关键词匹配
        query_lower = query.lower()
        scored = []
        
        for mem in memories:
            content = mem.get("content", "").lower()
            
            # 基础分：关键词匹配
            score = 0
            keywords = query_lower.split()
            for kw in keywords:
                if kw in content:
                    score += 1
            
            # 加分：情感匹配（查询中有情感词）
            if include_emotions and mem.get("emotion"):
                for kw in keywords:
                    if kw in ["累", "烦", "担心", "焦虑", "开心", "兴奋"]:
                        if mem["emotion"] and kw in mem["emotion"]:
                            score += 2
            
            # 加分：价值匹配
            if mem.get("value"):
                for kw in keywords:
                    if kw in mem["value"].lower():
                        score += 1.5
            
            if score > 0:
                scored.append((score, mem))
        
        # 按分数排序
        scored.sort(key=lambda x: x[0], reverse=True)
        return [m for _, m in scored]
    
    def get_context(self, user_id: str = "default") -> Dict:
        """
        获取用户上下文（用于每次对话前的记忆注入）
        
        返回：
        - 最近记忆（最近5条）
        - 情感趋势（最近的情绪变化）
        - 待履行承诺
        """
        memories = self._load_memories(user_id)
        recent = memories[-5:] if len(memories) > 5 else memories
        
        # 情感趋势
        emotions = self._load_emotions(user_id)
        recent_emotions = emotions[-10:] if len(emotions) > 10 else emotions
        
        return {
            "recent_memories": recent,
            "emotion_trend": [e.get("emotion") for e in recent_emotions],
            "pending_promises": self.promise_tracker.get_pending(),
            "user_values": self._extract_values(memories),
            "user_concerns": self._extract_concerns(memories)
        }
    
    # ========== 辅助方法 ==========
    
    def _detect_emotion(self, content: str) -> Optional[str]:
        """自动情感识别"""
        emotion_keywords = {
            "疲惫": ["累", "困", "疲惫", "没精神"],
            "兴奋": ["兴奋", "激动", "开心", "太好了"],
            "担忧": ["担心", "焦虑", "怕", "不安"],
            "无奈": ["无奈", "没办法", "只能", "就这样"],
            "期待": ["期待", "希望", "想要", "希望能够"],
            "满足": ["满意", "不错", "挺好", "可以"],
            "烦躁": ["烦", "烦躁", "闹心", "不爽"],
        }
        
        for emotion, keywords in emotion_keywords.items():
            if any(kw in content for kw in keywords):
                return emotion
        return None
    
    def _detect_promise(self, content: str) -> Optional[Dict]:
        """自动承诺识别"""
        promise_patterns = [
            (r"(明天|后天|周末|这周)(给|发|做|完成)(.*)", "short"),
            (r"(\d+月\d+日|下周一|下周二)(给|发|做)(.*)", "specific"),
            (r"(回头|之后|等一下)(给|发|做)(.*)", "deferred"),
            (r"(一定|肯定|保证)(给|发|做)(.*)", "commitment"),
        ]
        
        for pattern, ptype in promise_patterns:
            match = re.search(pattern, content)
            if match:
                return {
                    "promise": match.group(0),
                    "type": ptype,
                    "deadline": self._extract_deadline(content)
                }
        return None
    
    def _extract_deadline(self, content: str) -> Optional[str]:
        """提取截止时间"""
        date_patterns = [
            r"(\d{1,2}月\d{1,2}日)",
            r"(明天|后天|周末|下周)",
            r"(\d{4}-\d{2}-\d{2})"
        ]
        
        for pattern in date_patterns:
            match = re.search(pattern, content)
            if match:
                return match.group(1)
        return None
    
    def _generate_id(self) -> str:
        """生成唯一ID"""
        import uuid
        return f"mem_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:6]}"
    
    def _append_to_file(self, filepath: Path, data: Dict):
        """追加到JSONL文件"""
        with open(filepath, 'a', encoding='utf-8') as f:
            f.write(json.dumps(data, ensure_ascii=False) + '\n')
    
    def _load_memories(self, user_id: str) -> List[Dict]:
        """加载用户记忆"""
        if not self.memories_file.exists():
            return []
        
        memories = []
        with open(self.memories_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    mem = json.loads(line)
                    if mem.get("user_id") == user_id:
                        memories.append(mem)
                except json.JSONDecodeError:
                    continue
        return memories
    
    def _load_emotions(self, user_id: str) -> List[Dict]:
        """加载情感记录"""
        if not self.emotions_file.exists():
            return []
        
        emotions = []
        memory_ids = {m["id"] for m in self._load_memories(user_id)}
        
        with open(self.emotions_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    emo = json.loads(line)
                    if emo.get("memory_id") in memory_ids:
                        emotions.append(emo)
                except json.JSONDecodeError:
                    continue
        return emotions
    
    def _extract_values(self, memories: List[Dict]) -> List[str]:
        """提取价值观"""
        return list(set(m.get("value") for m in memories if m.get("value")))
    
    def _extract_concerns(self, memories: List[Dict]) -> List[str]:
        """提取顾虑"""
        return list(set(m.get("concern") for m in memories if m.get("concern")))


path: core/promise_tracker.py
content: """
承诺追踪模块 (义-Yi)
君子一诺，一诺千金

功能：
1. 承诺自动识别与注册
2. 截止日期追踪
3. 提醒生成
4. 履约记录
5. 信任度计算
"""

import json
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional, List, Dict
from dateutil import parser as date_parser

class PromiseTracker:
    """
    承诺追踪器
    
    中国人最重承诺。这个模块确保每一个承诺都被追踪，
    不遗漏、不忘记。
    
    状态流转：
    pending -> fulfilled (完成)
              -> overdue (逾期，待解释)
              -> cancelled (取消/放弃)
    """
    
    def __init__(self, data_dir: Optional[Path] = None):
        if data_dir is None:
            data_dir = Path.home() / ".mflow-memory-cn" / "promises"
        self.data_dir = Path(data_dir)
        self.data_dir.mkdir(parents=True, exist_ok=True)
        
        self.promises_file = self.data_dir / "promises.jsonl"
        self.stats_file = self.data_dir / "stats.json"
        
        # 加载统计数据
        self.stats = self._load_stats()
    
    def register(self, content: str, deadline: Optional[str] = None,
                 context: Optional[str] = None) -> str:
        """
        注册一个新承诺
        
        Args:
            content: 承诺内容
            deadline: 截止时间（可为空，之后提醒追问）
            context: 上下文
            
        Returns:
            promise_id: 承诺ID
        """
        promise = {
            "id": self._generate_id(),
            "content": content,
            "deadline": deadline,
            "deadline_parsed": self._parse_deadline(deadline) if deadline else None,
            "context": context,
            "status": "pending",
            "created_at": datetime.now().isoformat(),
            "updated_at": datetime.now().isoformat(),
            "reminders_sent": 0,
            "fulfillment_note": None
        }
        
        self._append_to_file(self.promises_file, promise)
        self.stats["total_promises"] += 1
        self._save_stats()
        
        return promise["id"]
    
    def get_pending(self) -> List[Dict]:
        """获取所有待履行的承诺"""
        return self._load_promises_by_status("pending")
    
    def get_overdue(self) -> List[Dict]:
        """获取所有逾期的承诺"""
        overdue = []
        for p in self._load_promises_by_status("pending"):
            if self._is_overdue(p):
                overdue.append(p)
        return overdue
    
    def get_near_deadline(self, hours: int = 24) -> List[Dict]:
        """获取临近截止的承诺（24小时内）"""
        near = []
        now = datetime.now()
        threshold = now + timedelta(hours=hours)
        
        for p in self._load_promises_by_status("pending"):
            dp = p.get("deadline_parsed")
            if dp:
                if now <= dp <= threshold:
                    near.append(p)
        return near
    
    def fulfill(self, promise_id: str, note: Optional[str] = None):
        """
        标记承诺已履行
        
        Args:
            promise_id: 承诺ID
            note: 备注（如"提前完成"、"按时完成"）
        """
        promises = self._load_all_promises()
        
        for p in promises:
            if p["id"] == promise_id:
                p["status"] = "fulfilled"
                p["fulfilled_at"] = datetime.now().isoformat()
                p["fulfillment_note"] = note
                p["updated_at"] = datetime.now().isoformat()
                break
        
        self._save_all_promises(promises)
        self.stats["fulfilled_promises"] += 1
        self._save_stats()
    
    def overdue(self, promise_id: str, explanation: Optional[str] = None):
        """标记承诺逾期"""
        promises = self._load_all_promises()
        
        for p in promises:
            if p["id"] == promise_id:
                p["status"] = "overdue"
                p["explanation"] = explanation
                p["updated_at"] = datetime.now().isoformat()
                break
        
        self._save_all_promises(promises)
        self.stats["overdue_promises"] += 1
        self._save_stats()
    
    def cancel(self, promise_id: str, reason: str):
        """取消承诺"""
        promises = self._load_all_promises()
        
        for p in promises:
            if p["id"] == promise_id:
                p["status"] = "cancelled"
                p["cancel_reason"] = reason
                p["updated_at"] = datetime.now().isoformat()
                break
        
        self._save_all_promises(promises)
        self.stats["cancelled_promises"] += 1
        self._save_stats()
    
    def get_stats(self) -> Dict:
        """获取承诺统计"""
        self._recalculate_stats()
        return self.stats
    
    def get_trust_score(self) -> float:
        """
        计算信任度分数
        
        公式：
        trust_score = fulfilled / total * 100%
        """
        total = self.stats["total_promises"]
        if total == 0:
            return 100.0  # 没有记录，默认满分
        
        fulfilled = self.stats["fulfilled_promises"]
        cancelled = self.stats["cancelled_promises"]
        
        # 有效承诺 = 总承诺 - 取消
        valid = total - cancelled
        if valid == 0:
            return 100.0
        
        return (fulfilled / valid) * 100
    
    def generate_reminder(self, promise: Dict) -> str:
        """生成提醒文本"""
        deadline = promise.get("deadline", "未定")
        content = promise.get("content", "")
        
        if self._is_overdue(promise):
            return f"【逾期提醒】您曾承诺：{content}（截止：{deadline}）。需要说明情况吗？"
        else:
            return f"【承诺提醒】您承诺：{content}（截止：{deadline}）。请记得履行。"
    
    def should_remind(self) -> bool:
        """
        判断是否应该发送提醒
        
        规则：
        1. 有逾期的承诺
        2. 有24小时内到期的承诺
        """
        overdue = self.get_overdue()
        near = self.get_near_deadline(24)
        
        return len(overdue) > 0 or len(near) > 0
    
    def get_reminders(self) -> List[str]:
        """获取所有待发送的提醒"""
        reminders = []
        
        for p in self.get_overdue():
            reminders.append(self.generate_reminder(p))
        
        for p in self.get_near_deadline(24):
            reminders.append(self.generate_reminder(p))
        
        return reminders
    
    # ========== 私有方法 ==========
    
    def _is_overdue(self, promise: Dict) -> bool:
        """判断是否逾期"""
        dp = promise.get("deadline_parsed")
        if dp is None:
            return False
        return datetime.now() > dp
    
    def _parse_deadline(self, deadline: str) -> Optional[datetime]:
        """解析截止时间"""
        if not deadline:
            return None
        
        # 自然语言处理
        now = datetime.now()
        
        if "明天" in deadline:
            return now + timedelta(days=1)
        elif "后天" in deadline:
            return now + timedelta(days=2)
        elif "周末" in deadline:
            # 计算到本周末
            days_until_saturday = (5 - now.weekday()) % 7
            if days_until_saturday == 0:
                days_until_saturday = 7
            return now + timedelta(days=days_until_saturday)
        elif "下周" in deadline:
            return now + timedelta(days=7)
        
        # 尝试解析日期格式
        try:
            return date_parser.parse(deadline)
        except:
            return None
    
    def _generate_id(self) -> str:
        """生成唯一ID"""
        import uuid
        return f"prm_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:6]}"
    
    def _append_to_file(self, filepath: Path, data: Dict):
        """追加到JSONL文件"""
        with open(filepath, 'a', encoding='utf-8') as f:
            f.write(json.dumps(data, ensure_ascii=False) + '\n')
    
    def _load_promises_by_status(self, status: str) -> List[Dict]:
        """按状态加载承诺"""
        if not self.promises_file.exists():
            return []
        
        promises = []
        with open(self.promises_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    p = json.loads(line)
                    if p.get("status") == status:
                        promises.append(p)
                except json.JSONDecodeError:
                    continue
        return promises
    
    def _load_all_promises(self) -> List[Dict]:
        """加载所有承诺"""
        if not self.promises_file.exists():
            return []
        
        promises = []
        with open(self.promises_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    promises.append(json.loads(line))
                except json.JSONDecodeError:
                    continue
        return promises
    
    def _save_all_promises(self, promises: List[Dict]):
        """保存所有承诺（覆盖）"""
        with open(self.promises_file, 'w', encoding='utf-8') as f:
            for p in promises:
                f.write(json.dumps(p, ensure_ascii=False) + '\n')
    
    def _load_stats(self) -> Dict:
        """加载统计"""
        if self.stats_file.exists():
            with open(self.stats_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        return {
            "total_promises": 0,
            "fulfilled_promises": 0,
            "overdue_promises": 0,
            "cancelled_promises": 0
        }
    
    def _save_stats(self):
        """保存统计"""
        with open(self.stats_file, 'w', encoding='utf-8') as f:
            json.dump(self.stats, f, ensure_ascii=False, indent=2)
    
    def _recalculate_stats(self):
        """重新计算统计"""
        promises = self._load_all_promises()
        
        self.stats = {
            "total_promises": len(promises),
            "fulfilled_promises": sum(1 for p in promises if p.get("status") == "fulfilled"),
            "overdue_promises": sum(1 for p in promises if p.get("status") == "overdue"),
            "cancelled_promises": sum(1 for p in promises if p.get("status") == "cancelled")
        }
        self._save_stats()


path: core/relationship_manager.py
content: """
关系管理模块 (五伦系统)
中国人讲究关系，不同关系不同对待

层级：
- 核心圈（本人）
- 工作圈（协作）
- 社交圈（公共）
- 陌生圈
"""

import json
from datetime import datetime
from pathlib import Path
from typing import Optional, Dict, List

class RelationshipManager:
    """
    五伦关系管理器
    
    中国人讲究"五伦"：君臣、父子、夫妇、兄弟、朋友
    这里简化为四层关系体系：
    
    intimacy_score 范围：0-100
    """
    
    # 关系层级定义
    TIERS = {
        "core": {"name": "核心圈", "threshold": 80, "icon": "❤️"},
        "work": {"name": "工作圈", "threshold": 50, "icon": "💼"},
        "social": {"name": "社交圈", "threshold": 20, "icon": "🤝"},
        "stranger": {"name": "陌生圈", "threshold": 0, "icon": "👤"}
    }
    
    def __init__(self, data_dir: Optional[Path] = None):
        if data_dir is None:
            data_dir = Path.home() / ".mflow-memory-cn" / "relationships"
        self.data_dir = Path(data_dir)
        self.data_dir.mkdir(parents=True, exist_ok=True)
        
        self.relationships_file = self.data_dir / "relationships.jsonl"
    
    def get_tier(self, user_id: str) -> str:
        """获取用户所在层级"""
        intimacy = self.get_intimacy(user_id)
        
        for tier_name, tier_info in self.TIERS.items():
            if intimacy >= tier_info["threshold"]:
                return tier_name
        return "stranger"
    
    def get_intimacy(self, user_id: str) -> float:
        """计算亲密度分数"""
        rel = self._load_relationship(user_id)
        if not rel:
            return 0.0
        
        # 亲密度公式
        intimacy = (
            rel.get("interaction_count", 0) * 0.1 +
            rel.get("deep_conversation_count", 0) * 0.3 +
            rel.get("emotional_sharing_count", 0) * 0.5 +
            rel.get("trust_verified_count", 0) * 0.4
        )
        
        # 衰减因子（太久没互动会衰减）
        last_interaction = rel.get("last_interaction")
        if last_interaction:
            days_since = (datetime.now() - datetime.fromisoformat(last_interaction)).days
            decay = max(0, 1 - days_since * 0.01)  # 每天衰减1%，最多100天归零
            intimacy *= decay
        
        return min(100.0, intimacy)
    
    def record_interaction(self, user_id: str, 
                          interaction_type: str = "normal",
                          topic: Optional[str] = None):
        """
        记录一次互动
        
        Args:
            user_id: 用户ID
            interaction_type: 互动类型
                - "normal": 普通互动
                - "deep": 深度对话
                - "emotional": 情感分享
                - "trust": 信任验证（对方做到了承诺的事）
        """
        rel = self._load_relationship(user_id)
        
        # 初始化
        if not rel:
            rel = {
                "user_id": user_id,
                "created_at": datetime.now().isoformat(),
                "interaction_count": 0,
                "deep_conversation_count": 0,
                "emotional_sharing_count": 0,
                "trust_verified_count": 0,
                "last_interaction": None,
                "topics": []
            }
        
        # 更新计数
        rel["interaction_count"] += 1
        rel["last_interaction"] = datetime.now().isoformat()
        
        if interaction_type == "deep":
            rel["deep_conversation_count"] += 1
        elif interaction_type == "emotional":
            rel["emotional_sharing_count"] += 1
        elif interaction_type == "trust":
            rel["trust_verified_count"] += 1
        
        if topic:
            rel.setdefault("topics", []).append(topic)
        
        self._save_relationship(user_id, rel)
    
    def get_response_style(self, user_id: str) -> Dict:
        """
        获取针对该用户的回复风格
        
        不同层级有不同的回复策略：
        - 核心圈：主动、深度、可以建议
        - 工作圈：专业、效率、完成任务
        - 社交圈：谨慎、礼貌、选择性参与
        - 陌生圈：礼貌、简短、观察为主
        """
        tier = self.get_tier(user_id)
        
        styles = {
            "core": {
                "proactive": True,
                "depth": "deep",
                "advice": True,
                "emotional_support": True,
                "initiation": "high"
            },
            "work": {
                "proactive": True,
                "depth": "medium",
                "advice": True,
                "emotional_support": False,
                "initiation": "medium"
            },
            "social": {
                "proactive": False,
                "depth": "shallow",
                "advice": False,
                "emotional_support": False,
                "initiation": "low"
            },
            "stranger": {
                "proactive": False,
                "depth": "minimal",
                "advice": False,
                "emotional_support": False,
                "initiation": "none"
            }
        }
        
        return styles.get(tier, styles["stranger"])
    
    def get_info_sharing_level(self, user_id: str) -> str:
        """
        获取信息共享级别
        
        - core: 可以分享个人思考、担忧、建议
        - work: 分享工作相关信息
        - social: 分享公共信息
        - stranger: 最小必要信息
        """
        tier = self.get_tier(user_id)
        levels = {
            "core": "full",
            "work": "professional",
            "social": "public",
            "stranger": "minimal"
        }
        return levels.get(tier, "minimal")
    
    def get_leader(self) -> str:
        """获取核心用户ID（JOJO）"""
        # 核心用户固定为"default"或"JOJO"
        return "JOJO"
    
    def get_network_summary(self) -> Dict:
        """获取关系网络摘要"""
        relationships = self._load_all_relationships()
        
        summary = {
            "total_relationships": len(relationships),
            "by_tier": {tier: 0 for tier in self.TIERS.keys()},
            "average_intimacy": 0
        }
        
        if relationships:
            intimacies = []
            for rel in relationships:
                uid = rel.get("user_id")
                intimacy = self.get_intimacy(uid)
                intimacies.append(intimacy)
                
                tier = self.get_tier(uid)
                summary["by_tier"][tier] += 1
            
            summary["average_intimacy"] = sum(intimacies) / len(intimacies)
        
        return summary
    
    # ========== 私有方法 ==========
    
    def _load_relationship(self, user_id: str) -> Optional[Dict]:
        """加载关系数据"""
        if not self.relationships_file.exists():
            return None
        
        with open(self.relationships_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    rel = json.loads(line)
                    if rel.get("user_id") == user_id:
                        return rel
                except json.JSONDecodeError:
                    continue
        return None
    
    def _save_relationship(self, user_id: str, data: Dict):
        """保存关系数据"""
        relationships = self._load_all_relationships()
        
        # 更新或添加
        found = False
        for i, rel in enumerate(relationships):
            if rel.get("user_id") == user_id:
                relationships[i] = data
                found = True
                break
        
        if not found:
            relationships.append(data)
        
        # 写回文件
        with open(self.relationships_file, 'w', encoding='utf-8') as f:
            for rel in relationships:
                f.write(json.dumps(rel, ensure_ascii=False) + '\n')
    
    def _load_all_relationships(self) -> List[Dict]:
        """加载所有关系"""
        if not self.relationships_file.exists():
            return []
        
        relationships = []
        with open(self.relationships_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    relationships.append(json.loads(line))
                except json.JSONDecodeError:
                    continue
        return relationships


path: core/timing_sensor.py
content: """
时机感知模块 (礼-Li)
懂分寸、知进退，适当时机做适当的事

核心问题：
- 什么时候该主动？
- 什么时候该沉默？
- 什么时候该提醒？
- 什么时候不该说？
"""

from datetime import datetime, time
from typing import Optional, Dict, List
from enum import Enum

class TimeSlot(Enum):
    """时间段枚举"""
    DEEP_NIGHT = "深夜"      # 23:00 - 08:00
    MORNING = "早晨"        # 08:00 - 10:00
    WORK = "工作时间"       # 10:00 - 12:00
    LUNCH = "午休"          # 12:00 - 14:00
    AFTERNOON = "下午"      # 14:00 - 18:00
    EVENING = "晚间"        # 18:00 - 22:00
    NIGHT = "夜间"          # 22:00 - 23:00

class EmotionalState(Enum):
    """情绪状态枚举"""
    POSITIVE = "positive"     # 积极（兴奋、开心）
    NEUTRAL = "neutral"      # 中性
    NEGATIVE = "negative"     # 消极（烦躁、疲惫）
    UNKNOWN = "unknown"       # 未知

class TimingSensor:
    """
    时机感知器
    
    中国人讲"礼"，核心是懂分寸。
    这个模块判断当前是否是行动的合适时机。
    """
    
    # 时间段规则
    TIME_RULES = {
        TimeSlot.DEEP_NIGHT: {
            "action": "静默",
            "reason": "深夜，应让用户休息",
            "allowed": ["紧急提醒"],
            "forbidden": ["主动搭话", "长篇大论", "不紧急的提醒"]
        },
        TimeSlot.MORNING: {
            "action": "简洁",
            "reason": "早晨时间宝贵",
            "allowed": ["任务清单", "重要提醒"],
            "forbidden": ["闲聊", "复杂分析"]
        },
        TimeSlot.WORK: {
            "action": "专注",
            "reason": "工作时间，专注工作",
            "allowed": ["工作提醒", "效率工具"],
            "forbidden": ["生活话题", "娱乐内容"]
        },
        TimeSlot.LUNCH: {
            "action": "适度",
            "reason": "休息时间",
            "allowed": ["简短提醒"],
            "forbidden": ["长篇大论", "复杂任务"]
        },
        TimeSlot.AFTERNOON: {
            "action": "正常",
            "reason": "下午黄金时间",
            "allowed": ["全类型"],
            "forbidden": []
        },
        TimeSlot.EVENING: {
            "action": "温和",
            "reason": "下班时间",
            "allowed": ["生活话题", "轻松内容"],
            "forbidden": ["工作施压"]
        },
        TimeSlot.NIGHT: {
            "action": "安静",
            "reason": "接近休息时间",
            "allowed": ["必要提醒"],
            "forbidden": ["闲聊", "复杂任务"]
        }
    }
    
    # 情绪响应规则
    EMOTION_RULES = {
        EmotionalState.POSITIVE: {
            "response_style": "热情",
            "engagement": "high",
            "topics": "可以深入讨论",
            "avoid": []
        },
        EmotionalState.NEUTRAL: {
            "response_style": "专业",
            "engagement": "medium",
            "topics": "完成任务即可",
            "avoid": ["过多闲聊"]
        },
        EmotionalState.NEGATIVE: {
            "response_style": "简洁",
            "engagement": "low",
            "topics": "少说多做",
            "avoid": ["长篇解释", "建议", "复杂分析"]
        },
        EmotionalState.UNKNOWN: {
            "response_style": "观察",
            "engagement": "observe",
            "topics": "等待明确信号",
            "avoid": ["主动判断情绪"]
        }
    }
    
    def __init__(self):
        self.last_check = None
        self.current_state = None
    
    def get_time_slot(self) -> TimeSlot:
        """获取当前时间段"""
        now = datetime.now()
        current_time = now.time()
        
        if current_time >= time(23, 0) or current_time < time(8, 0):
            return TimeSlot.DEEP_NIGHT
        elif current_time < time(10, 0):
            return TimeSlot.MORNING
        elif current_time < time(12, 0):
            return TimeSlot.WORK
        elif current_time < time(14, 0):
            return TimeSlot.LUNCH
        elif current_time < time(18, 0):
            return TimeSlot.AFTERNOON
        elif current_time < time(22, 0):
            return TimeSlot.EVENING
        else:
            return TimeSlot.NIGHT
    
    def should_act(self, action_type: str, 
                  is_user_initiated: bool = False) -> tuple[bool, str]:
        """
        判断是否应该执行某个动作
        
        Args:
            action_type: 动作类型（如"主动提醒"、"闲聊"、"复杂分析"）
            is_user_initiated: 是否是用户主动发起的
            
        Returns:
            (should_act, reason): 是否应该行动，以及原因
        """
        slot = self.get_time_slot()
        rules = self.TIME_RULES[slot]
        
        # 用户主动发起的，权限更大
        if is_user_initiated:
            return True, "用户主动发起"
        
        # 检查是否在允许列表
        if action_type in rules["allowed"]:
            return True, rules["reason"]
        
        # 检查是否在禁止列表
        if action_type in rules["forbidden"]:
            return False, rules["reason"]
        
        # 不明确的动作，按保守策略
        return False, "不在允许列表，保守处理"
    
    def get_response_style(self, user_emotion: EmotionalState = EmotionalState.UNKNOWN) -> Dict:
        """
        获取针对当前情绪的回复风格
        
        Args:
            user_emotion: 用户当前情绪
            
        Returns:
            风格配置字典
        """
        rules = self.EMOTION_RULES.get(user_emotion, self.EMOTION_RULES[EmotionalState.UNKNOWN])
        
        return {
            "style": rules["response_style"],
            "engagement": rules["engagement"],
            "topics": rules["topics"],
            "avoid": rules["avoid"],
            "time_slot": self.get_time_slot().value
        }
    
    def should_remember(self, content_type: str) -> tuple[bool, str]:
        """
        判断是否应该记住某个内容
        
        Args:
            content_type: 内容类型（如"私密抱怨"、"重要决定"）
        """
        rules = {
            "私密抱怨": (True, "可以记，但不应主动提起"),
            "重要决定": (True, "必须记住"),
            "承诺": (True, "必须记住并追踪"),
            "偏好": (True, "记住以便下次服务"),
            "闲聊": (False, "不需要记住"),
            "简单问答": (False, "不需要记住"),
            "情绪发泄": (True, "记住情感，但不形成事实记录"),
            "敏感信息": (True, "加密存储，不主动使用"),
        }
        
        rule = rules.get(content_type, (False, "默认不记住"))
        return rule
    
    def should_remind(self, topic: str, 
                     last_reminded: Optional[datetime] = None) -> tuple[bool, str]:
        """
        判断是否应该提醒某个话题
        
        Args:
            topic: 话题
            last_reminded: 上次提醒时间
        """
        slot = self.get_time_slot()
        
        # 深夜不主动提醒
        if slot == TimeSlot.DEEP_NIGHT:
            return False, "深夜，不打扰"
        
        # 检查频率限制
        if last_reminded:
            hours_since = (datetime.now() - last_reminded).total_seconds() / 3600
            
            # 紧急事项：2小时后可再提醒
            if topic in ["紧急", "截止", "逾期"]:
                return hours_since >= 2, f"需间隔{2}小时"
            
            # 重要事项：6小时后可再提醒
            if topic in ["重要", "承诺", "待办"]:
                return hours_since >= 6, f"需间隔{6}小时"
            
            # 一般事项：24小时
            return hours_since >= 24, f"需间隔{24}小时"
        
        # 从未提醒过，检查时间段
        if slot == TimeSlot.MORNING:
            return True, "早晨，适合提醒一天安排"
        elif slot == TimeSlot.WORK:
            return True, "工作时间，适合工作提醒"
        elif slot == TimeSlot.AFTERNOON:
            return True, "下午，适合进度提醒"
        elif slot == TimeSlot.EVENING:
            return True, "晚间，适合一天总结"
        else:
            return False, "当前时段不太适合提醒"
    
    def get_best_time_for(self, action_type: str) -> List[TimeSlot]:
        """
        获取执行某动作的最佳时间段
        """
        best_times = {
            "主动搭话": [TimeSlot.MORNING, TimeSlot.AFTERNOON],
            "闲聊": [TimeSlot.EVENING],
            "工作提醒": [TimeSlot.MORNING, TimeSlot.AFTERNOON],
            "承诺提醒": [TimeSlot.MORNING],
            "复杂分析": [TimeSlot.AFTERNOON],
            "轻松话题": [TimeSlot.EVENING, TimeSlot.LUNCH],
            "紧急提醒": [TimeSlot.WORK, TimeSlot.AFTERNOON],
        }
        
        return best_times.get(action_type, [TimeSlot.AFTERNOON])
    
    def analyze_context(self, 
                       user_emotion: EmotionalState = EmotionalState.UNKNOWN,
                       is_initiated: bool = False) -> Dict:
        """
        综合分析当前情境，返回完整时机判断
        
        Returns:
            包含所有判断的字典
        """
        slot = self.get_time_slot()
        time_rules = self.TIME_RULES[slot]
        emotion_rules = self.EMOTION_RULES[user_emotion]
        
        return {
            "time_slot": slot.value,
            "time_action": time_rules["action"],
            "time_reason": time_rules["reason"],
            "time_allowed": time_rules["allowed"],
            "time_forbidden": time_rules["forbidden"],
            "emotion_style": emotion_rules["response_style"],
            "emotion_engagement": emotion_rules["engagement"],
            "emotion_topics": emotion_rules["topics"],
            "emotion_avoid": emotion_rules["avoid"],
            "is_user_initiated": is_initiated,
            "recommendation": self._generate_recommendation(
                slot, user_emotion, is_initiated
            )
        }
    
    def _generate_recommendation(self, 
                                slot: TimeSlot,
                                emotion: EmotionalState,
                                is_initiated: bool) -> str:
        """生成行动建议"""
        if is_initiated:
            return "用户主动发起，全力以赴完成任务"
        
        if slot == TimeSlot.DEEP_NIGHT:
            return "静默模式，除非紧急"
        
        if emotion == EmotionalState.NEGATIVE:
            return "简洁回复，少说多做"
        
        if slot == TimeSlot.MORNING:
            return "简洁高效，列出要点"
        
        if emotion == EmotionalState.POSITIVE:
            return "可以适当展开，保持热情"
        
        return "正常模式，专业回复"


path: core/wisdom_engine.py
content: """
智慧引擎 (智-Zhi)
举一反三，触类旁通

核心能力：
1. 偏好推理 — 从已知偏好推断新场景
2. 经验复用 — 过去成功/失败经验迁移
3. 模式学习 — 用户拒绝/接受的模式
4. 相似匹配 — 找相似问题及解答
"""

import json
import re
from datetime import datetime
from pathlib import Path
from typing import Optional, Dict, List, Tuple

class WisdomEngine:
    """
    智慧推理引擎
    
    "举一隅不以三隅反，则不复也" — 孔子
    
    真正的智能不只是存储，更是推理和迁移。
    """
    
    def __init__(self, data_dir: Optional[Path] = None):
        if data_dir is None:
            data_dir = Path.home() / ".mflow-memory-cn" / "wisdom"
        self.data_dir = Path(data_dir)
        self.data_dir.mkdir(parents=True, exist_ok=True)
        
        # 经验库：成功/失败案例
        self.experiences_file = self.data_dir / "experiences.jsonl"
        # 偏好库：用户偏好及其来源
        self.preferences_file = self.data_dir / "preferences.jsonl"
        # 拒绝模式库
        self.rejection_patterns_file = self.data_dir / "rejection_patterns.jsonl"
    
    # ========== 核心能力 ==========
    
    def learn_preference(self, user_id: str, 
                        preference: str,
                        source: str,
                        weight: float = 0.8) -> str:
        """
        学习用户偏好
        
        Args:
            user_id: 用户ID
            preference: 偏好描述（如"喜欢简洁界面"）
            source: 来源（如"直接说"、"行为推断"）
            weight: 置信权重（0-1）
            
        Returns:
            preference_id
        """
        pref_data = {
            "id": self._generate_id("pref"),
            "user_id": user_id,
            "preference": preference,
            "source": source,  # "direct" | "inferred" | "observed"
            "weight": weight,
            "examples": [],
            "confirmed_count": 0,
            "contradicted_count": 0,
            "created_at": datetime.now().isoformat(),
            "last_updated": datetime.now().isoformat()
        }
        
        self._append_to_file(self.preferences_file, pref_data)
        return pref_data["id"]
    
    def confirm_preference(self, preference_id: str):
        """确认偏好（用户再次表现出该偏好）"""
        prefs = self._load_all_preferences()
        
        for p in prefs:
            if p["id"] == preference_id:
                p["confirmed_count"] += 1
                p["weight"] = min(1.0, p["weight"] + 0.05)  # 每次确认+0.05
                p["last_updated"] = datetime.now().isoformat()
                break
        
        self._save_all_preferences(prefs)
    
    def contradict_preference(self, preference_id: str):
        """矛盾偏好（用户表现出相反偏好）"""
        prefs = self._load_all_preferences()
        
        for p in prefs:
            if p["id"] == preference_id:
                p["contradicted_count"] += 1
                p["weight"] = max(0.1, p["weight"] - 0.15)  # 每次矛盾-0.15
                p["last_updated"] = datetime.now().isoformat()
                break
        
        self._save_all_preferences(prefs)
    
    def infer_preference(self, user_id: str, 
                        current_request: str) -> List[Dict]:
        """
        推断用户在新场景下的偏好
        
        基于历史偏好，预测当前请求的合适方案
        
        Args:
            user_id: 用户ID
            current_request: 当前请求
            
        Returns:
            推断出的偏好列表（带置信度）
        """
        prefs = self._get_user_preferences(user_id)
        
        # 关键词匹配
        inferred = []
        current_lower = current_request.lower()
        
        for pref in prefs:
            if pref["weight"] < 0.3:
                continue  # 权重太低，不采用
            
            pref_text = pref["preference"].lower()
            
            # 简单关键词匹配
            # "界面"相关
            if any(kw in current_lower for kw in ["界面", "UI", "界面", "设计"]):
                if any(kw in pref_text for kw in ["简洁", "简单", "干净", "花哨", "复杂"]):
                    inferred.append({
                        "preference": pref["preference"],
                        "weight": pref["weight"],
                        "reason": f"基于偏好'{pref['preference']}'推断"
                    })
            
            # "工具"相关
            if any(kw in current_lower for kw in ["工具", "软件", "安装", "配置"]):
                if any(kw in pref_text for kw in ["简单", "免安装", "一键", "复杂", "麻烦"]):
                    inferred.append({
                        "preference": pref["preference"],
                        "weight": pref["weight"],
                        "reason": f"基于偏好'{pref['preference']}'推断"
                    })
            
            # "时间"相关
            if any(kw in current_lower for kw in ["快速", "效率", "慢", "快"]):
                if any(kw in pref_text for kw in ["效率", "快", "慢", "简单"]):
                    inferred.append({
                        "preference": pref["preference"],
                        "weight": pref["weight"],
                        "reason": f"基于偏好'{pref['preference']}'推断"
                    })
        
        # 按权重排序
        inferred.sort(key=lambda x: x["weight"], reverse=True)
        return inferred[:5]  # 返回top5
    
    def record_experience(self, user_id: str,
                         experience_type: str,  # "success" | "failure"
                         situation: str,
                         action: str,
                         outcome: str) -> str:
        """
        记录一次经验
        
        用于未来类似场景的参考
        """
        exp_data = {
            "id": self._generate_id("exp"),
            "user_id": user_id,
            "type": experience_type,
            "situation": situation,  # 什么情况
            "action": action,        # 做了什么
            "outcome": outcome,     # 结果如何
            "use_count": 0,
            "created_at": datetime.now().isoformat()
        }
        
        self._append_to_file(self.experiences_file, exp_data)
        return exp_data["id"]
    
    def find_similar_experiences(self, user_id: str,
                                current_situation: str,
                                limit: int = 3) -> List[Dict]:
        """
        找相似经验
        
        用于类比推理
        """
        experiences = self._get_user_experiences(user_id)
        
        scored = []
        current_lower = current_situation.lower()
        
        for exp in experiences:
            situation = exp.get("situation", "").lower()
            
            # 简单相似度：共同关键词数量
            current_words = set(current_lower.split())
            situation_words = set(situation.split())
            
            common = current_words & situation_words
            if common:
                score = len(common) / max(len(current_words), len(situation_words))
                scored.append((score, exp))
        
        scored.sort(key=lambda x: x[0], reverse=True)
        return [exp for _, exp in scored[:limit]]
    
    def learn_rejection_pattern(self, user_id: str,
                               rejection_text: str,
                               context: Optional[str] = None):
        """
        学习用户的拒绝模式
        
        记录用户拒绝某事时的典型表达，
        用于未来预判和避免
        """
        pattern_data = {
            "id": self._generate_id("rej"),
            "user_id": user_id,
            "rejection_text": rejection_text,
            "context": context,
            "count": 1,
            "created_at": datetime.now().isoformat()
        }
        
        # 检查是否已存在
        patterns = self._load_all_patterns()
        found = False
        for p in patterns:
            if p["user_id"] == user_id and p["rejection_text"] == rejection_text:
                p["count"] += 1
                found = True
                break
        
        if not found:
            patterns.append(pattern_data)
        
        self._save_all_patterns(patterns)
    
    def predict_rejection(self, user_id: str,
                         proposed_action: str) -> Tuple[bool, str]:
        """
        预测用户是否会拒绝某个提议
        
        基于历史拒绝模式
        """
        patterns = self._get_user_patterns(user_id)
        action_lower = proposed_action.lower()
        
        # 检查危险信号
        danger_signals = []
        
        for p in patterns:
            rejection = p["rejection_text"].lower()
            
            # 简单匹配
            if any(word in action_lower for word in rejection.split()[:3]):
                if p["count"] >= 2:  # 至少被拒绝2次
                    danger_signals.append(f"类似表达'{rejection}'被拒绝{p['count']}次")
        
        if danger_signals:
            return True, "; ".join(danger_signals)
        
        return False, "未发现明显拒绝风险"
    
    def get_wisdom_summary(self, user_id: str) -> Dict:
        """
        获取智慧摘要
        
        总结该用户的所有智慧学习成果
        """
        prefs = self._get_user_preferences(user_id)
        experiences = self._get_user_experiences(user_id)
        patterns = self._get_user_patterns(user_id)
        
        # 高权重偏好
        high_weight_prefs = [p for p in prefs if p["weight"] >= 0.6]
        
        # 成功经验
        success_exp = [e for e in experiences if e["type"] == "success"]
        
        # 常见拒绝
        common_rejections = sorted(patterns, key=lambda x: x["count"], reverse=True)[:5]
        
        return {
            "user_id": user_id,
            "total_preferences": len(prefs),
            "high_weight_preferences": high_weight_prefs,
            "total_experiences": len(experiences),
            "success_experiences": success_exp,
            "total_rejection_patterns": len(patterns),
            "common_rejections": common_rejections,
            "summary": self._generate_wisdom_text(user_id, high_weight_prefs, success_exp, common_rejections)
        }
    
    # ========== 私有方法 ==========
    
    def _get_user_preferences(self, user_id: str) -> List[Dict]:
        """获取用户偏好"""
        if not self.preferences_file.exists():
            return []
        
        prefs = []
        with open(self.preferences_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    p = json.loads(line)
                    if p.get("user_id") == user_id:
                        prefs.append(p)
                except:
                    continue
        return prefs
    
    def _get_user_experiences(self, user_id: str) -> List[Dict]:
        """获取用户经验"""
        if not self.experiences_file.exists():
            return []
        
        exps = []
        with open(self.experiences_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    e = json.loads(line)
                    if e.get("user_id") == user_id:
                        exps.append(e)
                except:
                    continue
        return exps
    
    def _get_user_patterns(self, user_id: str) -> List[Dict]:
        """获取用户拒绝模式"""
        patterns = self._load_all_patterns()
        return [p for p in patterns if p.get("user_id") == user_id]
    
    def _load_all_patterns(self) -> List[Dict]:
        """加载所有拒绝模式"""
        if not self.rejection_patterns_file.exists():
            return []
        
        patterns = []
        with open(self.rejection_patterns_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    patterns.append(json.loads(line))
                except:
                    continue
        return patterns
    
    def _save_all_patterns(self, patterns: List[Dict]):
        """保存所有拒绝模式"""
        with open(self.rejection_patterns_file, 'w', encoding='utf-8') as f:
            for p in patterns:
                f.write(json.dumps(p, ensure_ascii=False) + '\n')
    
    def _save_all_preferences(self, prefs: List[Dict]):
        """保存所有偏好"""
        with open(self.preferences_file, 'w', encoding='utf-8') as f:
            for p in prefs:
                f.write(json.dumps(p, ensure_ascii=False) + '\n')
    
    def _append_to_file(self, filepath: Path, data: Dict):
        """追加到文件"""
        with open(filepath, 'a', encoding='utf-8') as f:
            f.write(json.dumps(data, ensure_ascii=False) + '\n')
    
    def _generate_id(self, prefix: str) -> str:
        """生成唯一ID"""
        import uuid
        return f"{prefix}_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:4]}"
    
    def _generate_wisdom_text(self, user_id: str,
                             prefs: List[Dict],
                             successes: List[Dict],
                             rejections: List[Dict]) -> str:
        """生成智慧摘要文本"""
        lines = [f"=== {user_id} 的智慧档案 ==="]
        
        if prefs:
            lines.append("\n【已知偏好】（高权重）：")
            for p in prefs[:5]:
                lines.append(f"  - {p['preference']} (置信度:{p['weight']:.0%})")
        
        if successes:
            lines.append("\n【成功经验】：")
            for e in successes[:3]:
                lines.append(f"  - {e['situation'][:30]}... → {e['outcome'][:30]}...")
        
        if rejections:
            lines.append("\n【避免触发】：")
            for r in rejections:
                lines.append(f"  - 别说\"{r['rejection_text'][:20]}...\"（被拒{r['count']}次）")
        
        return "\n".join(lines)


path: core/__init__.py
content: """
mflow-memory-cn 中式智慧记忆引擎
核心模块
"""

from .memory_store import MemoryStore
from .promise_tracker import PromiseTracker
from .relationship_manager import RelationshipManager
from .timing_sensor import TimingSensor
from .wisdom_engine import WisdomEngine

__all__ = [
    'MemoryStore',
    'PromiseTracker', 
    'RelationshipManager',
    'TimingSensor',
    'WisdomEngine'
]


path: README.md
content: # mflow-memory-cn 中式智慧记忆引擎

> "君子务本，本立而道生。" — 《论语》

基于M-flow知识图谱的长期记忆系统，融合中国人的优秀基因，让AI既有能力，又有情商。

## 五大核心模块

| 模块 | 对应 | 功能 |
|------|------|------|
| MemoryStore | 仁 (Ren) | 以人为本，存储人情而非只存事实 |
| PromiseTracker | 义 (Yi) | 一诺千金，承诺追踪 |
| RelationshipManager | 五伦 | 关系亲密度管理 |
| TimingSensor | 礼 (Li) | 懂分寸，审时度势 |
| WisdomEngine | 智 (Zhi) | 举一反三，触类旁通 |

## 安装

```bash
cd skills
clawhub install mflow-memory-cn
```

## 使用

### Python API

```python
from core.main import ChineseMemoryEngine

# 创建引擎
engine = ChineseMemoryEngine()

# 存储记忆（自动识别情感和承诺）
engine.remember("我不喜欢太复杂的工具", emotion="明确", value="效率优先")

# 检索记忆（举一反三）
results = engine.recall("想要一个简单的工作流工具")

# 承诺追踪
engine.register_promise("周末把报告发我", deadline="本周末")

# 检查承诺状态
status = engine.check_promises()

# 响应前分析（最重要）
analysis = engine.analyze_before_response("有什么工具推荐吗？")
```

### OpenClaw工具

```python
from openclaw_tools import *

# 响应前必调
analysis = analyze_before_response(user_message)

# 存储记忆
remember("用户偏好简洁界面", emotion="明确")

# 承诺追踪
register_promise("明天发报告")
```

## 数据存储

所有数据存储在 `~/.mflow-memory-cn/`:

```
.mflow-memory-cn/
├── data/           # 主记忆文件
├── promises/       # 承诺追踪
├── relationships/  # 关系管理
└── wisdom/         # 智慧引擎
```

## 设计理念

西方技术 + 中国智慧 = 既有能力，又有情商

- **西方**: 知识图谱、向量检索、语义理解
- **中国**: 人情世故、审时度势、举一反三

---

*Created by 马斯克 for JOJO | 2026-04-23*


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)