mod achievements; mod bridge_manager; mod clipboard; mod commands; mod config; mod cost_tracking; mod debug_logger; mod discord_rpc; mod drafts; mod git; mod notifications; mod process_ext; mod quick_actions; mod sessions; mod snippets; mod stats; mod temp_manager; mod tool_cache; mod tray; mod types; mod vbs_notification; mod windows_toast; mod wsl_bridge; mod wsl_notifications; use bridge_manager::create_shared_bridge_manager; use clipboard::*; use commands::load_saved_achievements; use commands::*; use debug_logger::TauriLogLayer; use discord_rpc::DiscordRpcManager; use drafts::*; use git::*; use notifications::*; use quick_actions::*; use sessions::*; use snippets::*; use std::sync::Arc; use tauri::{Emitter, Manager}; use temp_manager::create_shared_temp_manager; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use tray::setup_tray; use vbs_notification::*; use windows_toast::*; use wsl_notifications::*; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { let bridge_manager = create_shared_bridge_manager(); let temp_manager = create_shared_temp_manager().expect("Failed to create temp file manager"); let discord_rpc = Arc::new(DiscordRpcManager::new()); tauri::Builder::default() .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_notification::init()) .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_fs::init()) .manage(bridge_manager.clone()) .manage(temp_manager.clone()) .manage(discord_rpc.clone()) .setup(move |app| { // Initialize tracing with custom layer that emits to frontend // NOTE: We don't use fmt::layer() because in production builds with windows_subsystem = "windows", // stdout is hidden. Instead, all logs go through TauriLogLayer to the debug console. let tauri_layer = TauriLogLayer::new(app.handle().clone()); tracing_subscriber::registry() .with(tauri_layer) .init(); // Initialize the app handle in the bridge manager bridge_manager.lock().set_app_handle(app.handle().clone()); // Clean up any orphaned temp files from previous sessions if let Ok(count) = temp_manager.lock().cleanup_orphaned_files() { if count > 0 { tracing::info!("Cleaned up {} orphaned temp files", count); } } tracing::info!("Hikari Desktop started successfully"); // Set up system tray if let Err(e) = setup_tray(app.handle()) { tracing::error!("Failed to set up system tray: {}", e); } // Handle window close event for minimize to tray and close confirmation let main_window = app.get_webview_window("main").unwrap(); main_window.on_window_event({ let app_handle = app.handle().clone(); move |event| { if let tauri::WindowEvent::CloseRequested { api, .. } = event { // Always prevent default close - let frontend handle it api.prevent_close(); // Emit event to frontend to show confirmation modal if let Some(window) = app_handle.get_webview_window("main") { let _ = window.emit("window-close-requested", ()); } } } }); Ok(()) }) .invoke_handler(tauri::generate_handler![ start_claude, stop_claude, interrupt_claude, send_prompt, is_claude_running, get_working_directory, select_wsl_directory, get_config, save_config, get_usage_stats, get_persisted_stats, load_saved_achievements, answer_question, check_workspace_hooks, send_windows_notification, send_simple_notification, send_windows_toast, send_notify_send, send_wsl_notification, send_vbs_notification, validate_directory, list_skills, check_for_updates, fetch_changelog, check_cli_latest_version, save_temp_file, register_temp_file, get_temp_files, cleanup_temp_files, cleanup_all_temp_files, cleanup_orphaned_temp_files, get_file_size, list_sessions, save_session, load_session, delete_session, search_sessions, clear_all_sessions, list_snippets, save_snippet, delete_snippet, get_snippet_categories, reset_default_snippets, list_quick_actions, save_quick_action, delete_quick_action, reset_default_quick_actions, git_status, git_diff, git_branches, git_checkout, git_stage, git_unstage, git_stage_all, git_commit, git_push, git_pull, git_fetch, git_log, git_discard, git_create_branch, list_clipboard_entries, capture_clipboard, delete_clipboard_entry, toggle_pin_clipboard_entry, clear_clipboard_history, search_clipboard_entries, get_clipboard_languages, update_clipboard_language, list_directory, read_file_content, write_file_content, create_file, create_directory, delete_file, delete_directory, rename_path, // Cost tracking commands get_cost_summary, get_cost_alerts, set_cost_alert_thresholds, export_cost_csv, get_today_cost, get_week_cost, get_month_cost, init_discord_rpc, update_discord_rpc, stop_discord_rpc, close_application, list_memory_files, get_claude_version, get_auth_status, auth_login, auth_logout, list_plugins, install_plugin, uninstall_plugin, enable_plugin, disable_plugin, update_plugin, list_marketplaces, add_marketplace, remove_marketplace, list_mcp_servers, get_mcp_server, remove_mcp_server, add_mcp_server, get_mcp_server_details, list_drafts, save_draft, delete_draft, delete_all_drafts, scan_project, open_binary_file, get_global_claude_md, save_global_claude_md, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }