mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-11 01:51:34 -10:00
fix(config): honor a configured default_text_model; align the unset default with deepseek-flash
The V4.1 change moved the DeepSeek default to deepseek-flash but left two paths disagreeing: - Route/thread resolution ignored an operator-configured default_text_model and fell through to the provider catalog default, so a config declaring default_text_model = "deepseek-v4-pro" created new threads on flash (runtime_threads::create_thread -> resolve_runtime_route_for_identity with no selector). - The TUI DEFAULT_TEXT_MODEL still said deepseek-v4-pro, so a bare config reported one default and routed another. Resolution now mirrors provider_default_model precedence: the active provider configured default wins over the provider catalog default. The constant moves to deepseek-flash, matching DEFAULT_DEEPSEEK_MODEL in codewhale-config and the shipped default. The composed-frame test now pins the #6041 contract: the duplicate session reading is suppressed on a first turn and returns once a finished turn makes the totals differ. Evidence (each: 1 passed; 0 failed): - config::tests::remembered_deepseek_cn_and_layered_root_models_keep_their_precedence - doctor_endpoint_tests::doctor_api_target_reports_default_endpoint - doctor_endpoint_tests::doctor_api_target_routes_deepseek_cn_alias_to_beta_endpoint - runtime_api::configured_model_api_tests::scoped_runtime_selections_leave_device_memory_unchanged - runtime_api::tests::fleet_status_runtime_api_exposes_state_and_actions - tui::ui::frame::one_owner_tests::composed_frame_paints_each_fact_in_exactly_one_row - tui::ui::tests::provider_switch_to_deepseek_canonicalizes_openrouter_default_model - tui::ui::tests::provider_switch_to_deepseek_drops_stale_xiaomi_root_base_url
This commit is contained in:
1 parent
93e511c2c7
commit
7d144a286b
3 files changed
+46
-11
No files matched your search
@@ -6,7 +6,7 @@
|
||||
//! re-exported from `crate::config` via `pub use models::*;`, so every existing
|
||||
//! `crate::config::<CONST>` path keeps resolving unchanged (#3311).
|
||||
|
||||
pub const DEFAULT_TEXT_MODEL: &str = "deepseek-v4-pro";
|
||||
pub const DEFAULT_TEXT_MODEL: &str = "deepseek-flash";
|
||||
pub const DEFAULT_DEEPSEEK_BASE_URL: &str = "https://api.deepseek.com/beta";
|
||||
pub const DEFAULT_DEEPSEEK_ANTHROPIC_MODEL: &str = DEFAULT_TEXT_MODEL;
|
||||
pub const DEFAULT_DEEPSEEK_ANTHROPIC_BASE_URL: &str = "https://api.deepseek.com/anthropic";
|
||||
|
||||
@@ -748,7 +748,19 @@ pub(crate) fn resolve_runtime_route_for_identity(
|
||||
)?;
|
||||
let provider = identity.provider;
|
||||
let mut route_config = prepared_route_config(config, &identity, model_selector);
|
||||
let saved_provider_model = configured_model_for_route(&route_config, provider);
|
||||
// The operator's effective default for the active provider is the
|
||||
// route's default too; mirror `provider_default_model` precedence so a
|
||||
// configured choice is not displaced by the provider catalog's default
|
||||
// (deepseek-flash). `auto` stays the resolver's sentinel.
|
||||
let configured_default = (provider == config.api_provider()
|
||||
&& config.default_text_model.is_some())
|
||||
.then(|| config.default_model())
|
||||
.filter(|model| {
|
||||
let model = model.trim();
|
||||
!model.is_empty() && !model.eq_ignore_ascii_case("auto")
|
||||
});
|
||||
let saved_provider_model = configured_model_for_route(&route_config, provider)
|
||||
.or(configured_default.as_deref());
|
||||
// #5034: with no explicit selector and no saved model, a Codex route
|
||||
// would fall back to the resolver's static seed offering. Prefer the
|
||||
// live Codex roster head so a provider switch lands on the current
|
||||
|
||||
@@ -211,20 +211,43 @@ fn composed_frame_paints_each_fact_in_exactly_one_row() {
|
||||
// session half needs 120 columns here, the turn half 160. Each
|
||||
// paints in exactly one row wherever it paints. The metrics line
|
||||
// carries no repository, branch or provider.
|
||||
let clock_facts: &[(u16, &str)] =
|
||||
&[(120, "worked 1m 15s"), (160, "sub-agents underway 1m 15s")];
|
||||
for (needs, needle) in clock_facts {
|
||||
if width < *needs {
|
||||
continue;
|
||||
}
|
||||
assert!(rows[posture].contains(needle), "{}", rows[posture]);
|
||||
// First turn: the turn half names the phase and stays; the session
|
||||
// reading is the identical duration, so it is suppressed rather than
|
||||
// stated twice (#6041) — the turn half is the one that needs 160
|
||||
// columns, so a narrower row keeps the affordances and no stopwatch.
|
||||
let turn_needle = "sub-agents underway 1m 15s";
|
||||
if width >= 160 {
|
||||
assert!(rows[posture].contains(turn_needle), "{}", rows[posture]);
|
||||
assert_eq!(
|
||||
count_rows_containing(&rows, needle),
|
||||
count_rows_containing(&rows, turn_needle),
|
||||
1,
|
||||
"{width}x{height}: {needle:?} paints in exactly one row:\n{}",
|
||||
"{width}x{height}: {turn_needle:?} paints in exactly one row:\n{}",
|
||||
rows.join("\n")
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!rows[posture].contains("worked 1m 15s"),
|
||||
"{width}x{height}: the duplicate session reading must not be stated: {}",
|
||||
rows[posture]
|
||||
);
|
||||
// After a finished turn the totals differ and the worked chip
|
||||
// returns: 1m of finished turns plus the live 1m 15s reads 2m 15s.
|
||||
let mut worked = working_app();
|
||||
worked.cumulative_turn_duration = Duration::from_secs(60);
|
||||
let rows = draw(&mut worked, width, height);
|
||||
if width >= 120 {
|
||||
let worked_needle = "worked 2m 15s";
|
||||
assert!(rows[posture].contains(worked_needle), "{}", rows[posture]);
|
||||
assert_eq!(
|
||||
count_rows_containing(&rows, worked_needle),
|
||||
1,
|
||||
"{width}x{height}: {worked_needle:?} paints in exactly one row:\n{}",
|
||||
rows.join("\n")
|
||||
);
|
||||
}
|
||||
if width >= 160 {
|
||||
assert!(rows[posture].contains(turn_needle), "{}", rows[posture]);
|
||||
}
|
||||
assert!(!rows[metrics].contains('⑂'), "{}", rows[metrics]);
|
||||
// No dead key hints anywhere in the frame.
|
||||
for row in &rows {
|
||||
|
||||
Reference in new issue
Block a user