Skill: long57777/continuous-learning-kit (version 1.1.0)

--- name: continuous-learning description: 持续学习套件 - AI自主记忆管理工作流：自动识别新任务、记录对话到MemPalace、定期做梦分析、提取精华到文档、自我纠错改进。触发词："持续学习"、"记忆管理"、"自我改进"、"学习体系"。 version: 1.0.0 dependencies: - name: mempalace required: true description: 记忆存储系统，用于存储对话碎片和做梦分析 - name: minimax optional: true description: 做梦分析模型（可选，跳过则手动整理） default_model: MiniMax-M2.7 license: MIT author: 小麦 (Xiaomai) --- # 持续学习套件 (Continuous Learning Kit) 让AI具备**持续学习和自我进化**的核心能力。 --- ## 🧠 核心概念 ### 工作流程 ``` 每条消息 → 新任务判断 → 记录到MemPalace → 每日定时做梦 → 提取精华到文档 → 自我改进 ↓ 是否是新任务？ Yes → 读技能文档 → 执行 No → 继续 ``` ### 两大周期 **短期周期**（每次消息）： 1. 新任务判断 2. 自动记录对话到MemPalace **长期周期**（每日定时）： 1. 做梦分析（23:00同步聊天） 2. 精华提取（02:00做梦分析） 3. 文档更新 4. 自我纠错（ERRORS.md/LEARNINGS.md） --- ## 📦 技能包结构 ``` continuous-learning/ ├── SKILL.md # 技能说明（本文件） ├── bootstraps/ │ └── bootstrap_rules.md # 启动规则（整合版BOOTSTRAP） ├── sync/ │ ├── sync_chats_daily.py # 每日同步脚本 │ └── sync_notification.py # 带通知的同步 ├── dream/ │ ├── dream_cycle.py # 做梦分析核心 │ ├── dream_notification.py # 带通知版本 │ └── prompts/ │ ├── analysis_prompt.txt # MiniMax分析提示词 │ └── extraction_rules.md # 提取规则 ├── notifications/ │ ├── notification_queue.json # 通知队列（动态生成） │ └── send_notifications.py # 通知发送 ├── config/ │ ├── dream_config.json # 做梦配置 │ └── documentation_targets.json # 文档目标 └── setup/ ├── install_cron.py # 定时任务安装（跨平台） └── init_learning_files.py # 初始化学习文件 ``` --- ## 🎯 核心特性 ### 1. 新任务智能判断 **判断标准**： - 话题跨度大（从A项目跳到B项目） - 任务类型变（查LIMS → 发邮件） - 关键词第一次出现 - 用户说"新任务"、"开始做..."等 **触发流程**： ```python # 伪代码：新任务判断 if is_new_task(message, context): # 确认后读取： read("SOUL.md") read("AGENTS.md") read("MEMORY.md") read("TOOLS.md") # 读取学习文件 read(".learnings/ERRORS.md") read(".learnings/LEARNINGS.md") # 今日记忆 read(f"memory/{today}.md") read(f"memory/{yesterday}.md") ``` ### 2. MemPalace自动记录 **记录时机**： - 每日23:00定时 - 手动触发 **记录内容**： ``` SESSION:YYYY-MM-DD | 对话摘要 | 用户偏好 | 项目背景 | 重要决策 | 错误教训 ``` **通知机制**： - 同步完成 → WeChat通知 - 做梦完成 → WeChat通知 ### 3. 做梦分析 **执行时间**：每日02:00 **分析流程**： ``` 1. 读取MemPalace所有碎片记忆（N条） 2. MiniMax M2.7分析→ 分类+价值判断+去重 3. 提取精华到5个核心文档： - SOUL.md → 个性、偏好、风格 - AGENTS.md → 工作流程、规则 - MEMORY.md → 用户背景、项目 - TOOLS.md → 配置、坑、技巧 - BOOTSTRAP.md → 启动规则 4. 生成分析报告 5. WeChat通知用户 ``` ### 4. 自我纠错 **错误记录**（ERRORS.md）： ```markdown ### 错误：API字段猜测 **错误**: 猜测LIMS API用sampleBaseUuid获取报告 **正确**: 应该用sampleBaseTestingUuid **教训**: 先查证，不要猜测 **日期**: 2026-04-10 ``` **学习记录**（LEARNINGS.md）： ```markdown ### 学习：握手流程 **收获**: 登录类API必须先GET再POST **应用**: 企业微信、LIMS登录都适用 **日期**: 2026-04-10 ``` --- ## ⚠️ 前置条件（必需） 本技能包**严格依赖MemPalace记忆系统**，使用前必须先安装。 ### 安装MemPalace **方法1：通过ClawHub安装（推荐）** ```bash clawdhub install mempalace ``` **方法2：手动安装** 下载技能包到你的技能目录： ```bash cd skills/mempalace # 确保以下文件存在： # - SKILL.md # - scripts/mcp_server.py # - scripts/call.py ``` ### 验证MemPalace 测试连接： ```bash python skills/mempalace/scripts/call.py mempalace_status ``` 期望输出： ```json { "status": "ready", "drawer_count": 1, "wings": ["你的wing名称"] } ``` 如果返回错误，请检查： 1. ChromaDB是否已安装：`pip install chromadb` 2. 数据库路径是否有写入权限 --- ## 🚀 快速开始 ### 步骤1：初始化学习文件 ```bash python setup/init_learning_files.py ``` 创建： - `.learnings/ERRORS.md` - `.learnings/LEARNINGS.md` - `.learnings/FEATURES.md` - `memory/YYYY-MM-DD.md` ### 步骤2：配置文档目标 编辑 `config/documentation_targets.json`: ```json { "SOUL": { "path": "SOUL.md", "purpose": "行为准则、个性偏好、沟通风格" }, "AGENTS": { "path": "AGENTS.md", "purpose": "工作流程、代理规则、交互模式" }, "MEMORY": { "path": "MEMORY.md", "purpose": "用户偏好、项目背景、长期记忆" }, "TOOLS": { "path": "TOOLS.md", "purpose": "工具配置、集成注意事项、坑" }, "BOOTSTRAP": { "path": "BOOTSTRAP.md", "purpose": "会话启动规则、新任务判断" } } ``` ### 步骤3：安装定时任务 **所有平台（Windows/Linux/Mac）**: ```bash python setup/install_cron.py ``` **Windows用户注意**： - 如果提示权限问题，以管理员身份运行PowerShell/CMD - 脚本会自动检测操作系统并配置相应的定时任务 ### 步骤4：配置MiniMax API（可选） 编辑 `config/dream_config.json`: ```json { "analysis_model": { "provider": "minimax", "model": "MiniMax-M2.7", "api_url": "https://api.minimax.chat/v1", "api_key": "your_api_key_here" } } ``` **注意**：如果不配置，会跳过大模型分析，只做基础分类。 --- ## 📋 使用场景 ### 场景1：多项目并行工作 用户： ``` 查一下LIMS样本SDAA25D03362的报告 帮我做康鑫达周报 写一个Python脚本处理Excel ``` **技能行为**： 1. 第1条 → 检测到"LIMS"关键词 → 判断为新任务 2. 读取AGENTS.md → 知道LIMS地址和账号 3. 执行查询 → 记录结果到MemPalace 4. 第2条 → 检测到"康鑫达周报" → 新任务 5. 读取WORKFLOW.md → 调用周报生成脚本 ### 场景2：持续优化技能 **第1天**： - 执行任务A - 失败 → 记录到ERRORS.md **第23:00**： - 同步今日对话到MemPalace **第02:00**： - 做梦分析 → 发现失败模式 - 提取教训到LEARNINGS.md - 找到原因："API猜测" **第3天**： - 类似任务B出现 - 读取LEARNINGS.md - **避免**API猜测 → 成功！ ### 场景3：用户偏好记忆 **用户说**："叫我xiaolong，不要叫刘总" **技能行为**： 1. 记录到MemPalace 2. 做梦分析 3. 提取到SOUL.md：称呼偏好 4. 后续所有对话 → 直接用"xiaolong" --- ## 📊 配置选项 ### 做梦配置 (`config/dream_config.json`) ```json { "sync_schedule": "23:00", "dream_schedule": "02:00", "notification_enabled": true, "notification_channel": "openclaw-weixin", "doc_update_rules": { "min_similarity": 0.7, "max_noise_ratio": 0.5 } } ``` ### 分析模型配置 支持多个模型： - **MiniMax M2.7**（默认，效果最好） - **智谱GLM-4.7** - **Claude 3.5 Sonnet** - **GPT-4o** --- ## 🔧 故障排查 ### 问题1：定时任务不执行 **Windows**： ```powershell schtasks /query /tn "OpenClaw-SyncWeChat" schtasks /query /tn "OpenClaw-DreamCycle" ``` 检查状态是否为"就绪"。 **Linux**： ```bash crontab -l | grep openclaw ``` ### 问题2：MemPalace写入失败 检查： 1. ChromaDB路径是否正确 2. 写入权限是否足够 3. 数据库大小（超过5GB需清理） ### 问题3：做梦分析卡住 检查： 1. API Key是否有效 2. 网络连接 3. 记忆条目数（超过1000条需分批） --- ## 📈 进阶用法 ### 自定义文档目标 添加自己的文档： ```json { "PROJECT_NOTES": { "path": "docs/project_notes.md", "purpose": "项目特定笔记" }, "API_REFERENCE": { "path": "docs/api_reference.md", "purpose": "API调用记录" } } ``` ### 自定义分析提示词 编辑 `dream/prompts/analysis_prompt.txt`，改变分析规则。 ### 多Agent协同 多个AI共享MemPalace： ```json { "shared_agents": ["agent_A", "agent_B"], "sync_interval": "hourly" } ``` --- ## 🤝 依赖技能 ### 必需 - **mempalace** - 记忆存储系统 ### 可选 - **minimax-image-understanding** - 图像记忆 - **self-improving-agent** - 互补的自我改进功能 --- ## 📝 版本历史 ### v1.0.0 (2026-04-19) - ✅ 新任务智能判断 - ✅ MemPalace自动记录 - ✅ 做梦分析（MiniMax M2.7） - ✅ 5文档自动更新 - ✅ WeChat通知 - ✅ 自我纠错（ERRORS/LEARNINGS） --- ## 🌟 核心价值 这个技能包让AI从"一次性工具"进化为"**持续学习的智能体**"： | 维度 | 传统AI | 持续学习AI | |------|--------|-----------| | 记忆 | 每次对话重新开始 | 跨会话持久记忆 | | 学习 | 需要人工提示 | 自动提取规律 | | 纠错 | 重复犯同样错误 | 从错误中学习 | | 偏好 | 不知道用户喜好 | 记住用户习惯 | | 进化 | 能力固定 | 持续自我提升 | --- **技能作者**: 小麦 (Xiaomai) 🌾 **许可证**: MIT **反馈**: OpenClaw社区 Discord

path: bootstraps/bootstrap_rules.md
content: # 启动规则 - 持续学习套件

*整合版：新会话/新任务的标准启动流程*

---

## 铁律：判断 → 确认 → 读取 → 执行

### 1️⃣ 判断是否是新任务

**判断标准**：
- 话题跨度大（从A项目跳到B项目）
- 任务类型变（查LIMS → 发邮件）
- 关键词第一次出现
- 用户说"新任务"、"开始做..."
- 任何不确定的情况

### 2️⃣ 确认

- ✅ 明确是新任务 → 直接执行
- ❓ 不确定 → 问用户确认
- ❌ 禁止跳步

### 3️⃣ 读取

按以下顺序读取：

**核心文档**（每次都读）：
1. `SOUL.md` — 我是谁、个性偏好
2. `AGENTS.md` — 工作流程、规则
3. `MEMORY.md` — 用户背景、长期记忆
4. `TOOLS.md` — 工具配置、坑、技巧

**学习文件**（避免重复错误）：
5. `.learnings/ERRORS.md` — 历史错误教训
6. `.learnings/LEARNINGS.md` — 学习成果

**近期记忆**（上下文）：
7. `memory/YYYY-MM-DD.md` — 今日记忆
8. `memory/YYYY-MM-DD.md` — 昨日记忆

**相关技能**（仅当需要时）：
9. `skills/<技能名>/SKILL.md` — 特定技能使用方法

### 4️⃣ 执行

- 严格按照读取的规则执行
- 犯错立即记入 `.learnings/ERRORS.md`
- 被纠正立即记入 `.learnings/LEARNINGS.md`

---

## 🔄 记忆管理周期

### 短期周期（每次对话）

```
用户消息 → 新任务判断 → 记录到MemPalace → 继续对话
                      ↓
          SESSION:YYYY-MM-DD HH:MM对话摘要
```

### 长期周期（每日定时）

```
23:00 → 同步今日聊天到MemPalace → WeChat通知
02:00 → 做梦分析（MiniMax） → 提取精华到5文档 → WeChat通知
```

