diff --git a/agent/evolution/prompts.py b/agent/evolution/prompts.py index 39f01989..9733b595 100644 --- a/agent/evolution/prompts.py +++ b/agent/evolution/prompts.py @@ -79,13 +79,14 @@ them. When their signal is clear, act; do not be shy here. Act ONLY on something the main assistant clearly MISSED that does not belong in any skill. - MEMORY.md is the curated long-term index, auto-loaded into EVERY future - conversation. Treat it as precious: writing here is RARE and reserved for - CORRECTING a wrong fact already in MEMORY.md (edit that line in place). - Do NOT append new entries to MEMORY.md — that is the nightly pass's job. - - For a genuinely important NEW durable fact the chat missed, append ONE - short bullet to today's `memory/YYYY-MM-DD.md` (not MEMORY.md). When unsure, - the daily file is the safe place — but first ask whether this really - belongs in a skill instead. + conversation. Treat it as precious: edit it in place to CORRECT a wrong + fact, or append a new durable preference/decision/lesson — but do so + SPARINGLY (a lasting fact, not a passing detail; the nightly pass handles + routine consolidation). + - For a NEW fact that is important but not yet clearly lasting, append ONE + short bullet to today's `memory/YYYY-MM-DD.md` instead. When unsure, the + daily file is the safe place — but first ask whether this really belongs + in a skill. - Keep it to ONE short bullet. Never write paragraphs, never re-summarize the conversation, never copy what the main assistant already recorded. - If it is already captured anywhere (check MEMORY.md AND the daily file diff --git a/agent/memory/conversation_store.py b/agent/memory/conversation_store.py index 305e2576..1537f98e 100644 --- a/agent/memory/conversation_store.py +++ b/agent/memory/conversation_store.py @@ -124,6 +124,11 @@ def _is_internal_user_marker(text: str) -> bool: return any(t.startswith(m) for m in _SCHEDULED_DISPLAY_MARKERS) +def _is_evolution_text(text: str) -> bool: + """True if assistant text is a self-evolution summary (before cleaning).""" + return (text or "").lstrip().startswith(_EVOLUTION_DISPLAY_MARKER) + + def _clean_display_text(text: str) -> str: """Strip internal markers from assistant text for user-facing display. @@ -306,6 +311,10 @@ def _group_into_display_turns( step["result"] = tr.get("result", "") step["is_error"] = tr.get("is_error", False) + # Detect a self-evolution bubble BEFORE cleaning the marker away, so the + # UI can flag it even though the visible text stays clean. + is_evolution = _is_evolution_text(final_text) + # Clean internal markers from the user-facing assistant text. Applies to # both the final content and the mirrored content step so the rendered # bubble shows clean text while the stored message keeps the markers. @@ -321,6 +330,8 @@ def _group_into_display_turns( "steps": steps, "created_at": final_ts or (user_row[1] if user_row else 0), } + if is_evolution: + turn["kind"] = "evolution" if merged_extras: turn["extras"] = merged_extras turns.append(turn) diff --git a/channel/web/static/js/console.js b/channel/web/static/js/console.js index de1308b4..0e7f33ef 100644 --- a/channel/web/static/js/console.js +++ b/channel/web/static/js/console.js @@ -124,6 +124,7 @@ const I18N = { config_max_steps: '最大执行步数', config_max_steps_hint: '单次对话中 Agent 最多调用工具的次数', config_enable_thinking: '深度思考', config_enable_thinking_hint: '是否启用深度思考模式', config_self_evolution: '自主进化', config_self_evolution_hint: '会话空闲后自动复盘,沉淀记忆、优化技能、处理未完成事项', + evolution_badge: '自主学习', config_channel_type: '通道类型', config_provider: '模型厂商', config_model_name: '模型', config_custom_model_hint: '输入自定义模型名称', @@ -327,6 +328,7 @@ const I18N = { config_max_steps: 'Max Steps', config_max_steps_hint: 'Max tool calls the Agent can make in a single conversation', config_enable_thinking: 'Deep Thinking', config_enable_thinking_hint: 'Enable deep thinking mode', config_self_evolution: 'Self-Evolution', config_self_evolution_hint: 'Auto-review idle conversations to consolidate memory, improve skills, and follow up on unfinished tasks', + evolution_badge: 'Self-learned', config_channel_type: 'Channel Type', config_provider: 'Provider', config_model_name: 'Model', config_custom_model_hint: 'Enter custom model name', @@ -2886,10 +2888,20 @@ function createBotMessageEl(content, timestamp, requestId, msg) { stepsHtml = renderThinkingHtml(reasoning) + renderToolCallsHtml(toolCalls); } + // Self-evolution bubbles get a small badge so the user can feel the agent + // learned something on its own (text itself stays clean). + const evolutionBadge = (msg && msg.kind === 'evolution') + ? `
+ + ${t('evolution_badge')} +
` + : ''; + el.innerHTML = ` CowAgent
+ ${evolutionBadge} ${stepsHtml ? `
${stepsHtml}
` : ''}
${renderMarkdown(displayContent)}