Skip to content

Commit 2892630

Browse files
wesbillmanPinky
andcommitted
Fix dev ACP sidecar resolution
Build the local ACP sidecars before launching the desktop dev app so dev runs have real binaries available. Also ignore non-executable placeholder files during managed-agent command resolution so Tauri sidecar stubs cannot be selected as spawn targets. Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
1 parent 08aa9fb commit 2892630

2 files changed

Lines changed: 54 additions & 5 deletions

File tree

desktop/src-tauri/src/managed_agents/discovery.rs

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,17 +288,37 @@ fn command_search_dirs() -> Vec<PathBuf> {
288288
unique
289289
}
290290

291+
fn is_executable_file(path: &Path) -> bool {
292+
let Ok(metadata) = path.metadata() else {
293+
return false;
294+
};
295+
if !metadata.is_file() {
296+
return false;
297+
}
298+
299+
#[cfg(unix)]
300+
{
301+
use std::os::unix::fs::PermissionsExt;
302+
metadata.permissions().mode() & 0o111 != 0
303+
}
304+
305+
#[cfg(not(unix))]
306+
{
307+
true
308+
}
309+
}
310+
291311
fn resolve_workspace_command(command: &str) -> Option<PathBuf> {
292312
if command_looks_like_path(command) {
293313
let path = PathBuf::from(command);
294-
return path.exists().then_some(path);
314+
return is_executable_file(&path).then_some(path);
295315
}
296316

297317
let file_name = executable_basename(command);
298318
command_search_dirs()
299319
.into_iter()
300320
.map(|dir| dir.join(&file_name))
301-
.find(|candidate| candidate.exists())
321+
.find(|candidate| is_executable_file(candidate))
302322
}
303323

304324
fn resolve_cache() -> &'static std::sync::Mutex<std::collections::HashMap<String, Option<PathBuf>>>
@@ -351,7 +371,7 @@ fn resolve_command_uncached(command: &str) -> Option<PathBuf> {
351371
}
352372

353373
for candidate in path_candidates_from_env(command) {
354-
if candidate.exists() {
374+
if is_executable_file(&candidate) {
355375
return Some(candidate);
356376
}
357377
}
@@ -361,7 +381,7 @@ fn resolve_command_uncached(command: &str) -> Option<PathBuf> {
361381
}
362382
for dir in common_binary_paths() {
363383
let candidate = dir.join(executable_basename(command));
364-
if candidate.exists() {
384+
if is_executable_file(&candidate) {
365385
return Some(candidate);
366386
}
367387
}
@@ -401,7 +421,7 @@ fn find_via_login_shell(command: &str) -> Option<PathBuf> {
401421
let stdout = run_in_login_shell(&["-l", "-c", r#"command -v -- "$1""#, "_", command])?;
402422
let resolved = stdout.lines().rfind(|line| !line.trim().is_empty())?;
403423
let path = PathBuf::from(resolved.trim());
404-
(path.is_absolute() && path.exists()).then_some(path)
424+
(path.is_absolute() && is_executable_file(&path)).then_some(path)
405425
}
406426

407427
/// Return the user's full PATH from a login shell.
@@ -637,6 +657,34 @@ mod tests {
637657
);
638658
}
639659

660+
#[cfg(unix)]
661+
#[test]
662+
fn explicit_path_resolution_ignores_non_executable_files() {
663+
use std::os::unix::fs::PermissionsExt;
664+
665+
let dir =
666+
std::env::temp_dir().join(format!("buzz-discovery-path-{}", uuid::Uuid::new_v4()));
667+
std::fs::create_dir_all(&dir).expect("create temp dir");
668+
let bin = dir.join("buzz-acp");
669+
std::fs::write(&bin, "").expect("write placeholder");
670+
std::fs::set_permissions(&bin, std::fs::Permissions::from_mode(0o644))
671+
.expect("chmod placeholder");
672+
673+
assert!(
674+
super::resolve_workspace_command(bin.to_str().expect("utf8 path")).is_none(),
675+
"non-executable placeholder must not resolve"
676+
);
677+
678+
std::fs::set_permissions(&bin, std::fs::Permissions::from_mode(0o755))
679+
.expect("chmod executable");
680+
assert_eq!(
681+
super::resolve_workspace_command(bin.to_str().expect("utf8 path")),
682+
Some(bin.clone())
683+
);
684+
685+
let _ = std::fs::remove_dir_all(dir);
686+
}
687+
640688
#[test]
641689
fn classifies_available_when_adapter_found() {
642690
let (status, cmd, path) = classify_runtime(

justfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ proxy-release:
274274
dev *ARGS: _ensure-sidecar-stubs
275275
#!/usr/bin/env bash
276276
set -euo pipefail
277+
cargo build -p buzz-acp -p buzz-agent -p buzz-dev-mcp -p buzz-cli
277278
cd {{desktop_dir}}
278279
[[ -d node_modules ]] || pnpm install
279280
source ../scripts/instance-env.sh

0 commit comments

Comments
 (0)