diff --git a/desktop/src-tauri/src/intelligence/heartbeat.rs b/desktop/src-tauri/src/intelligence/heartbeat.rs index f447bca..b6f8947 100644 --- a/desktop/src-tauri/src/intelligence/heartbeat.rs +++ b/desktop/src-tauri/src/intelligence/heartbeat.rs @@ -268,6 +268,8 @@ async fn execute_tick( ("pending-tasks", check_pending_tasks), ("memory-health", check_memory_health), ("idle-greeting", check_idle_greeting), + ("personality-improvement", check_personality_improvement), + ("learning-opportunities", check_learning_opportunities), ]; let checks_count = checks.len(); @@ -278,7 +280,11 @@ async fn execute_tick( } if let Some(alert) = check_fn(agent_id) { - alerts.push(alert); + // Add source to alert + alerts.push(HeartbeatAlert { + source: source.to_string(), + ..alert + }); } } @@ -343,6 +349,49 @@ fn check_idle_greeting(_agent_id: &str) -> Option { None } +/// Check for personality improvement opportunities +/// +/// Detects patterns that suggest the agent's personality could be improved: +/// - User repeatedly corrects behavior (e.g., "不要那么啰嗦") +/// - User expresses same preference multiple times +/// - Context changes (new project, different role) +/// +/// When threshold is reached, proposes a personality change via the identity system. +fn check_personality_improvement(agent_id: &str) -> Option { + // Pattern detection heuristics + // In full implementation, this would: + // 1. Query memory for recent "correction" type interactions + // 2. Count frequency of similar corrections + // 3. If >= 3 similar corrections, trigger proposal + + // Common correction patterns to detect + let correction_patterns = [ + ("啰嗦|冗长|简洁", "用户偏好简洁回复", "communication_style"), + ("正式|随意|轻松", "用户偏好轻松语气", "tone"), + ("详细|概括|摘要", "用户偏好概要性回答", "detail_level"), + ("英文|中文|语言", "用户语言偏好", "language"), + ("代码|解释|说明", "用户偏好代码优先", "code_first"), + ]; + + // Placeholder: In production, query memory store for these patterns + // For now, return None (no pattern detected) + let _ = (agent_id, correction_patterns); + None +} + +/// Check for learning opportunities from recent conversations +/// +/// Identifies opportunities to capture user preferences or behavioral patterns +/// that could enhance agent effectiveness. +fn check_learning_opportunities(_agent_id: &str) -> Option { + // In full implementation, this would: + // 1. Analyze recent conversations for explicit preferences + // 2. Detect implicit preferences from user reactions + // 3. Suggest memory entries or identity changes + + None +} + // === Tauri Commands === /// Heartbeat engine state for Tauri diff --git a/desktop/src/components/ReflectionLog.tsx b/desktop/src/components/ReflectionLog.tsx index 3695ffd..3bdbde6 100644 --- a/desktop/src/components/ReflectionLog.tsx +++ b/desktop/src/components/ReflectionLog.tsx @@ -37,6 +37,39 @@ import { type ImprovementSuggestion, } from '../lib/intelligence-client'; +// === Config Persistence === + +const REFLECTION_CONFIG_KEY = 'zclaw-reflection-config'; + +const DEFAULT_CONFIG: ReflectionConfig = { + trigger_after_conversations: 5, + allow_soul_modification: true, + require_approval: true, + use_llm: true, + llm_fallback_to_rules: true, +}; + +function loadConfig(): ReflectionConfig { + try { + const stored = localStorage.getItem(REFLECTION_CONFIG_KEY); + if (stored) { + const parsed = JSON.parse(stored); + return { ...DEFAULT_CONFIG, ...parsed }; + } + } catch { + console.warn('[ReflectionLog] Failed to load config from localStorage'); + } + return DEFAULT_CONFIG; +} + +function saveConfig(config: ReflectionConfig): void { + try { + localStorage.setItem(REFLECTION_CONFIG_KEY, JSON.stringify(config)); + } catch { + console.warn('[ReflectionLog] Failed to save config to localStorage'); + } +} + // === Types === interface ReflectionLogProps { @@ -385,11 +418,12 @@ export function ReflectionLog({ const [expandedId, setExpandedId] = useState(null); const [isReflecting, setIsReflecting] = useState(false); const [showConfig, setShowConfig] = useState(false); - const [config, setConfig] = useState({ - trigger_after_conversations: 5, - allow_soul_modification: true, - require_approval: true, - }); + const [config, setConfig] = useState(() => loadConfig()); + + // Persist config changes + useEffect(() => { + saveConfig(config); + }, [config]); // Load history and pending proposals useEffect(() => {