From ea0b083d2558aba3f710e2f074fb610413571ecb Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Mon, 16 Feb 2026 09:31:46 -0800 Subject: [PATCH] Limit CLI plugin runtime startup and harden shutdown watcher --- crates-cli/yaak-cli/src/commands/request.rs | 2 +- crates-cli/yaak-cli/src/context.rs | 72 +++++++++++++-------- crates-cli/yaak-cli/src/main.rs | 10 ++- crates/yaak-plugins/src/nodejs.rs | 4 +- 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/crates-cli/yaak-cli/src/commands/request.rs b/crates-cli/yaak-cli/src/commands/request.rs index bf508c2f..c8cf016f 100644 --- a/crates-cli/yaak-cli/src/commands/request.rs +++ b/crates-cli/yaak-cli/src/commands/request.rs @@ -161,7 +161,7 @@ pub async fn send_request_by_id( let plugin_context = PluginContext::new(None, Some(request.workspace_id.clone())); let template_callback = PluginTemplateCallback::new( - ctx.plugin_manager.clone(), + ctx.plugin_manager(), ctx.encryption_manager.clone(), &plugin_context, RenderPurpose::Send, diff --git a/crates-cli/yaak-cli/src/context.rs b/crates-cli/yaak-cli/src/context.rs index 0dd0ac5c..471e962e 100644 --- a/crates-cli/yaak-cli/src/context.rs +++ b/crates-cli/yaak-cli/src/context.rs @@ -9,11 +9,11 @@ use yaak_plugins::manager::PluginManager; pub struct CliContext { query_manager: QueryManager, pub encryption_manager: Arc, - pub plugin_manager: Arc, + plugin_manager: Option>, } impl CliContext { - pub async fn initialize(data_dir: PathBuf, app_id: &str) -> Self { + pub async fn initialize(data_dir: PathBuf, app_id: &str, with_plugins: bool) -> Self { let db_path = data_dir.join("db.sqlite"); let blob_path = data_dir.join("blobs.sqlite"); @@ -23,35 +23,45 @@ impl CliContext { let encryption_manager = Arc::new(EncryptionManager::new(query_manager.clone(), app_id)); - let vendored_plugin_dir = data_dir.join("vendored-plugins"); - let installed_plugin_dir = data_dir.join("installed-plugins"); - let node_bin_path = PathBuf::from("node"); + let plugin_manager = if with_plugins { + let vendored_plugin_dir = data_dir.join("vendored-plugins"); + let installed_plugin_dir = data_dir.join("installed-plugins"); + let node_bin_path = PathBuf::from("node"); - let plugin_runtime_main = - std::env::var("YAAK_PLUGIN_RUNTIME").map(PathBuf::from).unwrap_or_else(|_| { - PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../../crates-tauri/yaak-app/vendored/plugin-runtime/index.cjs") - }); + let plugin_runtime_main = + std::env::var("YAAK_PLUGIN_RUNTIME").map(PathBuf::from).unwrap_or_else(|_| { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../crates-tauri/yaak-app/vendored/plugin-runtime/index.cjs") + }); - let plugin_manager = Arc::new( - PluginManager::new( - vendored_plugin_dir, - installed_plugin_dir, - node_bin_path, - plugin_runtime_main, - false, - ) - .await, - ); + let plugin_manager = Arc::new( + PluginManager::new( + vendored_plugin_dir, + installed_plugin_dir, + node_bin_path, + plugin_runtime_main, + false, + ) + .await, + ); - let plugins = query_manager.connect().list_plugins().unwrap_or_default(); - if !plugins.is_empty() { - let errors = - plugin_manager.initialize_all_plugins(plugins, &PluginContext::new_empty()).await; - for (plugin_dir, error_msg) in errors { - eprintln!("Warning: Failed to initialize plugin '{}': {}", plugin_dir, error_msg); + let plugins = query_manager.connect().list_plugins().unwrap_or_default(); + if !plugins.is_empty() { + let errors = plugin_manager + .initialize_all_plugins(plugins, &PluginContext::new_empty()) + .await; + for (plugin_dir, error_msg) in errors { + eprintln!( + "Warning: Failed to initialize plugin '{}': {}", + plugin_dir, error_msg + ); + } } - } + + Some(plugin_manager) + } else { + None + }; Self { query_manager, encryption_manager, plugin_manager } } @@ -60,7 +70,13 @@ impl CliContext { self.query_manager.connect() } + pub fn plugin_manager(&self) -> Arc { + self.plugin_manager.clone().expect("Plugin manager was not initialized for this command") + } + pub async fn shutdown(&self) { - self.plugin_manager.terminate().await; + if let Some(plugin_manager) = &self.plugin_manager { + plugin_manager.terminate().await; + } } } diff --git a/crates-cli/yaak-cli/src/main.rs b/crates-cli/yaak-cli/src/main.rs index 93ac925f..65a824d0 100644 --- a/crates-cli/yaak-cli/src/main.rs +++ b/crates-cli/yaak-cli/src/main.rs @@ -3,7 +3,7 @@ mod commands; mod context; use clap::Parser; -use cli::{Cli, Commands}; +use cli::{Cli, Commands, RequestCommands}; use context::CliContext; #[tokio::main] @@ -20,7 +20,13 @@ async fn main() { dirs::data_dir().expect("Could not determine data directory").join(app_id) }); - let context = CliContext::initialize(data_dir, app_id).await; + let needs_plugins = matches!( + &command, + Commands::Send(_) + | Commands::Request(cli::RequestArgs { command: RequestCommands::Send { .. } }) + ); + + let context = CliContext::initialize(data_dir, app_id, needs_plugins).await; let exit_code = match command { Commands::Send(args) => { diff --git a/crates/yaak-plugins/src/nodejs.rs b/crates/yaak-plugins/src/nodejs.rs index 1283274a..314abbb5 100644 --- a/crates/yaak-plugins/src/nodejs.rs +++ b/crates/yaak-plugins/src/nodejs.rs @@ -68,7 +68,9 @@ pub async fn start_nodejs_plugin_runtime( // Handle kill signal let mut kill_rx = kill_rx.clone(); tokio::spawn(async move { - kill_rx.wait_for(|b| *b == true).await.expect("Kill channel errored"); + if kill_rx.wait_for(|b| *b == true).await.is_err() { + warn!("Kill channel closed before explicit shutdown; terminating plugin runtime"); + } info!("Killing plugin runtime"); if let Err(e) = child.kill().await { warn!("Failed to kill plugin runtime: {e}");