---

## 📋 配置清单

### 必须配置的文件

- [x] `SOUL.md` - 你的个性
- [x] `AGENTS.md` - 工作流程
- [x] `MEMORY.md` - 长期记忆
- [x] `TOOLS.md` - 工具配置
- [x] `BOOTSTRAP.md` - 启动规则（本文件）
- [x] `.learnings/ERRORS.md` - 错误教训
- [x] `.learnings/LEARNINGS.md` - 学习成果
- [x] `.learnings/FEATURES.md` - 功能需求

### 定时任务配置

- [ ] `23:00` - 同步聊天（`sync/sync_notification.py`）
- [ ] `02:00` - 做梦分析（`dream/dream_notification.py`）

### API配置

- [ ] MiniMax API Key（做大模型分析）
- [ ] MemPalace路径配置
- [ ] 通知渠道配置

---

## 🚨 常见陷阱

### 陷阱1：凭记忆执行

**错误**：直接根据上次记忆执行
**正确**：每次新任务必须先读相关文档

### 陷阱2：猜测字段名

**错误**：猜测API字段名
**正确**：先验证，再使用

### 陷阱3：忽略错误

**错误**：错误后不记录
**正确**：立即记入ERRORS.md，避免重复

### 陷阱4：跳过确认

**错误**：不确定时直接执行
**正确**：先问用户确认

---

## 📊 效果评估

### 持续学习的指标

| 指标 | 说明 | 目标 |
|------|------|------|
| 错误重犯率 | 同样错误再次发生 | <10% |
| 学习条目数 | LEARNINGS.md条目增加 | >100/月 |
| 文档更新频 | 5文档每周更新 | ≈7次 |
| 用户满意度 | 用户反馈持续改进 | >90% |

### 检查时机

- 每次做梦时自动分析
- 每月人工审查ERRORS.md
- 每季度评估学习效果

---

## 🎯 最佳实践

### 实践1：结构化记录

`ERRORS.md`格式：
```markdown
### 错误：[简短描述]
**错误**: [具体错误内容]
**正确**: [正确做法]
**教训**: [避免方法]
**日期**: YYYY-MM-DD
```

`LEARNINGS.md`格式：
```markdown
### 学习：[主题]
**收获**: [学到的内容]
**应用**: [应用场景]
**日期**: YYYY-MM-DD
```

### 实践2：定期清理

- 每30天清理ERRORS.md中已解决的问题
- 将长期有效的迁移到MEMORY.md
- 保留最有价值的学习条目

### 实践3：主动应用

- 每次执行任务前 → 速览ERRORS.md
- 每次新任务开始 → 速览LEARNINGS.md
- 每周做梦后 → 检查5文档更新

---

## 🔧 故障排查

### 问题：定时任务不执行

**检查**：
- 任务计划程序（Windows）或cron（Linux）
- Python路径是否正确
- 脚本是否有执行权限

### 问题：MemPalace写入失败

**检查**：
- 数据库路径
- 写入权限
- 日志文件输出

### 问题：做梦无更新

**检查**：
- 记忆碎片数量
- API Key有效性
- 提示词配置

---

**更新版本**: 1.0.0
**最后更新**: 2026-04-19
**维护者**: 小麦 (Xiaomai) 🌾


path: config/documentation_targets.json
content: {
  "SOUL": {
    "path": "SOUL.md",
    "purpose": "行为准则、个性偏好、沟通风格"
  },
  "AGENTS": {
    "path": "AGENTS.md",
    "purpose": "工作流程、代理规则、交互模式"
  },
  "MEMORY": {
    "path": "MEMORY.md",
    "purpose": "用户偏好、项目背景、长期记忆"
  },
  "TOOLS": {
    "path": "TOOLS.md",
    "purpose": "工具配置、集成注意事项、坑"
  },
  "BOOTSTRAP": {
    "path": "BOOTSTRAP.md",
    "purpose": "会话启动规则、新任务判断"
  }
}


path: config/dream_config.json
content: {
  "version": "1.0.0",
  "sync_schedule": "23:00",
  "dream_schedule": "02:00",
  "timezone": "Asia/Shanghai",
  "notification": {
    "enabled": true,
    "channel": "openclaw-weixin",
    "to": "[REDACTED_SECRET]",
    "queue_file": ".notification_queue.json"
  },
  "mempalace": {
    "db_path": null,
    "collection_name": "mempalace_drawers",
    "entries_limit": 1000
  },
  "analysis": {
    "model": "minimax",
    "model_name": "MiniMax-M2.7",
    "api_url": "https://api.minimax.chat/v1",
    "api_key": "your_minimax_api_key_here",
    "timeout_seconds": 120,
    "temperature": 0.3
  },
  "doc_update": {
    "min_similarity": 0.7,
    "max_noise_ratio": 0.5,
    "auto_merge_duplicates": true
  },
  "learning_files": {
    "errors": ".learnings/ERRORS.md",
    "learnings": ".learnings/LEARNINGS.md",
    "features": ".learnings/FEATURES.md"
  }
}


path: dream/dream_cycle.py
content: # -*- coding: utf-8 -*-
"""
做梦脚本 - 调用MiniMax M2.7分析MemPalace记忆碎片，提炼精华到当下文档

运行时间：每天凌晨2:00
使用模型：MiniMax M2.7
API：openai-compat

作者：小麦
日期：2026-04-10
版本：v5 (带通知)
"""
import sys
import os
import json
from datetime import datetime
import traceback
from pathlib import Path
import requests

# 设置UTF-8输出
if sys.platform == 'win32':
    import codecs
    sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')
    sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, 'strict')

WORKSPACE = 'C:/Users/18625/.openclaw/workspace'

# 加载配置
CONFIG_FILE = os.path.join(WORKSPACE, 'skills/continuous-learning/config/dream_config.json')

def load_config():
    """加载配置文件"""
    default_config = {
        'baseUrl': 'https://api.minimax.chat/v1',
        'apiKey': '',  # 用户通过配置文件设置
        'model': 'MiniMax-M2.7',
        'notification': {
            'enabled': True,
            'channel': 'openclaw-weixin',
            'queue_file': '.notification_queue.json'
        }
    }

    try:
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            user_config = json.load(f)
            default_config.update(user_config)
    except:
        pass

    return default_config

MINIMAX_CONFIG = load_config()

