mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
## Why #29683 exposes managed defaults for new-thread model settings through `configRequirements/read` without applying them server-wide. The TUI is an app-server client, so it should explicitly consume those defaults when it creates a fresh thread. This lets plain `codex` start on the managed model while preserving the existing ability to change model settings within the thread. ## What changed - Read `requirements.models.newThread` during TUI app-server bootstrap. - Apply the managed model, reasoning effort, and service tier to the initial fresh thread and subsequent `/new` or `/clear` threads. - Keep explicit launch overrides above the managed defaults. - Normalize the managed `fast` service tier to the `priority` request value. - Leave resumed and forked threads unchanged. The application logic lives in a small TUI-only module; app-server `thread/start` behavior remains unchanged for other clients. ## User experience - Plain `codex` starts with the managed new-thread settings. - A user can still change settings with `/model` or the existing service-tier controls. - Starting another fresh thread reapplies the managed defaults. - Explicit launch choices such as `codex -m <model>` continue to win. ## Validation - `just test -p codex-tui managed_new_thread_defaults` - `just fix -p codex-tui` Depends on #29683.
111 lines
3.5 KiB
Rust
111 lines
3.5 KiB
Rust
use super::*;
|
|
use crate::legacy_core::config::ConfigBuilder;
|
|
use codex_protocol::openai_models::ReasoningEffort;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
async fn test_config() -> Config {
|
|
let codex_home = tempfile::tempdir().expect("tempdir").keep();
|
|
ConfigBuilder::default()
|
|
.codex_home(codex_home)
|
|
.build()
|
|
.await
|
|
.expect("config")
|
|
}
|
|
|
|
fn defaults() -> NewThreadModelDefaults {
|
|
NewThreadModelDefaults {
|
|
model: Some("managed-model".to_string()),
|
|
model_reasoning_effort: Some(ReasoningEffort::High),
|
|
service_tier: Some("fast".to_string()),
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn applies_managed_defaults_to_a_new_thread_config() {
|
|
let mut actual = test_config().await;
|
|
actual.model = Some("configured-model".to_string());
|
|
actual.model_reasoning_effort = Some(ReasoningEffort::Low);
|
|
actual.service_tier = Some("flex".to_string());
|
|
let mut expected = actual.clone();
|
|
expected.model = Some("managed-model".to_string());
|
|
expected.model_reasoning_effort = Some(ReasoningEffort::High);
|
|
expected.service_tier = Some(ServiceTier::Fast.request_value().to_string());
|
|
|
|
apply_managed_new_thread_defaults(
|
|
&mut actual,
|
|
Some(&defaults()),
|
|
&[],
|
|
&ConfigOverrides::default(),
|
|
);
|
|
|
|
assert_eq!(actual, expected);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn explicit_model_skips_managed_model_and_reasoning_effort() {
|
|
let mut actual = test_config().await;
|
|
actual.model = Some("explicit-model".to_string());
|
|
actual.model_reasoning_effort = None;
|
|
actual.service_tier = Some("flex".to_string());
|
|
let mut expected = actual.clone();
|
|
expected.service_tier = Some(ServiceTier::Fast.request_value().to_string());
|
|
let harness_overrides = ConfigOverrides {
|
|
model: Some("explicit-model".to_string()),
|
|
..ConfigOverrides::default()
|
|
};
|
|
|
|
apply_managed_new_thread_defaults(&mut actual, Some(&defaults()), &[], &harness_overrides);
|
|
|
|
assert_eq!(actual, expected);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn explicit_reasoning_effort_skips_managed_model_and_reasoning_effort() {
|
|
let mut actual = test_config().await;
|
|
actual.model = Some("configured-model".to_string());
|
|
actual.model_reasoning_effort = Some(ReasoningEffort::Low);
|
|
actual.service_tier = Some("flex".to_string());
|
|
let mut expected = actual.clone();
|
|
expected.service_tier = Some(ServiceTier::Fast.request_value().to_string());
|
|
let cli_kv_overrides = vec![(
|
|
"model_reasoning_effort".to_string(),
|
|
TomlValue::String("low".to_string()),
|
|
)];
|
|
|
|
apply_managed_new_thread_defaults(
|
|
&mut actual,
|
|
Some(&defaults()),
|
|
&cli_kv_overrides,
|
|
&ConfigOverrides::default(),
|
|
);
|
|
|
|
assert_eq!(actual, expected);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn explicit_launch_overrides_take_precedence() {
|
|
let mut actual = test_config().await;
|
|
actual.model = Some("explicit-model".to_string());
|
|
actual.model_reasoning_effort = Some(ReasoningEffort::Low);
|
|
actual.service_tier = Some("flex".to_string());
|
|
let expected = actual.clone();
|
|
let cli_kv_overrides = vec![(
|
|
"model_reasoning_effort".to_string(),
|
|
TomlValue::String("low".to_string()),
|
|
)];
|
|
let harness_overrides = ConfigOverrides {
|
|
model: Some("explicit-model".to_string()),
|
|
service_tier: Some(Some("flex".to_string())),
|
|
..ConfigOverrides::default()
|
|
};
|
|
|
|
apply_managed_new_thread_defaults(
|
|
&mut actual,
|
|
Some(&defaults()),
|
|
&cli_kv_overrides,
|
|
&harness_overrides,
|
|
);
|
|
|
|
assert_eq!(actual, expected);
|
|
}
|