// Claude Desktop — Autonomes Gedächtnis-System // Lädt Zugänge, Patterns, Vorgehensweisen automatisch und behält sie im Kontext use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use tauri::{AppHandle, Manager}; use crate::db; /// Kategorien für Sticky Context (werden nie vergessen) #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum ContextCategory { Critical, // API-Keys, Server-URLs, Projekt-Pfade Pattern, // Bekannte Fehler und Workarounds Preference, // Benutzer-Präferenzen GuardRail, // Freigabe-Regeln Hook, // Aktive Hooks Skill, // Verfügbare Skills } /// Ein Eintrag im Gedächtnis #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MemoryEntry { pub id: String, pub category: ContextCategory, pub key: String, pub value: serde_json::Value, pub sticky: bool, // Wird nie durch Compacting entfernt pub auto_load: bool, // Wird beim Start automatisch geladen pub last_used: Option, pub use_count: u32, } // MemorySystem Struct entfernt - Dead Code, Funktionalität läuft über Tauri-Commands #[derive(Debug, Serialize, Deserialize)] pub struct MemoryStats { pub total: usize, pub sticky: usize, pub by_category: HashMap, } /// Vorgehensweise / Pattern #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Pattern { pub id: String, pub name: String, pub description: String, pub trigger: String, // Wann wird es angewendet pub old_approach: String, // Was wurde vorher gemacht pub new_approach: String, // Was ist die Korrektur pub reason: String, // Warum wurde korrigiert pub occurrence_count: u32, // Wie oft ist das Problem aufgetreten pub auto_corrected: bool, // Wurde automatisch korrigiert pub created_at: String, pub updated_at: String, } // Tauri-Commands /// Lädt das Gedächtnis beim Start #[tauri::command] pub async fn load_memory(app: AppHandle) -> Result { println!("🧠 Lade Gedächtnis-System..."); let state = app.state::>>(); let db_lock = state.lock().unwrap(); let entries = db_lock.load_memory_entries().map_err(|e| e.to_string())?; let mut by_category: HashMap = HashMap::new(); let mut sticky_count = 0; for entry in &entries { let cat = format!("{:?}", entry.category); *by_category.entry(cat).or_insert(0) += 1; if entry.sticky { sticky_count += 1; } } println!("🧠 {} Einträge geladen ({} sticky)", entries.len(), sticky_count); Ok(MemoryStats { total: entries.len(), sticky: sticky_count, by_category, }) } /// Holt die Sticky-Memory-Einträge (veraltet, nutze context::get_sticky_context) #[tauri::command] pub async fn get_sticky_memory_entries(app: AppHandle) -> Result, String> { let state = app.state::>>(); let db_lock = state.lock().unwrap(); let entries = db_lock.load_memory_entries().map_err(|e| e.to_string())?; Ok(entries.into_iter().filter(|e| e.sticky).collect()) } /// Speichert eine neue Vorgehensweise #[tauri::command] pub async fn save_pattern(app: AppHandle, pattern: Pattern) -> Result<(), String> { println!("📝 Speichere Vorgehensweise: {}", pattern.name); let state = app.state::>>(); let db_lock = state.lock().unwrap(); db_lock.save_pattern(&pattern).map_err(|e| e.to_string()) } /// Erkennt ein Problem und schlägt Korrektur vor #[tauri::command] pub async fn detect_issue( app: AppHandle, error_message: String, _context: String, ) -> Result, String> { let preview_len = error_message.len().min(50); println!("🔍 Prüfe auf bekannte Probleme: {}", &error_message[..preview_len]); let state = app.state::>>(); let db_lock = state.lock().unwrap(); let patterns = db_lock.load_patterns().map_err(|e| e.to_string())?; // Einfaches Pattern-Matching: Trigger im Fehlertext suchen let error_lower = error_message.to_lowercase(); for pattern in patterns { if error_lower.contains(&pattern.trigger.to_lowercase()) { return Ok(Some(pattern)); } } Ok(None) }