use crate::brain::provider_spec::{ProviderKey, normalize_in};
use crate::config::Config;
use crate::config::types::AgentConfig;
use crate::utils::plan_files::PlanModeState;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ModeOverride {
pub provider: Option<String>,
pub model: Option<String>,
}
pub fn override_for(state: PlanModeState, agent: &AgentConfig) -> Option<ModeOverride> {
let (provider, model) = if state.is_editing() {
(agent.plan_provider.as_ref(), agent.plan_model.as_ref())
} else if state == PlanModeState::Active {
(
agent.execute_provider.as_ref(),
agent.execute_model.as_ref(),
)
} else {
return None;
};
if provider.is_none() && model.is_none() {
return None;
}
Some(ModeOverride {
provider: provider.cloned(),
model: model.cloned(),
})
}
pub fn normalized_override_for(state: PlanModeState, config: &Config) -> Option<ModeOverride> {
let over = override_for(state, &config.agent)?;
let Some(provider) = over.provider.as_deref() else {
return Some(over);
};
let key = if state.is_editing() {
ProviderKey::PLAN
} else {
ProviderKey::EXECUTE
};
let pair = normalize_in(config, key, provider, over.model.as_deref());
if let Some(note) = pair.note.as_deref() {
tracing::warn!(
"Plan-mode routing: {} corrected to '{}': {note}",
key.provider,
pair.provider
);
}
Some(ModeOverride {
provider: Some(pair.provider),
model: pair.model,
})
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlanModeSwap {
pub original_provider: String,
pub original_model: String,
pub applied_provider: String,
pub applied_model: String,
}
impl PlanModeSwap {
pub fn still_applied(&self, provider: &str, model: &str) -> bool {
self.applied_provider == provider && self.applied_model == model
}
}