From 71f9012de37f663ce967cd1068ef7f381b287a56 Mon Sep 17 00:00:00 2001 From: Illia Polosukhin Date: Thu, 19 Mar 2026 10:10:08 -0700 Subject: [PATCH] fix: skip NEAR AI session check when backend is not nearai (#1413) * fix: skip NEAR AI session check when backend is not nearai When a user configures a non-NEAR AI backend (e.g. Anthropic), the doctor command was incorrectly failing with "session file not found" even though no NEAR AI session is needed. The check now skips with a descriptive message when LLM_BACKEND is not nearai/near_ai/near. Co-Authored-By: Claude Sonnet 4.6 * fix(ci): avoid holding sync MutexGuard across await in doctor test Convert check_nearai_session_skips_for_non_nearai_backend from #[tokio::test] to #[test] with block_on, matching the pattern used by all other ENV_MUTEX tests. Fixes clippy::await_holding_lock error. Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Kristian Glass Co-authored-by: Claude Sonnet 4.6 --- src/cli/doctor.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/cli/doctor.rs b/src/cli/doctor.rs index dfc04de7..7510635a 100644 --- a/src/cli/doctor.rs +++ b/src/cli/doctor.rs @@ -33,7 +33,7 @@ pub async fn run_doctor_command() -> anyhow::Result<()> { check( "NEAR AI session", - check_nearai_session().await, + check_nearai_session(&settings).await, &mut passed, &mut failed, &mut skipped, @@ -215,7 +215,22 @@ fn check_settings_file() -> CheckResult { // ── NEAR AI session ───────────────────────────────────────── -async fn check_nearai_session() -> CheckResult { +async fn check_nearai_session(settings: &Settings) -> CheckResult { + // Skip entirely when the configured backend is not NEAR AI. + let llm_config = match crate::config::LlmConfig::resolve(settings) { + Ok(config) => config, + Err(e) => { + // check_llm_config will report the full error; just skip here. + return CheckResult::Skip(format!("LLM config error: {e}")); + } + }; + if llm_config.backend != "nearai" { + return CheckResult::Skip(format!( + "not using NEAR AI backend (backend={})", + llm_config.backend + )); + } + // Check if session file exists let session_path = crate::config::llm::default_session_path(); if !session_path.exists() { @@ -620,12 +635,53 @@ mod tests { #[tokio::test] async fn check_nearai_session_does_not_panic() { - let result = check_nearai_session().await; + let settings = Settings::default(); + let result = check_nearai_session(&settings).await; match result { CheckResult::Pass(_) | CheckResult::Fail(_) | CheckResult::Skip(_) => {} } } + #[test] + fn check_nearai_session_skips_for_non_nearai_backend() { + struct EnvGuard(&'static str, Option); + impl Drop for EnvGuard { + fn drop(&mut self) { + // SAFETY: Under ENV_MUTEX. + unsafe { + match &self.1 { + Some(val) => std::env::set_var(self.0, val), + None => std::env::remove_var(self.0), + } + } + } + } + + let _mutex = crate::config::helpers::ENV_MUTEX.lock().expect("env mutex"); + let prev = std::env::var("LLM_BACKEND").ok(); + // SAFETY: Under ENV_MUTEX, no concurrent env access. + unsafe { + std::env::set_var("LLM_BACKEND", "anthropic"); + } + let _env_guard = EnvGuard("LLM_BACKEND", prev); + + let settings = Settings::default(); + let rt = tokio::runtime::Runtime::new().expect("tokio runtime"); + let result = rt.block_on(check_nearai_session(&settings)); + match result { + CheckResult::Skip(msg) => { + assert!( + msg.contains("backend=anthropic"), + "expected backend name in skip message, got: {msg}" + ); + } + other => panic!( + "expected Skip for non-nearai backend, got: {}", + format_result(&other) + ), + } + } + #[test] fn check_settings_file_handles_missing() { // Settings::default_path() might or might not exist, but must not panic