mod llm; mod rag; mod generations; mod commands; mod sql_viewer; use llm::AppState; use std::sync::Mutex; use tauri::Manager; use tauri_plugin_store::StoreExt; // ponytail: the data-dir preference lives in a tiny store at the OS default // app_data_dir so it's always discoverable at startup, even before we know the // custom location. Key: `dataDir` (absolute path). Empty/missing → default. const PREFS_STORE: &str = "dm-pal-prefs.json"; const DATA_DIR_KEY: &str = "dataDir"; /// Resolve the data dir: the configured one if set and usable, else the /// default `$APPDATA/dm-toolkit`. fn resolve_data_dir(app: &tauri::AppHandle) -> std::path::PathBuf { let default = app .path() .app_data_dir() .expect("app data dir") .join("dm-toolkit"); if let Ok(store) = app.store(PREFS_STORE) { if let Some(Some(v)) = store.get(DATA_DIR_KEY).map(|v| v.as_str().map(|s| s.to_string())) { let p = std::path::PathBuf::from(v); // ponytail: fall back to default if the configured path is gone — // a DM who unmounts the external drive shouldn't lose the app. if p.is_absolute() { return p; } } } default } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_log::Builder::default().build()) .plugin(tauri_plugin_store::Builder::default().build()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_dialog::init()) .setup(|app| { let data_dir = resolve_data_dir(&app.handle()); let rag = rag::RagStore::open(&data_dir.join("lore")) .expect("open lore db"); let gen = generations::GenerationStore::open(&data_dir) .expect("open generations db"); app.manage(AppState { config: Mutex::new(llm::LlmConfig::default()), rag, gen, data_dir, }); Ok(()) }) .invoke_handler(tauri::generate_handler![ greet, commands::llm_commands::generate, commands::llm_commands::generate_stream, commands::llm_commands::get_llm_config, commands::llm_commands::set_llm_config, commands::llm_commands::test_connection, commands::image_commands::generate_image, commands::image_commands::generate_image_stream, commands::rag_commands::rag_add, commands::rag_commands::rag_search, commands::rag_commands::rag_list, commands::rag_commands::rag_clear, commands::rag_commands::rag_chunks, commands::generation_commands::generation_add, commands::generation_commands::generation_list, commands::generation_commands::generation_get, commands::generation_commands::generation_delete, commands::generation_commands::generation_counts, commands::data_commands::get_data_dir, commands::data_commands::set_data_dir, commands::data_commands::reset_data_dir, commands::data_commands::sql_query, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}! Welcome to DM-Pal ⚔", name) }