Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
Expand Down
6 changes: 5 additions & 1 deletion crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Comment on lines +7051 to 7056
.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
}
}),
Expand Down
47 changes: 47 additions & 0 deletions crates/config/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Comment on lines +2026 to +2029
// 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();
Expand Down
3 changes: 3 additions & 0 deletions crates/tui/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
}
Comment on lines +9284 to 9289
Expand Down
46 changes: 46 additions & 0 deletions crates/tui/src/config/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Comment on lines +1436 to +1439
// 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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[WARNING] TUI yolo alias test reuses mutated Config, second scenario not isolated

The test creates one config and mutates it with the first apply_env_overrides, leaving config.yolo = Some(true). The second scenario removes CODEWHALE_YOLO and sets DEEPSEEK_YOLO, but if the alias were not read, apply_env_overrides would not overwrite the existing config.yolo, so the assertion would still pass. This makes the test unable to catch regressions where DEEPSEEK_YOLO is no longer honored. Reset config to Config::default() before the second scenario (or use a fresh Config).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reset config before testing the deprecated alias so the assertion does not pass because of state left by the previous case.

Suggested change
// Only the deprecated alias is set: it must keep working through 0.9.x.
// Reset config so this scenario doesn't inherit yolo=true from the previous case.
config = Config::default();
// 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();
Expand Down
8 changes: 4 additions & 4 deletions crates/tui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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(
Expand Down
6 changes: 5 additions & 1 deletion docs/REBRAND.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion docs/id/REBRAND.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Loading