// Claude Desktop — Tauri Backend // Hauptmodul für die Rust-Seite der App use std::sync::{Arc, Mutex}; use tauri::{ Manager, menu::{Menu, MenuItem}, tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, }; mod audit; mod claude; mod db; mod guard; mod memory; mod session; /// Initialisiert die App #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .manage(Arc::new(Mutex::new(claude::ClaudeState::default()))) .manage(guard::GuardState::new(Mutex::new(guard::GuardRails::new()))) .invoke_handler(tauri::generate_handler![ // Claude SDK claude::send_message, claude::stop_all_agents, claude::get_agent_status, claude::set_model, claude::get_available_models, claude::get_current_model, // Gedächtnis-System memory::load_memory, memory::get_sticky_context, memory::save_pattern, memory::detect_issue, // Audit-Log audit::get_audit_log, audit::add_audit_entry, audit::get_audit_stats, // Guard-Rails guard::check_action, guard::add_permission, guard::remove_permission, guard::get_permissions, guard::get_blocked_patterns, // Datenbank db::init_database, db::get_db_stats, // Settings db::get_setting, db::set_setting, db::get_all_settings, // Sessions session::create_session, session::update_session, session::list_sessions, session::get_session, session::delete_session, session::resume_session, session::get_active_session, session::set_claude_session_id, // Messages db::save_message, db::load_messages, db::clear_messages, db::compact_session, ]) .setup(|app| { let handle = app.handle().clone(); println!("🤖 Claude Desktop gestartet"); // Datenbank initialisieren let app_dir = app.path().app_data_dir() .expect("Konnte App-Datenverzeichnis nicht ermitteln"); std::fs::create_dir_all(&app_dir).ok(); let db_path = app_dir.join("claude-desktop.db"); println!("📦 Datenbank: {:?}", db_path); let db = db::Database::open(&db_path) .expect("Datenbank konnte nicht geöffnet werden"); app.manage(Arc::new(Mutex::new(db))); // Guard-Rails: permanente Permissions aus DB laden { let db_state = handle.state::>>(); let guard_state = handle.state::(); let db_lock = db_state.lock().unwrap(); let mut guard_lock = guard_state.lock().unwrap(); if let Ok(perms) = db_lock.load_permissions() { for p in perms { guard_lock.add_permission(p); } println!("🛡️ {} permanente Permissions geladen", guard_lock.get_all_permissions().len()); } } // Gedächtnis-System laden tauri::async_runtime::spawn(async move { println!("🧠 Initialisiere Gedächtnis-System..."); }); // Tray-Icon einrichten let show_item = MenuItem::with_id(app, "show", "Fenster zeigen", true, None::<&str>)?; let hide_item = MenuItem::with_id(app, "hide", "Minimieren", true, None::<&str>)?; let quit_item = MenuItem::with_id(app, "quit", "Beenden", true, None::<&str>)?; let tray_menu = Menu::with_items(app, &[&show_item, &hide_item, &quit_item])?; // App-Icon für Tray verwenden let icon = app.default_window_icon() .cloned() .expect("Kein App-Icon konfiguriert"); let tray_icon = TrayIconBuilder::new() .icon(icon) .menu(&tray_menu) .show_menu_on_left_click(false) .tooltip("Claude Desktop") .on_menu_event(|app, event| { match event.id.as_ref() { "show" => { if let Some(window) = app.get_webview_window("main") { let _ = window.show(); let _ = window.set_focus(); } } "hide" => { if let Some(window) = app.get_webview_window("main") { let _ = window.hide(); } } "quit" => { app.exit(0); } _ => {} } }) .on_tray_icon_event(|tray, event| { // Doppelklick auf Tray-Icon zeigt das Fenster if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { if let Some(window) = tray.app_handle().get_webview_window("main") { let _ = window.show(); let _ = window.set_focus(); } } }) .build(app)?; // Tray-Icon Handle speichern (optional für späteren Zugriff) app.manage(tray_icon); println!("🔲 Tray-Icon eingerichtet"); Ok(()) }) .run(tauri::generate_context!()) .expect("Fehler beim Starten der App"); }