diff options
| author | Michelle Tilley <michelle@michelletilley.net> | 2026-03-17 16:38:45 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-17 16:38:45 -0700 |
| commit | 12742e32ed4edf77fe7aeb03bd0e734b3674d086 (patch) | |
| tree | b62537b60fc2beedaf10dbaaa583f9fab52a2723 /crates | |
| parent | chore(ci): use github for macos (diff) | |
| download | atuin-12742e32ed4edf77fe7aeb03bd0e734b3674d086.zip | |
feat: Report distro name with OS for distro-specific commands (#3289)
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/atuin-ai/src/commands/inline.rs | 26 | ||||
| -rw-r--r-- | crates/atuin-client/src/distro.rs | 89 | ||||
| -rw-r--r-- | crates/atuin-client/src/lib.rs | 1 |
3 files changed, 108 insertions, 8 deletions
diff --git a/crates/atuin-ai/src/commands/inline.rs b/crates/atuin-ai/src/commands/inline.rs index e0ee05d6..7cfacc77 100644 --- a/crates/atuin-ai/src/commands/inline.rs +++ b/crates/atuin-ai/src/commands/inline.rs @@ -4,6 +4,7 @@ use crate::tui::{ App, AppEvent, AppMode, ConversationEvent, EventLoop, ExitAction, RenderContext, TerminalGuard, calculate_needed_height, install_panic_hook, }; +use atuin_client::distro::detect_linux_distribution; use atuin_client::theme::ThemeManager; use atuin_common::tls::ensure_crypto_provider; use crossterm::{ @@ -185,16 +186,25 @@ fn create_chat_stream( debug!("Sending SSE request to {endpoint}"); + let os = detect_os(); + let shell = detect_shell(); + + let mut context = serde_json::json!({ + "os": os, + "shell": shell, + "pwd": if send_cwd { std::env::current_dir() + .ok() + .map(|path| path.to_string_lossy().into_owned()) } else { None }, + }); + + if os == "linux" { + context["distro"] = serde_json::json!(detect_linux_distribution()); + } + // Build request body let mut request_body = serde_json::json!({ "messages": messages, - "context": { - "os": detect_os(), - "shell": detect_shell(), - "pwd": if send_cwd { std::env::current_dir() - .ok() - .map(|path| path.to_string_lossy().into_owned()) } else { None }, - } + "context": context, }); // Include session_id only if present (not on first request) @@ -331,7 +341,7 @@ fn detect_os() -> String { "macos" => "macos".to_string(), "linux" => "linux".to_string(), "windows" => "windows".to_string(), - _ => "linux".to_string(), + other => format!("Other: {other}"), } } diff --git a/crates/atuin-client/src/distro.rs b/crates/atuin-client/src/distro.rs new file mode 100644 index 00000000..dead8355 --- /dev/null +++ b/crates/atuin-client/src/distro.rs @@ -0,0 +1,89 @@ +use std::process::Command; + +/// Detect the Linux distribution from the system, +/// using system-specific release files and falling +/// back to lsb_release. +pub fn detect_linux_distribution() -> String { + detect_from_os_release() + .or_else(detect_from_debian_version) + .or_else(detect_from_centos_release) + .or_else(detect_from_redhat_release) + .or_else(detect_from_fedora_release) + .or_else(detect_from_arch_release) + .or_else(detect_from_alpine_release) + .or_else(detect_from_suse_release) + .or_else(detect_from_lsb_release) + .unwrap_or_else(|| "Unknown".to_string()) +} + +fn detect_from_os_release() -> Option<String> { + let content = std::fs::read_to_string("/etc/os-release").ok()?; + + content + .lines() + .find(|l| l.starts_with("PRETTY_NAME=")) + .and_then(|l| l.split_once('=').map(|s| s.1)) + .map(|s| s.trim_matches('"').to_string()) +} + +fn detect_from_debian_version() -> Option<String> { + std::fs::read_to_string("/etc/debian_version") + .ok() + .map(|v| format!("Debian {}", v.trim())) +} + +fn detect_from_centos_release() -> Option<String> { + std::fs::read_to_string("/etc/centos-release") + .ok() + .map(|v| v.trim().to_string()) +} + +fn detect_from_redhat_release() -> Option<String> { + std::fs::read_to_string("/etc/redhat-release") + .ok() + .map(|v| v.trim().to_string()) +} + +fn detect_from_fedora_release() -> Option<String> { + std::fs::read_to_string("/etc/fedora-release") + .ok() + .map(|v| v.trim().to_string()) +} + +fn detect_from_arch_release() -> Option<String> { + std::fs::read_to_string("/etc/arch-release") + .ok() + .filter(|v| !v.trim().is_empty()) + .map(|_| "Arch Linux".to_string()) +} + +fn detect_from_alpine_release() -> Option<String> { + std::fs::read_to_string("/etc/alpine-release") + .ok() + .map(|v| format!("Alpine {}", v.trim())) +} + +fn detect_from_suse_release() -> Option<String> { + std::fs::read_to_string("/etc/SuSE-release") + .ok() + .and_then(|content| content.lines().next().map(|l| l.trim().to_string())) +} + +fn detect_from_lsb_release() -> Option<String> { + let output = Command::new("lsb_release").arg("-a").output().ok()?; + + if !output.status.success() { + return None; + } + + let output = String::from_utf8(output.stdout).ok()?; + linux_distro_from_lsb_release(&output) +} + +fn linux_distro_from_lsb_release(output: &str) -> Option<String> { + output + .lines() + .find(|line| line.starts_with("Description:")) + .and_then(|line| line.split_once(':').map(|s| s.1)) + .map(|s| s.trim().to_string()) +} diff --git a/crates/atuin-client/src/lib.rs b/crates/atuin-client/src/lib.rs index 4609a8e8..7938176a 100644 --- a/crates/atuin-client/src/lib.rs +++ b/crates/atuin-client/src/lib.rs @@ -17,6 +17,7 @@ pub mod register; pub mod sync; pub mod database; +pub mod distro; pub mod encryption; pub mod history; pub mod import; |
