diff options
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/linux.rs | 38 | ||||
| -rw-r--r-- | src/platform/mod.rs | 5 |
2 files changed, 43 insertions, 0 deletions
diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 9a44d02e..3cf643e5 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -124,6 +124,26 @@ pub fn process_cwd(pid: u32) -> Option<PathBuf> { std::fs::read_link(format!("/proc/{pid}/cwd")).ok() } +/// Read a Herdr agent identity hint from a process environment. +pub fn process_agent_hint(pid: u32) -> Option<crate::detect::Agent> { + if pid == 0 { + return None; + } + let environ = std::fs::read(format!("/proc/{pid}/environ")).ok()?; + parse_agent_env_hint(&environ) +} + +fn parse_agent_env_hint(environ: &[u8]) -> Option<crate::detect::Agent> { + for record in environ.split(|&byte| byte == 0) { + let Some(value) = record.strip_prefix(b"HERDR_AGENT=") else { + continue; + }; + let value = std::str::from_utf8(value).ok()?; + return crate::detect::parse_agent_label(value); + } + None +} + pub fn session_processes(child_pid: u32) -> Vec<u32> { let Some(session_id) = process_session_id(child_pid) else { return Vec::new(); @@ -490,6 +510,24 @@ mod tests { } #[test] + fn parse_agent_env_hint_accepts_known_agents() { + assert_eq!( + parse_agent_env_hint(b"PATH=/bin\0HERDR_AGENT=claude\0TERM=xterm\0"), + Some(crate::detect::Agent::Claude) + ); + assert_eq!( + parse_agent_env_hint(b"HERDR_AGENT=codex"), + Some(crate::detect::Agent::Codex) + ); + } + + #[test] + fn parse_agent_env_hint_ignores_missing_or_unknown_agents() { + assert_eq!(parse_agent_env_hint(b"PATH=/bin\0TERM=xterm\0"), None); + assert_eq!(parse_agent_env_hint(b"HERDR_AGENT=not-an-agent\0"), None); + } + + #[test] fn clipboard_commands_prefer_wayland_when_available() { let _guard = env_lock().lock().unwrap(); unsafe { diff --git a/src/platform/mod.rs b/src/platform/mod.rs index ec9a497f..0b5f9ecb 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -121,6 +121,11 @@ mod fallback; #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] pub use fallback::*; +#[cfg(not(target_os = "linux"))] +pub fn process_agent_hint(_pid: u32) -> Option<crate::detect::Agent> { + None +} + #[cfg(not(target_os = "macos"))] #[derive(Debug)] pub(crate) struct InputSourceRestore; |
