//! Captures how this Codex process was launched. //! //! Runtime diagnostics answer provenance questions that are hard to infer from //! user reports: which binary is running, which install channel it resembles, //! which platform it targets, and whether the search command comes from bundled //! package files or from PATH. use std::env; use std::process::Command; use codex_install_context::InstallContext; use codex_install_context::InstallMethod; use super::CheckStatus; use super::DoctorCheck; use super::describe_install_context; use super::doctor_install_context; use super::push_path_detail; /// Builds the process provenance row for the current Codex executable. /// /// This check is informational and should not fail on its own; inconsistent /// install state is reported by the installation and update checks instead. pub(super) fn runtime_check() -> DoctorCheck { let current_exe = env::current_exe().ok(); let install_context = doctor_install_context(current_exe.as_deref()); let os = env::consts::OS; let arch = env::consts::ARCH; let platform = format!("{os}-{arch}"); let install_method = install_method_name(&install_context); let mut details = vec![ format!("version: {}", env!("CARGO_PKG_VERSION")), format!("platform: {platform}"), format!( "install method: {}", describe_install_context(&install_context) ), format!("commit: {}", build_commit()), ]; push_path_detail(&mut details, "current executable", current_exe.as_deref()); DoctorCheck::new( "runtime.provenance", "runtime", CheckStatus::Ok, format!("running {install_method} on {platform}"), ) .details(details) } /// Verifies that the search command selected by the install context is usable. /// /// Package-layout installs should point at a bundled ripgrep binary, while local /// installs without that layout usually resolve rg from PATH. A warning here /// means features that depend on file search may degrade even when the CLI /// launches. pub(super) fn search_check() -> DoctorCheck { let current_exe = env::current_exe().ok(); let install_context = doctor_install_context(current_exe.as_deref()); let rg_command = install_context.rg_command(); let provider = search_provider(&install_context); let mut details = vec![ format!("search command: {}", rg_command.display()), format!("search provider: {provider}"), ]; let status = if rg_command.components().count() > 1 { match std::fs::metadata(&rg_command) { Ok(metadata) if metadata.is_file() => { details.push("search command readiness: file exists".to_string()); CheckStatus::Ok } Ok(_) => { details.push("search command readiness: path is not a file".to_string()); CheckStatus::Warning } Err(err) => { details.push(format!("search command readiness: {err}")); CheckStatus::Warning } } } else { match Command::new(&rg_command).arg("--version").output() { Ok(output) if output.status.success() => { let version = String::from_utf8_lossy(&output.stdout) .lines() .next() .unwrap_or("rg version unknown") .to_string(); details.push(format!("search command readiness: {version}")); CheckStatus::Ok } Ok(output) => { details.push(format!( "search command readiness: exited with status {}", output.status )); CheckStatus::Warning } Err(err) => { details.push(format!("search command readiness: {err}")); CheckStatus::Warning } } }; let summary = match status { CheckStatus::Ok => format!("search is OK ({provider})"), CheckStatus::Warning => "search command could not be verified".to_string(), CheckStatus::Fail => unreachable!(), }; let mut check = DoctorCheck::new("runtime.search", "search", status, summary).details(details); if status != CheckStatus::Ok { check = check.remediation("Install ripgrep or repair the bundled Codex package."); } check } fn install_method_name(context: &InstallContext) -> &'static str { match &context.method { InstallMethod::Standalone { .. } => "standalone", InstallMethod::Npm => "npm", InstallMethod::Bun => "bun", InstallMethod::Brew => "brew", InstallMethod::Other => "local build", } } fn search_provider(context: &InstallContext) -> &'static str { let rg_command = context.rg_command(); let from_package_layout = context .package_layout .as_ref() .and_then(|package_layout| package_layout.path_dir.as_ref()) .is_some_and(|path_dir| rg_command.starts_with(path_dir)); let from_legacy_standalone = matches!( &context.method, InstallMethod::Standalone { resources_dir: Some(resources_dir), .. } if rg_command.starts_with(resources_dir) ); if from_package_layout || from_legacy_standalone { "bundled" } else { "system" } } fn build_commit() -> &'static str { option_env!("CODEX_BUILD_COMMIT") .or(option_env!("GIT_COMMIT")) .unwrap_or("unknown") }