From 83f6625e0cccafae122be5422d0e2454736b7c86 Mon Sep 17 00:00:00 2001 From: zhayujie Date: Tue, 14 Apr 2026 12:08:57 +0800 Subject: [PATCH] feat: release 2.0.6 --- agent/memory/summarizer.py | 2 +- channel/web/static/js/console.js | 35 ++++++++++++-- cli/VERSION | 2 +- docs/docs.json | 1 + docs/releases/overview.mdx | 1 + docs/releases/v2.0.6.mdx | 82 ++++++++++++++++++++++++++++++++ plugins/cow_cli/cow_cli.py | 42 ++++++++++++++-- 7 files changed, 155 insertions(+), 10 deletions(-) create mode 100644 docs/releases/v2.0.6.mdx 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) {
-
${formatTime(timestamp)}
+
+ ${formatTime(timestamp)} + +
`; messagesDiv.appendChild(botEl); @@ -1116,8 +1135,10 @@ function startSSE(requestId, loadingEl, timestamp, titleInfo) { addBotMessage(finalText, new Date((item.timestamp || Date.now() / 1000) * 1000), requestId); } else if (botEl) { contentEl.classList.remove('sse-streaming'); - // Only update text content when there is something new to show. if (finalText) contentEl.innerHTML = renderMarkdown(finalText); + contentEl.dataset.rawMd = finalText || ''; + const copyBtn = botEl.querySelector('.copy-msg-btn'); + if (copyBtn && finalText) copyBtn.style.display = ''; applyHighlighting(botEl); } scrollChatToBottom(); @@ -1366,9 +1387,15 @@ function createBotMessageEl(content, timestamp, requestId, msg) { ${stepsHtml ? `
${stepsHtml}
` : ''}
${renderMarkdown(displayContent)}
-
${formatTime(timestamp)}
+
+ ${formatTime(timestamp)} + +
`; + el.querySelector('.answer-content').dataset.rawMd = displayContent; applyHighlighting(el); bindChatKnowledgeLinks(el); return el; diff --git a/cli/VERSION b/cli/VERSION index e0102586..157e54f3 100644 --- a/cli/VERSION +++ b/cli/VERSION @@ -1 +1 @@ -2.0.5 +2.0.6 diff --git a/docs/docs.json b/docs/docs.json index 3ab3e6c2..9a098e88 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -199,6 +199,7 @@ "group": "发布记录", "pages": [ "releases/overview", + "releases/v2.0.6", "releases/v2.0.5", "releases/v2.0.4", "releases/v2.0.3", diff --git a/docs/releases/overview.mdx b/docs/releases/overview.mdx index e34f852c..feb0e9f8 100644 --- a/docs/releases/overview.mdx +++ b/docs/releases/overview.mdx @@ -5,6 +5,7 @@ description: CowAgent 版本更新历史 | 版本 | 日期 | 说明 | | --- | --- | --- | +| [2.0.6](/releases/v2.0.6) | 2026.04.14 | 项目更名、知识库系统、梦境记忆蒸馏、上下文智能压缩、Web 控制台多会话及多项优化 | | [2.0.5](/releases/v2.0.5) | 2026.04.01 | Cow CLI、Skill Hub 开源、浏览器工具、企微扫码创建、多项优化和修复 | | [2.0.4](/releases/v2.0.4) | 2026.03.22 | 新增个人微信通道、新模型支持、日文文档、脚本重构及多项修复 | | [2.0.3](/releases/v2.0.3) | 2026.03.18 | 新增企微智能机器人和 QQ 通道、支持Coding Plan、新增多个模型、Web端文件处理、记忆系统升级 | diff --git a/docs/releases/v2.0.6.mdx b/docs/releases/v2.0.6.mdx new file mode 100644 index 00000000..d29cc2bb --- /dev/null +++ b/docs/releases/v2.0.6.mdx @@ -0,0 +1,82 @@ +--- +title: v2.0.6 +description: CowAgent 2.0.6 - 知识库系统、梦境记忆蒸馏、上下文智能压缩、Web 控制台多会话及多项优化 +--- + +## 项目正式更名为 CowAgent + +项目仓库正式从 `chatgpt-on-wechat` 更名为 **CowAgent**,演进为功能完备的 AI Agent 助理。 + +- 新地址:[github.com/zhayujie/CowAgent](https://github.com/zhayujie/CowAgent),旧地址 GitHub 会自动重定向 +- CLI 命令、配置文件、文档链接均保持兼容,无需额外操作 + +## 📚 知识库系统 + +新增个人知识库系统,Agent 可自主构建和维护结构化知识,并在对话中按需检索引用: + +- **索引驱动的自组织结构**:知识库采用 `knowledge/` 目录,按分类自动组织,每个知识页面为独立的 Markdown 文件 +- **自动写入**:向 Agent 发送文件、链接等知识,或在讨论中识别到有价值的知识时,自动创建或更新知识页面 +- **混合检索**:支持关键词全文搜索和向量语义检索,在对话中按需加载相关知识 +- **可视化**:支持文件树浏览和知识图谱可视化,文档内链接可直接跳转查看 +- **命令管理**:`/knowledge` 查看统计、`/knowledge list` 查看目录结构、`/knowledge on|off` 开关知识库 + + + + +相关文档:[知识库](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)."""