diff --git a/agent/memory/summarizer.py b/agent/memory/summarizer.py index 536922b7..99a94afd 100644 --- a/agent/memory/summarizer.py +++ b/agent/memory/summarizer.py @@ -54,7 +54,7 @@ MEMORY.md 会注入每次对话的系统提示词中,因此必须保持精炼 - **合并提炼**:将含义相近的多条合并为一条高密度表述,而非简单罗列 - **新增萃取**:从今日日记中提取值得永久记住的新信息(偏好、决策、人物、规则、经验) - **冲突更新**:当新信息与旧条目矛盾时,以新信息为准,替换旧条目 -- **清理无效**:删除临时性记录、空白条目、格式残留等 +- **清理无效**:删除临时性记录、空白条目、格式残留、无意义、重复内容等 - **删除冗余**:已被更精炼表述涵盖的旧条目应删除,避免信息重复 - 每条一行,用 "- " 开头,不带日期前缀 - 目标:控制在 50 条以内,每条尽量一句话概括 diff --git a/channel/web/static/js/console.js b/channel/web/static/js/console.js index 722d689e..55a6f94f 100644 --- a/channel/web/static/js/console.js +++ b/channel/web/static/js/console.js @@ -203,7 +203,7 @@ function applyI18n() { el.setAttribute('data-tooltip', t(el.dataset.tipKey)); }); const langLabel = document.getElementById('lang-label'); - if (langLabel) langLabel.textContent = currentLang === 'zh' ? 'EN' : '中文'; + if (langLabel) langLabel.textContent = currentLang === 'zh' ? '中文' : 'EN'; } function toggleLanguage() { @@ -430,6 +430,20 @@ const fileInput = document.getElementById('file-input'); // Intercept internal navigation links in chat messages messagesDiv.addEventListener('click', (e) => { + const copyBtn = e.target.closest('.copy-msg-btn'); + if (copyBtn) { + e.preventDefault(); + const msgRoot = copyBtn.closest('.flex.gap-3'); + const answerEl = msgRoot && msgRoot.querySelector('.answer-content'); + const rawMd = answerEl && answerEl.dataset.rawMd; + if (rawMd) { + navigator.clipboard.writeText(rawMd).then(() => { + const icon = copyBtn.querySelector('i'); + if (icon) { icon.className = 'fas fa-check'; setTimeout(() => { icon.className = 'fas fa-copy'; }, 1500); } + }); + } + return; + } const a = e.target.closest('a'); if (!a) return; const href = a.getAttribute('href') || ''; @@ -936,7 +950,12 @@ function startSSE(requestId, loadingEl, timestamp, titleInfo) {
-
+
+
+相关文档:[知识库](https://docs.cowagent.ai/knowledge)
+
+## 🌙 梦境记忆蒸馏(Deep Dream)
+
+全新的记忆整理机制,每日自动将分散的对话记忆蒸馏为精炼的长期记忆:
+
+- **三层记忆流转**:对话上下文(短期)→ 天级记忆(中期)→ MEMORY.md(长期),形成完整的记忆生命周期
+- **自动蒸馏**:每日 23:55 定时执行,读取当天天级记忆和 MEMORY.md,通过 LLM 进行去重、合并、修剪,输出精炼的新版 MEMORY.md
+- **梦境日记**:每次蒸馏生成一篇叙事风格的梦境日记,记录整理过程的发现和洞察,存储在 `memory/dreams/` 目录
+- **手动触发**:支持 `/memory dream [N]` 手动触发,可指定整理天数(默认 3 天,最大 30 天),完成后在对话中通知结果
+- **Web 控制台**:记忆管理页面新增「梦境日记」tab,可浏览和查看所有梦境日记
+
+相关文档:[梦境蒸馏](https://docs.cowagent.ai/memory/deep-dream)
+
+
+
+## 🧠 上下文智能压缩
+
+上下文超出限制时将裁剪的部分通过 LLM 总结后异步注入,保持对话连贯性:
+
+- **LLM 异步摘要**:裁剪的消息由 LLM 总结为关键信息,同时写入天级记忆文件和注入保留的上下文
+- **多模型兼容**:优先使用主模型进行摘要,兼容 Claude、OpenAI、MiniMax 等不同模型的消息格式要求
+
+相关文档:[短期记忆](https://docs.cowagent.ai/memory/context)
+
+## 💬 Web 控制台升级
+
+Web 控制台多项功能增强:
+
+- **多会话管理**:支持创建和切换多个独立会话,侧边栏展示会话列表,支持会话标题自动生成和手动编辑
+- **密码保护**:支持为控制台设置登录密码,可通过 `web_console_password` 配置项控制
+- **深度思考**:支持在 Web 端展示模型的思考过程,可通过`enable_thinking` 配置项控制
+- **定时推送**:支持定时任务结果推送到 Web 控制台
+- **消息复制**:AI 回复支持一键复制原始 Markdown 内容
+
+## 🤖 模型相关
+
+- **视觉识别优化**:图片识别工具优先使用主模型,支持多模型厂商自动降级。相关文档:[视觉工具](https://docs.cowagent.ai/tools/vision)
+- **MiniMax 新模型**:新增 MiniMax-M2.7-highspeed 模型和 MiniMax TTS 语音合成支持。Thanks @octo-patch
+- **通义千问**:新增 qwen3.6-plus 模型支持
+
+## 🐛 其他优化与修复
+
+- **记忆提示词优化**:`MEMORY.md` 默认注入系统提示词,精细化记忆检索和写入的触发条件,增强主动写入能力
+- **系统提示词**:优化系统提示词的风格和语气引导
+- **浏览器工具**:增强隐式交互元素检测
+- **文件发送**:修复通用文件类型(tar.gz、zip 等)未能正确发送的问题。Thanks @6vision
+- **macOS 兼容**:修复网络预检超时兼容性问题。Thanks @Moliang Zhou
+- **Windows 兼容**:修复 Windows 下 PowerShell 兼容性、进程更新、终端编码等多项问题
+- **Python 3.13+**:修复 Python 3.13 及以上版本缺少 `legacy-cgi` 依赖的问题
+- **个人微信**:更新个人微信通道版本
+
+## 📦 升级方式
+
+源码部署可执行 `cow update` 或 `./run.sh update` 一键升级,或手动拉取代码后重启。详见 [更新升级文档](https://docs.cowagent.ai/guide/upgrade)。
+
+**发布日期**:2026.04.14 | [Full Changelog](https://github.com/zhayujie/CowAgent/compare/2.0.5...master)
diff --git a/plugins/cow_cli/cow_cli.py b/plugins/cow_cli/cow_cli.py
index d4115091..c470529b 100644
--- a/plugins/cow_cli/cow_cli.py
+++ b/plugins/cow_cli/cow_cli.py
@@ -895,14 +895,14 @@ class CowCliPlugin(Plugin):
if not flush_mgr.llm_model:
return "⚠️ 未配置 LLM 模型,无法执行记忆蒸馏"
+ is_web = self._is_web_channel(e_context)
+
def _run():
try:
result = flush_mgr.deep_dream(lookback_days=days, force=True)
if result:
- self._notify(
- e_context,
- "✅ 记忆蒸馏完成\n\n[MEMORY.md](/memory/MEMORY.md) 已更新,[查看梦境日记](/memory/dreams)"
- )
+ msg = self._build_dream_result(flush_mgr, is_web)
+ self._notify(e_context, msg)
else:
self._notify(e_context, "💤 记忆蒸馏跳过 — 没有新的记忆内容需要整理")
except Exception as e:
@@ -927,6 +927,40 @@ class CowCliPlugin(Plugin):
except Exception as e:
logger.warning(f"[CowCli] notify failed: {e}")
+ @staticmethod
+ def _is_web_channel(e_context) -> bool:
+ if e_context is None:
+ return False
+ try:
+ return e_context["context"].kwargs.get("channel_type") == "web"
+ except Exception:
+ return False
+
+ @staticmethod
+ def _build_dream_result(flush_mgr, is_web: bool) -> str:
+ """Build dream completion message with diary content."""
+ from datetime import datetime
+ lines = ["✅ 记忆蒸馏完成"]
+
+ # Read today's dream diary
+ today = datetime.now().strftime("%Y-%m-%d")
+ diary_file = flush_mgr.memory_dir / "dreams" / f"{today}.md"
+ if diary_file.exists():
+ diary = diary_file.read_text(encoding="utf-8").strip()
+ # Strip the "# Dream Diary: ..." header line
+ diary_lines = diary.split("\n")
+ if diary_lines and diary_lines[0].startswith("# "):
+ diary = "\n".join(diary_lines[1:]).strip()
+ if diary:
+ lines.append(f"\n{diary}")
+
+ if is_web:
+ lines.append("\n[MEMORY.md](/memory/MEMORY.md) | [梦境日记](/memory/dreams)")
+ else:
+ lines.append("\nMEMORY.md 已更新")
+
+ return "\n".join(lines)
+
@staticmethod
def _create_standalone_flush_manager():
"""Create a MemoryFlushManager without a running agent (for pre-init dream)."""