From 6925f8a5d67d254a10703f22897b0efab5b453a5 Mon Sep 17 00:00:00 2001 From: kangal-bot Date: Tue, 19 May 2026 00:36:16 +0300 Subject: fix: prefer process group leader for agent detection (#172) refs #161 Co-authored-by: kangal-bot --- src/detect.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'src') diff --git a/src/detect.rs b/src/detect.rs index 0319b4ef..595e81f1 100644 --- a/src/detect.rs +++ b/src/detect.rs @@ -96,6 +96,17 @@ pub fn identify_agent(process_name: &str) -> Option { } pub fn identify_agent_in_job(job: &crate::platform::ForegroundJob) -> Option<(Agent, String)> { + if let Some(process) = job + .processes + .iter() + .find(|process| process.pid == job.process_group_id) + { + let candidate = normalized_process_name(process); + if let Some(agent) = identify_agent(&candidate) { + return Some((agent, candidate)); + } + } + let mut best: Option<(u8, Agent, String)> = None; for process in &job.processes { @@ -829,6 +840,58 @@ mod tests { ); } + #[test] + fn identify_agent_in_job_prefers_recognized_process_group_leader() { + let job = crate::platform::ForegroundJob { + process_group_id: 42, + processes: vec![ + crate::platform::ForegroundProcess { + pid: 42, + name: "claude".to_string(), + argv0: None, + cmdline: Some("claude".to_string()), + }, + crate::platform::ForegroundProcess { + pid: 43, + name: "node".to_string(), + argv0: None, + cmdline: Some("node /tmp/mcp/bin/codex".to_string()), + }, + ], + }; + + assert_eq!( + identify_agent_in_job(&job), + Some((Agent::Claude, "claude".to_string())) + ); + } + + #[test] + fn identify_agent_in_job_falls_back_when_process_group_leader_is_unrecognized() { + let job = crate::platform::ForegroundJob { + process_group_id: 42, + processes: vec![ + crate::platform::ForegroundProcess { + pid: 42, + name: "bash".to_string(), + argv0: None, + cmdline: Some("bash".to_string()), + }, + crate::platform::ForegroundProcess { + pid: 43, + name: "node".to_string(), + argv0: None, + cmdline: Some("node /tmp/mcp/bin/codex".to_string()), + }, + ], + }; + + assert_eq!( + identify_agent_in_job(&job), + Some((Agent::Codex, "codex".to_string())) + ); + } + #[test] fn identify_agent_in_job_detects_nix_wrapped_codex_from_cmdline_argv0() { let job = crate::platform::ForegroundJob { -- cgit v1.2.3