From ac404ba67f2f6fb0a986e865ded4402e445fd009 Mon Sep 17 00:00:00 2001 From: Cameron Hotchkies Date: Fri, 17 Jul 2026 09:59:42 -0700 Subject: [PATCH] fix(desktop): include exe dir and ~/.local/bin in provider discovery (#2007) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why On macOS, GUI apps launched from Finder/Spotlight/Dock inherit a minimal PATH from launchd (`/usr/bin:/bin:/usr/sbin:/sbin`). The `discover_provider_candidates()` function in `backend.rs` only scanned this process PATH when looking for `buzz-backend-*` executables. As a result, backend providers (like `buzz-backend-blox`) were never found, and the "Run on" dropdown in Agent Settings was hidden — even though the binary existed both in the app bundle (`Contents/MacOS/`) and in `~/.local/bin`. ## What Augment the search directories in `discover_provider_candidates()` with: 1. **exe parent dir** (`Contents/MacOS/` in a `.app` bundle) — so bundled providers are always found regardless of how the desktop was launched 2. **`~/.local/bin`** — the conventional location for user-installed provider binaries (symlinks created by install scripts) Both directories are only added if not already present in PATH (deduplication). The exe parent dir is prepended (highest priority for bundled providers); `~/.local/bin` is appended. ## Verification - `cargo check --lib` passes - All 17 `managed_agents::backend` unit tests pass - Pre-push hook `desktop-tauri-test` passes (38s) ## References Root cause confirmed by inspecting the running `buzz-desktop` process environment: ``` $ ps eww | grep PATH PATH=/usr/bin:/bin:/usr/sbin:/sbin ``` --- Generated with Fizz --- .../src-tauri/src/managed_agents/backend.rs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/desktop/src-tauri/src/managed_agents/backend.rs b/desktop/src-tauri/src/managed_agents/backend.rs index 0eada757d..5e7a9cbf7 100644 --- a/desktop/src-tauri/src/managed_agents/backend.rs +++ b/desktop/src-tauri/src/managed_agents/backend.rs @@ -410,13 +410,40 @@ pub fn validate_provider_config(config: &serde_json::Value) -> Result<(), String /// Enumerate PATH for buzz-backend-* executables. Returns (id, path) pairs. /// Only includes files that are executable. Does NOT execute any binaries. +/// +/// On macOS, GUI apps inherit a minimal PATH from launchd (`/usr/bin:/bin:/usr/sbin:/sbin`) +/// which excludes both the app bundle's `Contents/MacOS/` dir and `~/.local/bin`. +/// We augment the search with those directories so bundled and user-installed providers +/// are always discovered regardless of how the desktop was launched. pub fn discover_provider_candidates() -> Vec<(String, PathBuf)> { let prefix = "buzz-backend-"; let mut seen = std::collections::HashSet::new(); let mut results = Vec::new(); let path_var = std::env::var_os("PATH").unwrap_or_default(); - for dir in std::env::split_paths(&path_var) { + let mut dirs: Vec = std::env::split_paths(&path_var).collect(); + + // Prepend the exe parent dir (Contents/MacOS/ in a .app bundle) so bundled + // providers are found even when the process PATH is minimal. + if let Ok(exe) = std::env::current_exe() { + if let Some(parent) = exe.parent() { + let parent_buf = parent.to_path_buf(); + if !dirs.contains(&parent_buf) { + dirs.insert(0, parent_buf); + } + } + } + + // Also include ~/.local/bin — the conventional location for user-installed + // provider binaries (symlinks created by install scripts). + if let Some(home) = dirs::home_dir() { + let local_bin = home.join(".local").join("bin"); + if !dirs.contains(&local_bin) { + dirs.push(local_bin); + } + } + + for dir in dirs { let Ok(entries) = std::fs::read_dir(&dir) else { continue; };