# 目标文档
TARGET_DOCS = {
    'SOUL': {
        'path': os.path.join(WORKSPACE, 'SOUL.md'),
        'purpose': '行为准则、个性偏好、沟通风格'
    },
    'AGENTS': {
        'path': os.path.join(WORKSPACE, 'AGENTS.md'),
        'purpose': '工作流程、代理规则、交互模式'
    },
    'MEMORY': {
        'path': os.path.join(WORKSPACE, 'MEMORY.md'),
        'purpose': '用户偏好、项目背景、长期记忆'
    },
    'TOOLS': {
        'path': os.path.join(WORKSPACE, 'TOOLS.md'),
        'purpose': '工具配置、集成注意事项、坑'
    },
    'BOOTSTRAP': {
        'path': os.path.join(WORKSPACE, 'BOOTSTRAP.md'),
        'purpose': '会话启动规则、预检清单'
    }
}

# 分析提示词
ANALYSIS_PROMPT = """## 做梦任务 - 分析MemPalace记忆碎片

我是小麦，需要在每天凌晨2:00将记忆宫殿中的碎片记忆整理到我的当下文档中。

### 我的当下文档结构
{doc_descriptions}

### 记忆碎片
以下是MemPalace中的日记条目({count}条)：
{entries_text}

### 分析要求

你现在需要完成以下任务：

1. **分类判断**：每个碎片应该归纳到哪个文档（SOUL/AGENTS/MEMORY/TOOLS/BOOTSTRAP）？

2. **价值判断**：这个碎片有无价值？请过滤掉：
   - 错误记录、异常堆栈
   - 临时测试、调试信息
   - 无意义的流水账
   - 重复的内容

3. **去重检查**：检查碎片是否与现有内容重复

4. **提炼精简**：将碎片提炼成简洁的条目

### 输出格式（严格JSON，不要有其他内容）

```json
{{
  "summary": "本次分析总结",
  "stats": {{
    "total_entries": 总条目数,
    "processed": 处理数,
    "valuable": 有价值数,
    "duplicates": 重复数,
    "noise": 噪音数
  }},
  "updates": [
    {{
      "doc": "SOUL",
      "reason": "这个碎片之所以应该记录到SOUL是因为...",
      "content": "提炼后的内容..."
    }}
  ]
}}
```

请开始分析，只返回上述JSON格式，不要有任何额外说明。"""

def queue_notification(message):
    """将通知存入队列"""
    try:
        # 从配置获取
        notification_config = MINIMAX_CONFIG.get('notification', {})
        queue_file = notification_config.get('queue_file', '.notification_queue.json')
        to_user = notification_config.get('to', '')  # 从配置设置

        if not to_user:
            # 默认：尝试从之前的配置读取或留空
            to_user = ''

        queue_path = os.path.join(WORKSPACE, queue_file)
        queue_dir = os.path.dirname(queue_path)
        os.makedirs(queue_dir, exist_ok=True)

        notifications = []

        if os.path.exists(queue_path):
            with open(queue_path, 'r', encoding='utf-8') as f:
                notifications = json.load(f)

        notification_item = {
            'message': message,
            'timestamp': datetime.now().isoformat()
        }

        if to_user:
            notification_item['to'] = to_user

        notifications.append(notification_item)

        with open(queue_path, 'w', encoding='utf-8') as f:
            json.dump(notifications, f, ensure_ascii=False, indent=2)

        print(f"[通知] 已加入发送队列")
        return True
    except Exception as e:
        print(f"[通知] 队列写入失败: {e}")
        return False

def read_mempalace_entries():
    """从MemPalace读取所有日记条目"""
    try:
        from chromadb import PersistentClient

        client = PersistentClient(path="C:/Users/18625/.mempalace/palace")
        collection = client.get_or_create_collection("mempalace_drawers")

        results = collection.get(include=["documents", "metadatas"])

        entries = []
        for doc, meta in zip(results['documents'], results['metadatas']):
            if meta.get('type') == 'diary_entry' or 'diary' in str(meta).lower():
                entries.append({
                    'document': doc,
                    'metadata': meta
                })

        return {
            'status': 'success',
            'entries': entries,
            'total': len(entries)
        }

    except Exception as e:
        return {
            'status': 'error',
            'error': str(e),
            'traceback': traceback.format_exc()
        }

def call_minimax_analysis(entries):
    """调用MiniMax M2.7分析记忆碎片"""
    try:
        # 构造entries文本
        entries_text = []
        for i, entry in enumerate(entries, 1):
            entries_text.append(f"条目{i}: {entry['document']}")
            if entry.get('metadata'):
                entries_text.append(f"  元数据: {json.dumps(entry['metadata'], ensure_ascii=False)}")

        # 构造文档描述
        doc_descriptions = json.dumps(TARGET_DOCS, indent=2, ensure_ascii=False)

        # 构造完整提示词
        user_prompt = ANALYSIS_PROMPT.format(
            doc_descriptions=doc_descriptions,
            count=len(entries),
            entries_text='\n'.join(entries_text)
        )

        # 调用MiniMax API（OpenAI兼容）
        url = f"{MINIMAX_CONFIG['baseUrl']}/chat/completions"

        headers = {
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {MINIMAX_CONFIG["apiKey"]}'
        }

        payload = {
            'model': MINIMAX_CONFIG['model'],
            'messages': [
                {
                    'role': 'system',
                    'content': '你是一个专业的记忆分析师，擅长整理和提炼信息，只输出严格的JSON格式。'
                },
                {
                    'role': 'user',
                    'content': user_prompt
                }
            ],
            'temperature': 0.3
        }

        response = requests.post(url, headers=headers, json=payload, timeout=120)

        if response.status_code == 200:
            result = response.json()
            content = result['choices'][0]['message']['content']

            # 提取JSON
            import re
            json_match = re.search(r'```json\s*\n({[\s\S]*?})\s*```', content) or re.search(r'({[\s\S]*?})', content)

            if json_match:
                parsed_result = json.loads(json_match.group(1))
                return {
                    'status': 'success',
                    'result': parsed_result
                }
            else:
                return {
                    'status': 'error',
                    'error': '无法从响应中提取JSON',
                    'raw_response': content
                }
        else:
            return {
                'status': 'error',
                'error': f"MiniMax API错误: {response.status_code}",
                'response': response.text
            }

    except requests.exceptions.Timeout:
        return {
            'status': 'error',
            'error': 'API请求超时'
        }
    except Exception as e:
        return {
            'status': 'error',
            'error': str(e),
            'traceback': traceback.format_exc()
        }

