claude-desktop/src-tauri/src/lib.rs
Eddy 9d73684ece Monitor-Events Backend-Persistierung in SQLite
- MonitorEvent Struct + CRUD-Methoden in db.rs
- monitor_events Tabelle mit Auto-Cleanup (7 Tage)
- Tauri Commands: save/load/clear_monitor_events
- Frontend: Events beim Start laden, beim Hinzufügen speichern
- Async clearMonitorEvents löscht auch DB-Einträge

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-14 14:22:31 +02:00

184 lines
6.8 KiB
Rust

// 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 context;
mod db;
mod guard;
mod knowledge;
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,
// Monitor-Events
db::save_monitor_event,
db::load_monitor_events,
db::load_monitor_events_by_type,
db::clear_all_monitor_events,
db::get_monitor_stats,
// Wissensbasis (claude-db)
knowledge::search_knowledge,
knowledge::get_knowledge,
knowledge::save_knowledge,
knowledge::get_knowledge_categories,
knowledge::get_recent_knowledge,
knowledge::test_knowledge_connection,
// Context-Management
context::get_sticky_context,
context::set_sticky_context,
context::remove_sticky_context,
context::get_project_context,
context::extract_context_before_compacting,
context::log_context_failure,
context::get_full_context,
context::list_sticky_context,
])
.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::<Arc<Mutex<db::Database>>>();
let guard_state = handle.state::<guard::GuardState>();
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");
}