From 949a00e58ce6b9ed43c87a2d5d70c36737cc22a4 Mon Sep 17 00:00:00 2001 From: CodeWhale Bot Date: Wed, 2 Sep 2026 11:38:39 -0700 Subject: [PATCH] chore: retire the DEEPSEEK_YOLO env alias (#5443) --- crates/cli/src/lib.rs | 27 ++++++++++++++++++- crates/config/src/lib.rs | 6 ++++- crates/config/src/tests.rs | 47 ++++++++++++++++++++++++++++++++++ crates/tui/src/config.rs | 3 +++ crates/tui/src/config/tests.rs | 46 +++++++++++++++++++++++++++++++++ crates/tui/src/lib.rs | 8 +++--- docs/REBRAND.md | 6 ++++- docs/id/REBRAND.md | 3 ++- 8 files changed, 138 insertions(+), 8 deletions(-) diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index ce110041ff..0d13cba246 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -5170,7 +5170,6 @@ fn apply_tui_env(cli: &Cli, resolved_runtime: &ResolvedRuntimeOptions, passthrou if cli.yolo { unsafe { std::env::set_var("CODEWHALE_YOLO", "true"); - std::env::set_var("DEEPSEEK_YOLO", "true"); } } if let Some(api_key) = cli.api_key.as_ref() { @@ -5518,6 +5517,32 @@ mod tests { } } + #[test] + fn yolo_flag_writes_only_the_codewhale_env_var() { + let _lock = env_lock(); + let _guards = [ + ScopedEnvVar::remove("CODEWHALE_TELEMETRY"), + ScopedEnvVar::remove("DEEPSEEK_TELEMETRY"), + ScopedEnvVar::remove(codewhale_config::TELEMETRY_FLOOR_ENV), + ScopedEnvVar::remove("CODEWHALE_YOLO"), + ScopedEnvVar::remove("DEEPSEEK_YOLO"), + ]; + + let cli = parse_ok(&["codewhale", "--yolo"]); + let runtime = resolved_runtime_for_test(ProviderKind::NvidiaNim, ProviderSource::Cli); + apply_tui_env(&cli, &runtime, &[]); + + assert_eq!( + std::env::var("CODEWHALE_YOLO").as_deref(), + Ok("true"), + "--yolo must still enable the posture via CODEWHALE_YOLO" + ); + assert!( + std::env::var("DEEPSEEK_YOLO").is_err(), + "--yolo must not write the retired DEEPSEEK_YOLO alias (#5443)" + ); + } + #[test] fn clap_command_definition_is_consistent() { Cli::command().debug_assert(); diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 703f81107b..b5d735b279 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -7048,13 +7048,17 @@ impl EnvRuntimeOverrides { sandbox_mode: std::env::var("CODEWHALE_SANDBOX_MODE") .or_else(|_| std::env::var("DEEPSEEK_SANDBOX_MODE")) .ok(), + // `DEEPSEEK_YOLO` is a read-only deprecated alias of + // `CODEWHALE_YOLO` so existing scripts keep working; when both are + // set `CODEWHALE_YOLO` wins. The alias is removed in 0.10 per + // issue #5443 — do not write it anywhere. yolo: std::env::var("CODEWHALE_YOLO") .or_else(|_| std::env::var("DEEPSEEK_YOLO")) .ok() .and_then(|v| match parse_bool(&v) { Ok(b) => Some(b), Err(_) => { - tracing::warn!("Invalid CODEWHALE_YOLO/DEEPSEEK_YOLO value '{v}', expected true/false"); + tracing::warn!("Invalid CODEWHALE_YOLO value '{v}', expected true/false"); None } }), diff --git a/crates/config/src/tests.rs b/crates/config/src/tests.rs index 266de73b1b..0a977846c2 100644 --- a/crates/config/src/tests.rs +++ b/crates/config/src/tests.rs @@ -2019,6 +2019,53 @@ fn http_headers_env_overrides_config() { ); } +#[test] +fn yolo_env_var_prefers_codewhale_and_keeps_deepseek_alias() { + let _lock = env_lock(); + let _env = EnvGuard::without_deepseek_runtime_overrides(); + let codewhale_prev = env::var_os("CODEWHALE_YOLO"); + let deepseek_prev = env::var_os("DEEPSEEK_YOLO"); + let config = ConfigToml::default(); + + // Only the canonical name is set. + unsafe { + env::set_var("CODEWHALE_YOLO", "true"); + env::remove_var("DEEPSEEK_YOLO"); + } + let resolved = config.resolve_runtime_options(&CliRuntimeOverrides::default()); + assert_eq!( + resolved.yolo, + Some(true), + "CODEWHALE_YOLO=true must enable the yolo posture" + ); + + // Only the deprecated alias is set: it must keep working through 0.9.x. + unsafe { + env::remove_var("CODEWHALE_YOLO"); + env::set_var("DEEPSEEK_YOLO", "true"); + } + let resolved = config.resolve_runtime_options(&CliRuntimeOverrides::default()); + assert_eq!( + resolved.yolo, + Some(true), + "DEEPSEEK_YOLO remains a read-only deprecated alias until 0.10 (#5443)" + ); + + // Both set: the canonical name wins. + unsafe { env::set_var("CODEWHALE_YOLO", "false") }; + let resolved = config.resolve_runtime_options(&CliRuntimeOverrides::default()); + assert_eq!( + resolved.yolo, + Some(false), + "CODEWHALE_YOLO must win over the deprecated DEEPSEEK_YOLO alias" + ); + + unsafe { + EnvGuard::restore_var("CODEWHALE_YOLO", codewhale_prev); + EnvGuard::restore_var("DEEPSEEK_YOLO", deepseek_prev); + } +} + #[test] fn nvidia_nim_provider_defaults_to_catalog_endpoint_and_model() { let _lock = env_lock(); diff --git a/crates/tui/src/config.rs b/crates/tui/src/config.rs index c9f5e2236e..4487270590 100644 --- a/crates/tui/src/config.rs +++ b/crates/tui/src/config.rs @@ -9281,6 +9281,9 @@ fn apply_env_overrides_unlocked(config: &mut Config, policy: ConfigEnvironmentPo .map(str::to_string) .collect(); } + // `DEEPSEEK_YOLO` is a read-only deprecated alias of `CODEWHALE_YOLO` + // (removable in 0.10 per issue #5443); `CODEWHALE_YOLO` wins when both + // are set. if let Ok(value) = std::env::var("CODEWHALE_YOLO").or_else(|_| std::env::var("DEEPSEEK_YOLO")) { config.yolo = Some(value == "1" || value.eq_ignore_ascii_case("true")); } diff --git a/crates/tui/src/config/tests.rs b/crates/tui/src/config/tests.rs index 9f5bfb7475..e73129d4e9 100644 --- a/crates/tui/src/config/tests.rs +++ b/crates/tui/src/config/tests.rs @@ -1430,6 +1430,52 @@ fn apply_env_overrides_sets_search_api_key() { ); } +#[test] +fn apply_env_overrides_yolo_prefers_codewhale_and_keeps_deepseek_alias() { + let _guard = lock_test_env(); + let codewhale_prev = env::var_os("CODEWHALE_YOLO"); + let deepseek_prev = env::var_os("DEEPSEEK_YOLO"); + let mut config = Config::default(); + + // Only the canonical name is set. + unsafe { + env::set_var("CODEWHALE_YOLO", "true"); + env::remove_var("DEEPSEEK_YOLO"); + } + apply_env_overrides(&mut config, ConfigEnvironmentPolicy::Runtime); + assert_eq!( + config.yolo, + Some(true), + "CODEWHALE_YOLO=true must enable the yolo posture" + ); + + // Only the deprecated alias is set: it must keep working through 0.9.x. + unsafe { + env::remove_var("CODEWHALE_YOLO"); + env::set_var("DEEPSEEK_YOLO", "true"); + } + apply_env_overrides(&mut config, ConfigEnvironmentPolicy::Runtime); + assert_eq!( + config.yolo, + Some(true), + "DEEPSEEK_YOLO remains a read-only deprecated alias until 0.10 (#5443)" + ); + + // Both set: the canonical name wins. + unsafe { env::set_var("CODEWHALE_YOLO", "false") }; + apply_env_overrides(&mut config, ConfigEnvironmentPolicy::Runtime); + assert_eq!( + config.yolo, + Some(false), + "CODEWHALE_YOLO must win over the deprecated DEEPSEEK_YOLO alias" + ); + + unsafe { + EnvGuard::restore_var("CODEWHALE_YOLO", codewhale_prev); + EnvGuard::restore_var("DEEPSEEK_YOLO", deepseek_prev); + } +} + #[test] fn structural_config_load_keeps_safe_environment_overrides_but_omits_secret_values() { let _guard = lock_test_env(); diff --git a/crates/tui/src/lib.rs b/crates/tui/src/lib.rs index 0057cd59b5..43700db22d 100644 --- a/crates/tui/src/lib.rs +++ b/crates/tui/src/lib.rs @@ -2342,8 +2342,8 @@ async fn run_async_main_dispatch( explicit_provider, explicit_model, ); - // The `deepseek` launcher forwards `--yolo` to this binary via - // the DEEPSEEK_YOLO env var (which the config loader folds into + // A launcher can forward `--yolo` to this binary via the + // CODEWHALE_YOLO env var (which the config loader folds into // `config.yolo`), not as a CLI flag. Honour either source. let yolo = cli.yolo || config.yolo.unwrap_or(false); let env_tool_surface = exec_tool_surface_from_env(); @@ -10974,8 +10974,8 @@ async fn run_interactive_with_notice( } }); - // The `deepseek` launcher forwards `--yolo` to this binary via the - // DEEPSEEK_YOLO env var (config.yolo), not as a CLI flag. Honour either. + // A launcher can forward `--yolo` to this binary via the CODEWHALE_YOLO + // env var (config.yolo), not as a CLI flag. Honour either. let yolo = cli.yolo || config.yolo.unwrap_or(false); tui::run_tui( diff --git a/docs/REBRAND.md b/docs/REBRAND.md index 1292b71525..ff9ddd489b 100644 --- a/docs/REBRAND.md +++ b/docs/REBRAND.md @@ -55,11 +55,15 @@ the legacy directory automatically. Anything that targets the DeepSeek provider API stays exactly as it was: - **Environment variables**: `DEEPSEEK_API_KEY`, `DEEPSEEK_BASE_URL`, - `DEEPSEEK_MODEL`, `DEEPSEEK_PROVIDER`, `DEEPSEEK_PROFILE`, `DEEPSEEK_YOLO`, + `DEEPSEEK_MODEL`, `DEEPSEEK_PROVIDER`, `DEEPSEEK_PROFILE`, `DEEPSEEK_LOG_LEVEL`, plus the existing `DEEPSEEK_TUI_*` runtime knobs (`DEEPSEEK_TUI_BIN`, `DEEPSEEK_TUI_RELEASE_BASE_URL`, etc.). They're kept for backward compatibility; renaming them would break every shell rc on the planet. +- **`DEEPSEEK_YOLO`**: now deprecated, but still read as an alias of + `CODEWHALE_YOLO` through 0.9.x so existing scripts keep working (when both + are set, `CODEWHALE_YOLO` wins). It is removed in 0.10 (#5443); use + `CODEWHALE_YOLO` in new scripts. - **Model IDs**: `deepseek-v4-pro`, `deepseek-v4-flash`, and the legacy aliases `deepseek-chat` and `deepseek-reasoner`. - **Hosts**: `api.deepseek.com` (global). The legacy typo host diff --git a/docs/id/REBRAND.md b/docs/id/REBRAND.md index 9e9528e165..1b55b674c5 100644 --- a/docs/id/REBRAND.md +++ b/docs/id/REBRAND.md @@ -42,5 +42,6 @@ Berkas dan direktori Anda yang ada seperti `~/.deepseek/config.toml`, `~/.deepse ## Apa yang TIDAK Berubah Semua hal yang berkaitan dengan API penyedia DeepSeek tetap berjalan persis seperti sebelumnya: -- **Variabel Lingkungan**: `DEEPSEEK_API_KEY`, `DEEPSEEK_BASE_URL`, `DEEPSEEK_MODEL`, `DEEPSEEK_PROVIDER`, `DEEPSEEK_PROFILE`, `DEEPSEEK_YOLO`, dll. tetap didukung sepenuhnya. +- **Variabel Lingkungan**: `DEEPSEEK_API_KEY`, `DEEPSEEK_BASE_URL`, `DEEPSEEK_MODEL`, `DEEPSEEK_PROVIDER`, `DEEPSEEK_PROFILE`, dll. tetap didukung sepenuhnya. +- **`DEEPSEEK_YOLO`**: kini usang, tetapi masih dibaca sebagai alias dari `CODEWHALE_YOLO` selama 0.9.x agar skrip lama tetap berjalan (jika keduanya diisi, `CODEWHALE_YOLO` yang menang). Dihapus di 0.10 (#5443); gunakan `CODEWHALE_YOLO` untuk skrip baru. - **Konfigurasi Penyedia**: Pengaturan rute `[providers.deepseek]` pada `config.toml` tetap valid.