use super::*;
#[test]
fn substituted_fallback_is_pinned_to_a_group_that_can_serve() {
let dir = tempfile::tempdir().expect("tempdir");
let _guard = AidHomeGuard::set(dir.path());
crate::routing::rate_limit::mark_group_rate_limited(
&AgentKind::OpenCode,
None,
"opencode",
"Insufficient balance.",
);
crate::routing::rate_limit::mark_group_rate_limited(
&AgentKind::Antigravity,
None,
"gemini",
"Individual quota reached. Please upgrade your subscription to increase your limits. Resets in 59m21s.",
);
let store = Arc::new(Store::open_memory().expect("store"));
let mut args = RunArgs {
agent_name: "opencode".to_string(),
prompt: "Add unit tests".to_string(),
model: Some("opencode/deepseek-v4-pro".to_string()),
cascade: vec!["agy".to_string()],
..Default::default()
};
let setup = resolve_agent_setup(&store, &mut args, None).expect("should substitute opencode to agy");
assert_eq!(setup.agent_kind, AgentKind::Antigravity);
let model = setup.effective_model.expect("substitution must pin a healthy model");
assert_ne!(
crate::agent::model_group::model_group(AgentKind::Antigravity, Some(&model)),
Some("gemini"),
"the exhausted gemini family must not be dispatched"
);
assert!(setup.substituted_from.is_some());
}
#[test]
fn substituted_aid_resolved_pin_survives_served_list_miss() {
let dir = tempfile::tempdir().expect("tempdir");
let _guard = AidHomeGuard::set(dir.path());
crate::routing::rate_limit::mark_group_rate_limited(
&AgentKind::OpenCode,
None,
"opencode",
"Insufficient balance.",
);
crate::routing::rate_limit::mark_group_rate_limited(
&AgentKind::Antigravity,
None,
"gemini",
"Individual quota reached. Please upgrade your subscription to increase your limits. Resets in 59m21s.",
);
let _served = crate::agent::model_validation::MockServedModelsGuard::set(
AgentKind::Antigravity,
Some(vec![
"gemini-3.1-pro-high".to_string(),
"gemini-3.6-flash-high".to_string(),
"gemini-3.6-flash-low".to_string(),
]),
);
let store = Arc::new(Store::open_memory().expect("store"));
let mut args = RunArgs {
agent_name: "opencode".to_string(),
prompt: "Add unit tests".to_string(),
model: Some("opencode/deepseek-v4-pro".to_string()),
cascade: vec!["agy".to_string()],
..Default::default()
};
let setup = resolve_agent_setup(&store, &mut args, None).expect("should substitute opencode to agy");
assert_eq!(setup.agent_kind, AgentKind::Antigravity);
let model = setup
.effective_model
.expect("aid-resolved pin must survive a served-list miss on a substituted route");
assert_ne!(
crate::agent::model_group::model_group(AgentKind::Antigravity, Some(&model)),
Some("gemini"),
"the exhausted gemini family must not be dispatched"
);
assert!(setup.substituted_from.is_some());
}
#[test]
fn substituted_route_keeps_agent_config_model_despite_served_list_miss() {
let dir = tempfile::tempdir().expect("tempdir");
let _guard = AidHomeGuard::set(dir.path());
crate::routing::rate_limit::mark_rate_limited(
&AgentKind::Grok,
None,
&format!(
"Individual quota reached. Please upgrade your subscription. try again at {}.",
crate::routing::rate_limit::test_future_recovery_time()
),
);
crate::config::agent::save_agent_default_model("codex", Some("codex-stale-config-model"))
.expect("save codex default");
let _served = crate::agent::model_validation::MockServedModelsGuard::set(
AgentKind::Codex,
Some(vec!["gpt-5.4".to_string()]),
);
let store = Arc::new(Store::open_memory().expect("store"));
let mut args = RunArgs {
agent_name: "grok".to_string(),
prompt: "Add unit tests".to_string(),
cascade: vec!["codex".to_string()],
..Default::default()
};
let setup = resolve_agent_setup(&store, &mut args, None).expect("should substitute grok to codex");
assert_eq!(setup.agent_kind, AgentKind::Codex);
assert_eq!(
setup.effective_model.as_deref(),
Some("codex-stale-config-model"),
"an agent-config model on a substituted route must survive a served-list miss"
);
assert!(setup.substituted_from.is_some());
}