mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-09 09:59:45 -10:00
fix(app-server): find installed agent CLIs with tokio::fs, not blocking calls on a runtime worker
resolve and is_executable in runtime_api/external_agents.rs become async and use
tokio::fs::metadata. c4a7d694a0 left one unprotected std::fs site there, which
fails scripts/check-blocking-calls-budget.py (std_fs sites 1 > budget 0).
Verification: check-blocking-calls-budget.py within budget (653 sites);
cargo clippy -p codewhale-app-server --lib --locked -D warnings clean. No existing
test covers this file; GET /v1/agents/external not exercised after the change.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
1 parent
0a626fdab8
commit
9becbc824a
1 file changed
+16
-9
@@ -98,7 +98,7 @@ const USER_BIN_DIRS: &[&str] = &[
|
||||
];
|
||||
const SYSTEM_BIN_DIRS: &[&str] = &["/opt/homebrew/bin", "/usr/local/bin"];
|
||||
|
||||
fn resolve(binary: &str) -> Option<PathBuf> {
|
||||
async fn resolve(binary: &str) -> Option<PathBuf> {
|
||||
let mut dirs: Vec<PathBuf> = std::env::var_os("PATH")
|
||||
.map(|path| std::env::split_paths(&path).collect())
|
||||
.unwrap_or_default();
|
||||
@@ -106,21 +106,28 @@ fn resolve(binary: &str) -> Option<PathBuf> {
|
||||
dirs.extend(USER_BIN_DIRS.iter().map(|dir| home.join(dir)));
|
||||
}
|
||||
dirs.extend(SYSTEM_BIN_DIRS.iter().map(PathBuf::from));
|
||||
dirs.into_iter()
|
||||
.map(|dir| dir.join(binary))
|
||||
.find(|candidate| is_executable(candidate))
|
||||
for dir in dirs {
|
||||
let candidate = dir.join(binary);
|
||||
if is_executable(&candidate).await {
|
||||
return Some(candidate);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn is_executable(path: &Path) -> bool {
|
||||
async fn is_executable(path: &Path) -> bool {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
std::fs::metadata(path)
|
||||
tokio::fs::metadata(path)
|
||||
.await
|
||||
.is_ok_and(|meta| meta.is_file() && meta.permissions().mode() & 0o111 != 0)
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn is_executable(path: &Path) -> bool {
|
||||
path.is_file()
|
||||
async fn is_executable(path: &Path) -> bool {
|
||||
tokio::fs::metadata(path)
|
||||
.await
|
||||
.is_ok_and(|meta| meta.is_file())
|
||||
}
|
||||
|
||||
fn foreign_command(path: &Path, args: &[&str]) -> Command {
|
||||
@@ -258,7 +265,7 @@ fn clean_kind(kind: &str) -> &'static str {
|
||||
}
|
||||
|
||||
async fn describe(agent: &'static Agent) -> Value {
|
||||
let Some(path) = resolve(agent.binary) else {
|
||||
let Some(path) = resolve(agent.binary).await else {
|
||||
return json!({
|
||||
"id": agent.id,
|
||||
"name": agent.name,
|
||||
|
||||
Reference in new issue
Block a user