- Session Auto-Load bei App-Start (aktive Session + Nachrichten) - agent_id Spalte in messages-Tabelle für Agent-Zuordnung - DbMessage Interface erweitert (agent_id) - Session-Compacting: compact_session() fasst alte Nachrichten zusammen - Standard: 30 letzte Nachrichten behalten, Rest als Summary Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
160 lines
5.9 KiB
Rust
160 lines
5.9 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 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::<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");
|
|
}
|