diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-03 20:10:42 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-03 20:11:00 +0300 |
| commit | 0473d329fdd7566c209edd205f5ddf1dd5e9dc16 (patch) | |
| tree | bec09f53cf04f2ca19cb359dc7ec3a0a5742422c /src | |
| parent | 3965b6fb80528fd6b48a4582cf3d35e765be132f (diff) | |
fix: detect pnpm opencode executable
refs #447
Diffstat (limited to 'src')
| -rw-r--r-- | src/detect/mod.rs | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/src/detect/mod.rs b/src/detect/mod.rs index e22a5c3b..6240d1b2 100644 --- a/src/detect/mod.rs +++ b/src/detect/mod.rs @@ -84,7 +84,7 @@ pub fn agent_label(agent: Agent) -> &'static str { } pub fn parse_agent_label(agent: &str) -> Option<Agent> { - let name = agent.trim().to_lowercase(); + let name = normalized_agent_lookup_name(agent); match name.as_str() { "pi" => Some(Agent::Pi), "claude" | "claude-code" => Some(Agent::Claude), @@ -110,7 +110,7 @@ pub fn parse_agent_label(agent: &str) -> Option<Agent> { /// Identify which agent is running from the process name. /// Returns `None` for plain shells or unrecognized programs. pub fn identify_agent(process_name: &str) -> Option<Agent> { - let name = process_name.to_lowercase(); + let name = normalized_agent_lookup_name(process_name); // Match against known binary names match name.as_str() { "pi" => Some(Agent::Pi), @@ -486,6 +486,14 @@ fn agent_name_from_basename(basename: &str) -> Option<String> { Some(agent_label(agent).to_string()) } +fn normalized_agent_lookup_name(name: &str) -> String { + let mut name = name.trim().to_lowercase(); + if name.ends_with(".exe") { + name.truncate(name.len() - ".exe".len()); + } + name +} + fn path_basename(path: &str) -> &str { std::path::Path::new(path) .file_name() @@ -616,6 +624,7 @@ mod tests { assert_eq!(identify_agent("antigravity-cli"), Some(Agent::Antigravity)); assert_eq!(identify_agent("cline"), Some(Agent::Cline)); assert_eq!(identify_agent("opencode"), Some(Agent::OpenCode)); + assert_eq!(identify_agent("opencode.exe"), Some(Agent::OpenCode)); assert_eq!(identify_agent("kimi"), Some(Agent::Kimi)); assert_eq!(identify_agent("Kimi Code"), Some(Agent::Kimi)); assert_eq!(identify_agent("kiro"), Some(Agent::Kiro)); @@ -637,6 +646,7 @@ mod tests { assert_eq!(parse_agent_label("cursor-agent"), Some(Agent::Cursor)); assert_eq!(parse_agent_label("agy"), Some(Agent::Antigravity)); assert_eq!(parse_agent_label("antigravity"), Some(Agent::Antigravity)); + assert_eq!(parse_agent_label("opencode.exe"), Some(Agent::OpenCode)); assert_eq!(parse_agent_label("copilot"), Some(Agent::GithubCopilot)); assert_eq!(parse_agent_label("kimi-code"), Some(Agent::Kimi)); assert_eq!( @@ -777,6 +787,40 @@ mod tests { } #[test] + fn identify_agent_in_job_detects_opencode_exe_from_pnpm_package() { + let job = crate::platform::ForegroundJob { + process_group_id: 123, + processes: vec![foreground_process( + 123, + "opencode.exe", + &["/home/user/.local/share/pnpm/global/node_modules/opencode-ai/bin/opencode.exe"], + )], + }; + + assert_eq!( + identify_agent_in_job(&job), + Some((Agent::OpenCode, "opencode.exe".to_string())) + ); + } + + #[test] + fn identify_agent_in_job_detects_opencode_exe_from_argv0_path() { + let job = crate::platform::ForegroundJob { + process_group_id: 123, + processes: vec![foreground_process( + 123, + "MainThread", + &["/home/user/.local/share/pnpm/global/node_modules/opencode-ai/bin/opencode.exe"], + )], + }; + + assert_eq!( + identify_agent_in_job(&job), + Some((Agent::OpenCode, "opencode".to_string())) + ); + } + + #[test] fn wrapped_agent_name_from_runtime_argv_ignores_plain_shell_flags() { assert_eq!( wrapped_agent_name_from_runtime_argv("bash", Some(&["bash".into(), "-lc".into()])), |