def check_duplicate(doc_path, content):
    """检查内容是否已存在于文档中"""
    if not os.path.exists(doc_path):
        return False

    try:
        with open(doc_path, 'r', encoding='utf-8') as f:
            existing_content = f.read()

        # 简单关键词检查
        core_words = content.replace('\n', ' ').split()
        for word in core_words:
            if len(word) > 4 and word in existing_content:
                return True

        return False

    except Exception:
        return False

def safe_append(doc_path, reason, content):
    """安全追加内容到文档"""
    try:
        if not os.path.exists(doc_path):
            print(f"[WARNING] 文档不存在，创建: {doc_path}")
            with open(doc_path, 'w', encoding='utf-8') as f:
                f.write(f"# {os.path.basename(doc_path)}\n\n")

        # 去重检查
        if check_duplicate(doc_path, content):
            print(f"[SKIP] 跳过重复内容: {content[:50]}...")
            return {'status': 'duplicate', 'doc': doc_path}

        # 追加内容
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M')
        new_entry = f"""

## 记忆更新 - {timestamp}

**来源**: 记忆宫殿分析
**推理**: {reason}

{content}

---
"""

        with open(doc_path, 'a', encoding='utf-8') as f:
            f.write(new_entry)

        print(f"[OK] 追加到 {os.path.basename(doc_path)}: {content[:50]}...")
        return {'status': 'success', 'doc': doc_path}

    except Exception as e:
        return {
            'status': 'error',
            'doc': doc_path,
            'error': str(e),
            'traceback': traceback.format_exc()
        }

def apply_updates(updates):
    """应用更新到对应的文档"""
    results = []

    for update in updates:
        doc_name = update.get('doc')
        reason = update.get('reason', '')
        content = update.get('content', '')

        if doc_name not in TARGET_DOCS:
            print(f"[ERROR] 警告: 未知文档 {doc_name}")
            results.append({
                'status': 'error',
                'error': f'未知文档: {doc_name}'
            })
            continue

        doc_path = TARGET_DOCS[doc_name]['path']
        result = safe_append(doc_path, reason, content)
        results.append(result)

    return results

