From 53c1129d4e0710486301c959daa1256f895c557d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Hu=E1=BB=B3nh=20Anh=20Khoa?= Date: Mon, 22 Jun 2026 16:26:52 +0700 Subject: [PATCH 1/2] fix(manager): remove stale plugins with missing directories --- crates/yaak-plugins/src/manager.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/yaak-plugins/src/manager.rs b/crates/yaak-plugins/src/manager.rs index 584952f20..0a4350ba0 100644 --- a/crates/yaak-plugins/src/manager.rs +++ b/crates/yaak-plugins/src/manager.rs @@ -181,7 +181,19 @@ impl PluginManager { } } - let plugins = db.list_plugins()?; + let mut plugins = db.list_plugins()?; + plugins.retain(|p| { + if Path::new(&p.directory).exists() { + true + } else { + warn!("Stale plugin entry removed (directory missing): {}", p.directory); + if let Err(e) = db.delete_plugin(p, &UpdateSource::Background) { + warn!("Failed to delete stale plugin from DB: {e:?}"); + } + false + } + }); + drop(db); let init_errors = plugin_manager.initialize_all_plugins(plugins, plugin_context).await; From 03ff602db1d6cab39ddd2bb81627e2c0f6982ed9 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Fri, 26 Jun 2026 22:27:23 -0700 Subject: [PATCH 2/2] fix(manager): keep missing plugins manageable --- apps/yaak-client/lib/initGlobalListeners.tsx | 13 ++++++++ crates-tauri/yaak-app-client/src/lib.rs | 33 +++++++++++++++++--- crates/yaak-plugins/src/install.rs | 11 +++++-- crates/yaak-plugins/src/manager.rs | 14 +-------- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/apps/yaak-client/lib/initGlobalListeners.tsx b/apps/yaak-client/lib/initGlobalListeners.tsx index cd27f68ec..abdcff969 100644 --- a/apps/yaak-client/lib/initGlobalListeners.tsx +++ b/apps/yaak-client/lib/initGlobalListeners.tsx @@ -44,6 +44,19 @@ export function initGlobalListeners() { color: "danger", timeout: null, message: `Failed to load plugin "${name}": ${err}`, + action: ({ hide }) => ( + + ), }); } }); diff --git a/crates-tauri/yaak-app-client/src/lib.rs b/crates-tauri/yaak-app-client/src/lib.rs index ff3f1fe44..1be81957f 100644 --- a/crates-tauri/yaak-app-client/src/lib.rs +++ b/crates-tauri/yaak-app-client/src/lib.rs @@ -54,7 +54,7 @@ use yaak_plugins::events::{ InternalEventPayload, JsonPrimitive, PluginContext, RenderPurpose, ShowToastRequest, }; use yaak_plugins::manager::PluginManager; -use yaak_plugins::plugin_meta::PluginMetadata; +use yaak_plugins::plugin_meta::{PluginMetadata, get_plugin_meta}; use yaak_plugins::template_callback::PluginTemplateCallback; use yaak_sse::sse::ServerSentEvent; use yaak_tauri_utils::window::WorkspaceWindowTrait; @@ -1512,11 +1512,36 @@ async fn cmd_plugin_info( plugin_manager: State<'_, PluginManager>, ) -> YaakResult { let plugin = app_handle.db().get_plugin(id)?; - Ok(plugin_manager + if let Some(plugin_handle) = plugin_manager .get_plugin_by_dir(plugin.directory.as_str()) .await - .ok_or(GenericError("Failed to find plugin for info".to_string()))? - .info()) + { + return Ok(plugin_handle.info()); + } + + if let Ok(metadata) = get_plugin_meta(&PathBuf::from(&plugin.directory)) { + return Ok(metadata); + } + + Ok(fallback_plugin_metadata(&plugin.directory)) +} + +fn fallback_plugin_metadata(directory: &str) -> PluginMetadata { + let display_name = PathBuf::from(directory) + .file_name() + .and_then(|name| name.to_str()) + .filter(|name| !name.is_empty()) + .unwrap_or(directory) + .to_string(); + + PluginMetadata { + version: "Unavailable".to_string(), + name: directory.to_string(), + display_name, + description: Some(format!("Plugin metadata could not be loaded from {directory}")), + homepage_url: None, + repository_url: None, + } } #[tauri::command] diff --git a/crates/yaak-plugins/src/install.rs b/crates/yaak-plugins/src/install.rs index bafd00ab8..d8ac243f6 100644 --- a/crates/yaak-plugins/src/install.rs +++ b/crates/yaak-plugins/src/install.rs @@ -1,6 +1,6 @@ use crate::api::{PluginVersion, download_plugin_archive, get_plugin}; use crate::checksum::compute_checksum; -use crate::error::Error::PluginErr; +use crate::error::Error::{PluginErr, PluginNotFoundErr}; use crate::error::Result; use crate::events::PluginContext; use crate::manager::PluginManager; @@ -29,7 +29,14 @@ pub async fn delete_and_uninstall( let db = query_manager.connect(); db.delete_plugin_by_id(plugin_id, &update_source)? }; - plugin_manager.uninstall(plugin_context, plugin.directory.as_str()).await?; + if let Err(err) = plugin_manager + .uninstall(plugin_context, plugin.directory.as_str()) + .await + { + if !matches!(err, PluginNotFoundErr(_)) { + return Err(err); + } + } Ok(plugin) } diff --git a/crates/yaak-plugins/src/manager.rs b/crates/yaak-plugins/src/manager.rs index 0a4350ba0..584952f20 100644 --- a/crates/yaak-plugins/src/manager.rs +++ b/crates/yaak-plugins/src/manager.rs @@ -181,19 +181,7 @@ impl PluginManager { } } - let mut plugins = db.list_plugins()?; - plugins.retain(|p| { - if Path::new(&p.directory).exists() { - true - } else { - warn!("Stale plugin entry removed (directory missing): {}", p.directory); - if let Err(e) = db.delete_plugin(p, &UpdateSource::Background) { - warn!("Failed to delete stale plugin from DB: {e:?}"); - } - false - } - }); - + let plugins = db.list_plugins()?; drop(db); let init_errors = plugin_manager.initialize_all_plugins(plugins, plugin_context).await;