From 3df7e7107f106690e83c1ae283abd3a55466d243 Mon Sep 17 00:00:00 2001 From: Wes Date: Tue, 21 Apr 2026 15:56:00 -0600 Subject: [PATCH] Fix zombie agent detection and surface stopped agent cleanup (#380) Co-authored-by: Claude Opus 4.6 (1M context) --- crates/sprout-relay/src/api/messages.rs | 7 ++----- crates/sprout-relay/src/handlers/ingest.rs | 12 ++++-------- .../src-tauri/src/managed_agents/runtime.rs | 4 ++-- .../agents/ui/ManagedAgentsSection.tsx | 18 ++++++++++++++++++ rust-toolchain.toml | 2 +- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/crates/sprout-relay/src/api/messages.rs b/crates/sprout-relay/src/api/messages.rs index ef80c0d80c..bcd9d8478f 100644 --- a/crates/sprout-relay/src/api/messages.rs +++ b/crates/sprout-relay/src/api/messages.rs @@ -129,11 +129,8 @@ pub fn validate_imeta_tags(tags: &[Vec], media_base_url: &str) -> Result return Err("imeta duration must be a valid float".into()); } } - "bitrate" => { - // NIP-71 standard field: bits/sec as integer, positive - if value.parse::().map_or(true, |b| b == 0) { - return Err("imeta bitrate must be a positive integer".into()); - } + "bitrate" if value.parse::().map_or(true, |b| b == 0) => { + return Err("imeta bitrate must be a positive integer".into()); } "image" => { // NIP-71 poster frame — must be a local media URL with an image extension. diff --git a/crates/sprout-relay/src/handlers/ingest.rs b/crates/sprout-relay/src/handlers/ingest.rs index 60c5f8c834..72fbe6c2a0 100644 --- a/crates/sprout-relay/src/handlers/ingest.rs +++ b/crates/sprout-relay/src/handlers/ingest.rs @@ -703,15 +703,11 @@ fn validate_diff_event(event: &Event) -> Result<(), String> { return Err("parent-commit SHA must be at least 7 hex characters".to_string()); } } - "branch" => { - if parts.len() < 3 || parts[1].is_empty() || parts[2].is_empty() { - return Err("branch tag requires both source and target".to_string()); - } + "branch" if (parts.len() < 3 || parts[1].is_empty() || parts[2].is_empty()) => { + return Err("branch tag requires both source and target".to_string()); } - "pr" => { - if parts[1].parse::().map(|n| n == 0).unwrap_or(true) { - return Err("pr number must be a positive integer".to_string()); - } + "pr" if parts[1].parse::().map(|n| n == 0).unwrap_or(true) => { + return Err("pr number must be a positive integer".to_string()); } _ => {} } diff --git a/desktop/src-tauri/src/managed_agents/runtime.rs b/desktop/src-tauri/src/managed_agents/runtime.rs index db221da409..0b4df7e570 100644 --- a/desktop/src-tauri/src/managed_agents/runtime.rs +++ b/desktop/src-tauri/src/managed_agents/runtime.rs @@ -321,7 +321,7 @@ pub fn sync_managed_agent_processes( continue; }; - if process_is_running(pid) { + if process_is_running(pid) && process_belongs_to_us(pid) { continue; } @@ -601,7 +601,7 @@ pub fn start_managed_agent_process( } if let Some(pid) = record.runtime_pid { - if process_is_running(pid) { + if process_is_running(pid) && process_belongs_to_us(pid) { record.updated_at = now_iso(); record.last_error = None; return Ok(()); diff --git a/desktop/src/features/agents/ui/ManagedAgentsSection.tsx b/desktop/src/features/agents/ui/ManagedAgentsSection.tsx index 3ba0dccc92..49fcd67e39 100644 --- a/desktop/src/features/agents/ui/ManagedAgentsSection.tsx +++ b/desktop/src/features/agents/ui/ManagedAgentsSection.tsx @@ -186,6 +186,24 @@ export function ManagedAgentsSection({ ) : null} + {!isLoading && stoppedCount > 0 ? ( +
+

+ {stoppedCount} stopped {stoppedCount === 1 ? "agent" : "agents"} +

+ +
+ ) : null} + {error ? (

{error.message} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 02cb8fcb53..f92020c653 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "stable" +channel = "1.95.0" profile = "default"