Add a self-evolution subsystem that reviews idle conversations in an
isolated agent and durably learns from them — patching/creating skills,
finishing unfinished tasks, and backfilling missed memory.
- Trigger: background idle scan, fires when a session is idle >= N min AND
(>= N turns OR context usage > 80%). In-memory cursor reviews only new
messages so a session never re-learns old content.
- Isolated review agent: same model, restricted toolset, hard write-guard
confining edits to the workspace (built-in skills are protected).
- Safety: file-level backup before edits + evolution_undo tool; notify the
user ONLY when a workspace file actually changed (no-nag rule); capped
concurrency.
- Records to memory/evolution/<date>.md, surfaced in the memory UI's
renamed "Self-Evolution" tab (merged with dream diaries).
- Hide internal [SCHEDULED]/[EVOLUTION]/backup_id markers from chat history
display (also fixes scheduler marker leakage) while keeping them in stored
content for undo.
- Flat config: self_evolution_enabled (default off until release),
self_evolution_idle_minutes (15), self_evolution_min_turns (6).
- Tests: tests/test_evolution.py (stub + real model modes, 7 scenarios).
- Add language labels and copy buttons to code blocks
- Enhance drag-and-drop to full chat view
- Fix data consistency bugs in message operations
- Use RLock to prevent deadlock in conversation store"
When reloading a conversation, failed tool calls incorrectly showed checkmark instead of X because the is_error field was lost in the history rendering pipeline. Propagate is_error from DB extraction through to the frontend rendering to match the live SSE behavior.
Further refinements on top of #2795:
- persist real session_id (notify_session_id) at task creation so group chats
correctly map back to the user's actual conversation
- mark scheduler turns with [SCHEDULED] (recognise legacy "Scheduled task"
prefix too for backward-compatible pruning)
- prune both DB and in-memory to scheduler_inject_max_per_session (default 3),
only marker-tagged pairs are touched; regular user turns never deleted
- send_message type gated by scheduler_inject_send_message (default false) —
fixed reminder text rarely benefits follow-up Q&A
Co-authored-by: huangrichao2020 <grdomai43881@gmail.com>