def run_dream_cycle():
    """执行一个做梦周期"""
    start_time = datetime.now()
    print(f"\n{'='*60}")
    print(f"[DREAM] 做梦开始于 {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
    print(f"{'='*60}\n")

    # 1. 读取MemPalace记忆碎片
    print("[STEP 1] 读取MemPalace记忆碎片...")
    entries_result = read_mempalace_entries()

    if entries_result['status'] == 'error':
        print(f"[ERROR] 错误: {entries_result['error']}")

        # 发送错误通知
        error_msg = f"""❌ 做梦失败

阶段: 读取MemPalace
错误: {entries_result.get('error', '未知错误')}
🕒 时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
        queue_notification(error_msg)

        return entries_result

    entries = entries_result.get('entries', [])
    print(f"[OK] 读取了 {len(entries)} 条碎片\n")

    if not entries:
        print("[SKIP] 没有记忆碎片，跳过本次做梦")

        # 发送跳过通知
        skip_msg = f"""⏭️ 做梦跳过

原因: 无记忆碎片
🕒 时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
        queue_notification(skip_msg)

        return {'status': 'skipped', 'reason': 'no_entries'}

    # 2. 调用MiniMax分析
    print("[STEP 2] 调用MiniMax M2.7分析记忆碎片...")
    print(f"[INFO] 等待大模型分析...（可能需要几十秒）\n")
    analysis = call_minimax_analysis(entries)

    if analysis['status'] == 'error':
        print(f"[ERROR] 分析失败: {analysis['error']}")

        # 发送错误通知
        error_msg = f"""❌ 做梦失败

阶段: 分析记忆碎片
错误: {analysis.get('error', '未知错误')}
🕒 时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
        queue_notification(error_msg)

        return analysis

    result = analysis['result']
    stats = result.get('stats', {})
    updates = result.get('updates', [])

    print(f"[OK] 分析完成")
    print(f"  处理: {stats.get('processed')}/{stats.get('total_entries')}")
    print(f"  有价值: {stats.get('valuable')}")
    print(f"  重复: {stats.get('duplicates')}")
    print(f"  噪音: {stats.get('noise')}\n")

    # 3. 应用更新
    print(f"[STEP 3] 应用更新到文档...")
    print(f"[INFO] 共 {len(updates)} 条更新准备写入\n")

    results = apply_updates(updates)

    success_count = sum(1 for r in results if r.get('status') == 'success')
    duplicate_count = sum(1 for r in results if r.get('status') == 'duplicate')
    error_count = sum(1 for r in results if r.get('status') == 'error')

    print(f"\n[RESULT] 应用结果:")
    print(f"  成功: {success_count}")
    print(f"  跳过（重复）: {duplicate_count}")
    print(f"  失败: {error_count}\n")

    # 4. 汇总
    end_time = datetime.now()
    duration = (end_time - start_time).total_seconds()

    print(f"\n{'='*60}")
    print(f"[DREAM] 做梦完成于 {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
    print(f"[TIME] 耗时: {duration:.2f}秒")
    print(f"{'='*60}\n")

    # 发送完成通知
    success_msg = f"""🌙 做梦完成！

📊 分析结果:
  • 处理: {stats.get('processed')}/{stats.get('total_entries')} 条
  • 有价值: {stats.get('valuable')} 条
  • 去重: {stats.get('duplicates')} 条
  • 噪音: {stats.get('noise')} 条

📝 文档更新:
  • 成功: {success_count} 条
  • 跳过: {duplicate_count} 条
  • 失败: {error_count} 条

⏱️ 耗时: {duration:.2f}秒
🕒 时间: {end_time.strftime('%Y-%m-%d %H:%M:%S')}
"""

    queue_notification(success_msg)

    return {
        'status': 'completed',
        'duration': duration,
        'stats': stats,
        'results': results
    }

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description='Dream Cycle v5 - MiniMax M2.7 with Notifications')
    parser.add_argument('--test', action='store_true', help='Test mode (no analysis)')
    args = parser.parse_args()

    if args.test:
        print("[TEST MODE] 只读取，不调用大模型\n")
        result = read_mempalace_entries()

        if result['status'] == 'success':
            print(f"[OK] 找到 {result['total']} 条碎片")
            if result['entries']:
                print("\n前3条:")
                for i, entry in enumerate(result['entries'][:3], 1):
                    print(f"{i}. {entry['document'][:100]}...")
                    print(f"   Meta: {entry.get('metadata', {})}")
        else:
            print(f"[ERROR] {result.get('error')}")
            if result.get('traceback'):
                print(result['traceback'])
    else:
        result = run_dream_cycle()
        print("\n[SUMMARY] 做梦汇报:")
        print(json.dumps(result, indent=2, ensure_ascii=False))


path: README.md
content: # 持续学习套件
## Continuous Learning Kit

让OpenClaw AI助手具备**持续学习和自我进化**的核心能力。

---

## 🌟 核心特性

### 1. 智能新任务判断
- 自动识别话题切换
- 任务类型变化检测
- 关键词追踪

### 2. MemPalace自动记录
- 每日对话自动归档
- 语义化记忆存储
- 跨会话上下文保持

### 3. 做梦分析（02:00）
- MiniMax M2.7智能分析
- 自动去重降噪
- 精华提取到5个核心文档

### 4. 自我纠错机制
- ERROR/LEARNING记录
- 避免重复错误
- 持续改进

---

## ⚠️ 前置条件（必需）

本技能包**依赖MemPalace记忆系统**，使用前必须先安装。

### 安装MemPalace

通过ClawHub安装：

```bash
clawdhub install mempalace
```

或者手动克隆技能包到你的技能目录：

```bash
cd skills/mempalace
# 确保有以下文件：
# - SKILL.md
# - scripts/mcp_server.py
# - scripts/call.py
```

### 验证MemPalace

测试连接：
```bash
python skills/mempalace/scripts/call.py mempalace_status
```

如果返回类似：
```json
{
  "status": "ready",
  "drawer_count": 1,
  "wings": ["wing_xiaolong"]
}
```

则说明安装成功。

---

## 🚀 快速开始

### 5分钟快速安装

#### 1️⃣ 初始化文件

```bash
cd <你的工作区>
python skills/continuous-learning/setup/init_learning_files.py
```

#### 2️⃣ 配置（可选）

编辑 `skills/continuous-learning/config/dream_config.json`，添加你的MiniMax API Key：

```json
{
  "analysis": {
    "model": "minimax",
    "api_key": "your_minimax_api_key_here"
  }
}
```

#### 3️⃣ 安装定时任务

**所有平台（Windows/Linux/Mac）**:
```bash
python skills/continuous-learning/setup/install_cron.py
```

**Windows用户注意**：
- 如果提示权限问题，以管理员身份运行PowerShell/CMD
- 脚本会自动检测操作系统并配置相应的定时任务

#### 4️⃣ 测试

```bash
# 测试同步
python skills\continuous-learning\sync\sync_notification.py

# 测试做梦
python skills\continuous-learning\dream\dream_cycle.py
```

---

## 📊 工作流程

```
用户消息
    ↓
新任务判断
    ↓ Yes
读取文档（SOUL/AGENTS/MEMORY/TOOLS/ERRORS/LEARNINGS）
    ↓
执行任务
    ↓
记录到MemPalace
    ↓
23:00 自动同步今日聊天
    ↓
02:00 做梦分析 → 提取精华到文档 → WeChat通知
```

---

## 📁 技能包结构

```
continuous-learning/
├── SKILL.md                        # 技能说明
├── README.md                       # 本文件
├── config/
│   ├── dream_config.json          # 做梦配置
│   └── documentation_targets.json # 文档目标
├── bootstraps/
│   └── bootstrap_rules.md         # 启动规则（会话启动时自动加载）
├── sync/
│   └── sync_notification.py       # 同步脚本（23:00）
├── dream/
│   └── dream_cycle.py             # 做梦脚本（02:00）
├── notifications/
│   └── .notification_queue.json   # 通知队列（自动生成）
└── setup/
    ├── init_learning_files.py     # 初始化学习文件
    └── install_cron.py            # 定时任务安装（跨平台）
```

---

## 🎯 使用场景

### 场景1：多项目管理

```
用户：查LIMS样本 → 做周报 → 发邮件
     ↓
AI自动识别3个不同任务
     ↓
每次都重新读取相关配置
     ↓
无缝切换，不混乱
```

### 场景2：避免重复错误

```
第1天：犯错 → 记录ERRRORS.md
第23:00：同步
第02:00：做梦分析
第3天：类似任务 → 读取LEARNINGS.md → 避免错误！
```

### 场景3：用户偏好记忆

```
第一次：用户说"叫我xiaolong"
     ↓
记录到MemPalace
     ↓
做梦分析 → 提取到SOUL.md
     ↓
后续所有对话 → 自动用"xiaolong"
```

---

## 🔧 配置说明

### dream_config.json

```json
{
  "sync_schedule": "23:00",              // 同步时间
  "dream_schedule": "02:00",             // 做梦时间
  "notification": {
    "enabled": true,                     // 启用通知
    "channel": "openclaw-weixin"         // 通知渠道
  },
  "analysis": {
    "model": "minimax",                  // 分析模型
    "timeout_seconds": 120               // 超时时间
  }
}
```

### 通知配置

支持的通知渠道：
- `openclaw-weixin` - 企业微信
- `email` - 邮件
- `None` - 不通知

---

## 📈 效果指标

| 指标 | 传统AI | 持续学习AI |
|------|--------|-----------|
| 记忆持久 | 无 | 跨会话 |
| 错误重犯 | 高 | <10% |
| 学习能力 | 无 | 自动 |
| 用户偏好 | 不知道 | 自动记忆 |

---

## 🐛 故障排查

### 定时任务不执行

**Windows**:
```powershell
schtasks /query /tn "OpenClaw-ContinuousSync"
```

**Linux**:
```bash
crontab -l
```

### MemPalace写入失败

检查：
- ChromaDB路径
- 写入权限
- 日志文件

### 做梦无更新

检查：
- API Key有效性
- 记忆碎片数量
- 提示词配置

---

## 📚 相关技能

- **mempalace** - 记忆 palace（必需）
- **self-improving-agent** - 互补的自我改进功能

---

## 📝 格式示例

### ERRORS.md

```markdown
### 错误：API字段猜测
**错误**: 猜测用 sampleBaseUuid
**正确**: 应该用 sampleBaseTestingUuid
**教训**: 先验证，不要猜测
**日期**: 2026-04-10
```

### LEARNINGS.md

```markdown
### 学习：登录握手
**收获**: 先GET再POST
**应用**: LIMS登录、企业微信认证
**日期**: 2026-04-10
```

---

## 🤝 贡献

欢迎提交PR和Issue！

---

**版本**: 1.0.0
**作者**: 小麦 (Xiaomai) 🌾
**许可证**: MIT
**维护**: OpenClaw社区 Discord


path: requirements.txt
content: # 持续学习套件 - Python依赖

# 核心依赖
chromadb>=0.4.0          # MemPalace存储
requests>=2.28.0         # HTTP请求

# 可选：大模型分析
openai>=1.0.0            # OpenAI兼容API（用于MiniMax）

# 开发依赖（可选）
pytest>=7.0.0            # 测试
black>=23.0.0            # 代码格式化


path: setup/init_learning_files.py
content: # -*- coding: utf-8 -*-
"""
持续学习套件 - 初始化脚本

创建必要的学习文件和目录结构
"""
import sys
import os
from pathlib import Path
from datetime import datetime

sys.stdout.reconfigure(encoding='utf-8', errors='replace')

WORKSPACE = Path.cwd()


def create_file(filepath, content=None):
    """创建文件"""
    filepath.parent.mkdir(parents=True, exist_ok=True)
    with open(filepath, 'w', encoding='utf-8') as f:
        if content:
            f.write(content)
    print(f"✅ {filepath}")


def main():
    print("\n持续学习套件 - 初始化")
    print("=" * 60)

    # 创建学习文件目录
    learnings_dir = WORKSPACE / ".learnings"
    learnings_dir.mkdir(exist_ok=True)

    # 创建ERRORS.md
    create_file(
        learnings_dir / "ERRORS.md",
        """# 错误教训记录

> 每次犯错立即记录，避免重复

---

## 格式

### 错误：[简短描述]
**错误**: [具体错误内容]
**正确**: [正确做法]
**教训**: [避免方法]
**日期**: YYYY-MM-DD

---

## 示例

### 错误：LIMS报告下载字段错误
**错误**: 猜测LIMS API用`sampleBaseUuid`获取报告
**正确**: 应该用`sampleBaseTestingUuid`
**教训**: API字段名必须查证，不能猜测；先验证再使用
**日期**: 2026-04-10
"""
    )

    # 创建LEARNINGS.md
    create_file(
        learnings_dir / "LEARNINGS.md",
        """# 学习成果记录

> 从错误和被纠正中获得的知识

---

## 格式

### 学习：[主题]
**收获**: [学到的内容]
**应用**: [应用场景]
**日期**: YYYY-MM-DD

---

## 示例

### 学习：登录类API握手流程
**收获**: 必须先GET再POST，不能直接POST
**应用**: LIMS登录、企业微信认证
**日期**: 2026-04-10
"""
    )

    # 创建FEATURES.md
    create_file(
        learnings_dir / "FEATURES.md",
        """# 功能需求和改进建议

> 用户提出的功能需求、todo项

---

## 格式

### [功能名称]
**需求**: [详细描述]
**状态**: pending/doing/done
**优先级**: high/medium/low
**日期**: YYYY-MM-DD

---

## 示例

### 植物大战僵尸游戏
**需求**: 在手机上创建可直接运行的植物大战僵尸游戏
**状态**: pending
**优先级**: low
**日期**: 2026-04-10
"""
    )

    # 创建memory目录
    memory_dir = WORKSPACE / "memory"
    memory_dir.mkdir(exist_ok=True)

    # 创建今日记忆文件
    today = datetime.now().strftime('%Y-%m-%d')
    today_memory = memory_dir / f"{today}.md"
    if not today_memory.exists():
        create_file(
            today_memory,
            f"# {today} - 今日对话记录\n\n> 自动生成的记忆文件\n\n"
        )

    # 创建通知队列空文件
    queue_file = WORKSPACE / ".notification_queue.json"
    if not queue_file.exists():
        create_file(queue_file, "[]")

    print("=" * 60)
    print("\n✅ 初始化完成！")
    print("\n创建的文件：")
    print("  - .learnings/ERRORS.md")
    print("  - .learnings/LEARNINGS.md")
    print("  - .learnings/FEATURES.md")
    print(f"  - memory/{today}.md")
    print("  - .notification_queue.json")
    print("\n下一步：")
    print("  1. 配置 config/dream_config.json")
    print("  2. 运行 setup/install_cron.py 安装定时任务")
    print("  3. 测试 sync/sync_notification.py")
    print("  4. 测试 dream/dream_cycle.py")


if __name__ == '__main__':
    main()


path: setup/install_cron.py
content: #!/usr/bin/env python3
"""
持续学习套件 - 定时任务安装脚本（跨平台）

支持Windows/Linux/Mac
"""
import subprocess
import sys
import platform
from pathlib import Path

WORKSPACE = Path.cwd()
SYNC_SCRIPT = WORKSPACE / "skills/continuous-learning/sync/sync_notification.py"
DREAM_SCRIPT = WORKSPACE / "skills/continuous-learning/dream/dream_cycle.py"


def is_windows():
    """检测是否为Windows"""
    return platform.system() == 'Windows'


def get_existing_windows_tasks():
    """获取Windows现有任务"""
    try:
        result = subprocess.run(
            ['schtasks', '/query', '/fo', 'LIST', '/v'],
            capture_output=True,
            text=True,
            shell=True
        )
        return result.stdout if result.returncode == 0 else ''
    except:
        return ''


def install_windows_tasks():
    """安装Windows定时任务"""
    print("\n检测到Windows系统，将创建任务计划程序任务...")

    # 删除旧任务
    for task_name in ['OpenClaw-ContinuousSync', 'OpenClaw-ContinuousDream']:
        try:
            subprocess.run(
                ['schtasks', '/delete', '/tn', task_name, '/f'],
                capture_output=True,
                shell=True
            )
            print(f"  删除旧任务: {task_name}")
        except:
            pass

    # 创建新任务
    tasks = [
        {
            'name': 'OpenClaw-ContinuousSync',
            'script': str(SYNC_SCRIPT),
            'time': '23:00'
        },
        {
            'name': 'OpenClaw-ContinuousDream',
            'script': str(DREAM_SCRIPT),
            'time': '02:00'
        }
    ]

    success = True
    for task in tasks:
        try:
            result = subprocess.run(
                [
                    'schtasks', '/create',
                    '/tn', task['name'],
                    '/tr', f'python "{task["script"]}"',
                    '/sc', 'daily',
                    '/st', task['time'],
                    '/f'
                ],
                capture_output=True,
                text=True,
                shell=True
            )

            if result.returncode == 0:
                print(f"  ✅ 创建任务: {task['name']} ({task['time']})")
            else:
                print(f"  ❌ 创建任务失败: {task['name']}")
                print(f"     错误: {result.stderr}")
                success = False
        except Exception as e:
            print(f"  ❌ 创建任务异常: {task['name']} - {e}")
            success = False

    return success


def get_cron_jobs():
    """获取现有cron任务（Linux/Mac）"""
    try:
        result = subprocess.run(['crontab', '-l'], capture_output=True, text=True)
        return result.stdout.split('\n') if result.returncode == 0 else []
    except:
        return []


def install_cron_jobs():
    """安装cron任务（Linux/Mac）"""
    print("\n检测到Linux/Mac系统，将创建cron任务...")

    existing_jobs = get_cron_jobs()

    # 过滤掉我们的旧任务
    filtered_jobs = [
        job for job in existing_jobs
        if 'ContinuousSync' not in job and 'ContinuousDream' not in job
    ]

    # 添加新任务
    new_jobs = filtered_jobs.copy()

    sync_cron = f"0 23 * * * cd {WORKSPACE} && python {SYNC_SCRIPT} >> /tmp/openclaw_sync.log 2>&1"
    dream_cron = f"0 2 * * * cd {WORKSPACE} && python {DREAM_SCRIPT} >> /tmp/openclaw_dream.log 2>&1"

    new_jobs.append(sync_cron)
    new_jobs.append(dream_cron)

    # 写入crontab
    crontab_content = '\n'.join(new_jobs)

    process = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE, text=True)
    process.communicate(input=crontab_content)

    return process.returncode == 0


def main():
    print("\n持续学习套件 - 定时任务安装")
    print("=" * 60)

    print("将添加以下定时任务：")
    print(f"  23:00 - 同步聊天 ({SYNC_SCRIPT})")
    print(f"  02:00 - 做梦分析 ({DREAM_SCRIPT})")
    print()

    # 检查操作系统
    if is_windows():
        print(f"检测到系统: {platform.system()} {platform.release()}")
        print()
        response = input("继续安装Windows任务计划程序任务？ [y/N]: ")
    else:
        print(f"检测到系统: {platform.system()} {platform.release()}")
        print()
        response = input("继续安装cron任务？ [y/N]: ")

    if response.lower() != 'y':
        print("已取消")
        sys.exit(0)

    # 安装任务
    if is_windows():
        success = install_windows_tasks()

        if success:
            print("\n✅ 任务计划程序任务安装成功！")
            print("\n查看任务：")
            print("  打开“任务计划程序”（taskschd.msc）")
            print("  查找任务名：OpenClaw-ContinuousSync, OpenClaw-ContinuousDream")
            print("\n查看状态：")
            print("  schtasks /query /tn \"OpenClaw-ContinuousSync\"")
        else:
            print("\n❌ 安装失败")
            print("\n提示：可能需要管理员权限")
            sys.exit(1)
    else:
        if install_cron_jobs():
            print("\n✅ cron任务安装成功！")
            print("\n查看任务：")
            print("  crontab -l")
            print("\n日志文件：")
            print("  /tmp/openclaw_sync.log")
            print("  /tmp/openclaw_dream.log")
        else:
            print("\n❌ 安装失败")
            sys.exit(1)


if __name__ == '__main__':
    main()


path: sync/sync_notification.py
content: # -*- coding: utf-8 -*-
import json
import sys
import os
from datetime import datetime

sys.stdout.reconfigure(encoding='utf-8', errors='replace')

# 添加路径
sys.path.insert(0, 'C:/Users/18625/.openclaw/workspace/skills/mempalace')
from mempalace.mcp_server import handle_request

# 加载配置
def load_config():
    """加载配置"""
    config_path = 'C:/Users/18625/.openclaw/workspace/skills/continuous-learning/config/dream_config.json'
    default_queue = "C:/Users/18625/.openclaw/workspace/.notification_queue.json"

    try:
        with open(config_path, 'r', encoding='utf-8') as f:
            config = json.load(f)
            notification_config = config.get('notification', {})
            return {
                'queue_file': os.path.join(
                    os.path.dirname(config_path),
                    notification_config.get('queue_file', '.notification_queue.json')
                ),
                'to': notification_config.get('to', '')
            }
    except:
        return {
            'queue_file': default_queue,
            'to': ''
        }

NOTIFICATION_CONFIG = load_config()

def queue_notification(message):
    """将通知存入队列"""
    try:
        notifications = []

        queue_file = NOTIFICATION_CONFIG['queue_file']
        to_user = NOTIFICATION_CONFIG.get('to', '')

        if os.path.exists(queue_file):
            with open(queue_file, 'r', encoding='utf-8') as f:
                notifications = json.load(f)

        notification_item = {
            'message': message,
            'timestamp': datetime.now().isoformat()
        }

        if to_user:
            notification_item['to'] = to_user

        notifications.append(notification_item)

        with open(queue_file, 'w', encoding='utf-8') as f:
            json.dump(notifications, f, ensure_ascii=False, indent=2)

        print(f"[通知] 已加入发送队列")
        return True
    except Exception as e:
        print(f"[通知] 队列写入失败: {e}")
        return False

if __name__ == '__main__':
    start_time = datetime.now()
    print(f"[SYNC] 开始同步 - {start_time.strftime('%Y-%m-%d %H:%M:%S')}")

    date_str = datetime.now().strftime('%Y-%m-%d')
    entry_text = f"SESSION:{date_str} 今日聊天已经自动同步到MemPalace 定时任务执行时间 {start_time.strftime('%H:%M:%S')}"

    # 执行同步
    req = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "mempalace_diary_write",
            "arguments": {
                "agent_name": "小麦",
                "entry": entry_text,
                "topic": "daily_summary"
            }
        }
    }

    result = handle_request(req)

    if 'result' in result:
        content = result['result']['content'][0]['text']
        data = json.loads(content)

        if data.get('success'):
            print(f"[SYNC] 同步成功")
            print(f"  条目ID: {data.get('entry_id')}")

            end_time = datetime.now()
            duration = (end_time - start_time).total_seconds()

            # 队列通知
            message = f"""✅ 今日聊天已同步到MemPalace

📅 日期: {date_str}
🕒 时间: {start_time.strftime('%H:%M:%S')}
⏱️ 耗时: {duration:.2f}秒

条目ID: {data.get('entry_id', 'unknown')}
"""
            queue_notification(message)

        else:
            print(f"[SYNC] 同步失败")
            queue_notification(f"❌ 同步失败: {data}")
    else:
        print(f"[SYNC] 错误: {result}")


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