fix(providers): update stale Atlascloud/Ollama capability tests to the generic model-based path; add bare Moonshot/MiniMax/Z.ai model rows (kimi-k2.6, kimi-for-coding, minimax-m3, glm-5.1, glm-5v-turbo) mirroring vendor-prefixed rows; add Moonshot capability + engine capacity tests (#3023, #1310)
Co-Authored-By: Claude <noreply@anthropic.com> https://claude.ai/code/session_018zaP8vUfTAsrE38L6h6fw5
This commit is contained in:
@@ -10756,14 +10756,30 @@ model = "deepseek-ai/deepseek-v4-pro"
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_capability_atlascloud_custom_model_is_chat_completions_without_thinking() {
|
||||
fn provider_capability_atlascloud_v4_model_resolves_model_metadata() {
|
||||
// #3023: Atlascloud uses the generic model-based path, so its default
|
||||
// DeepSeek V4 model resolves the real V4 metadata instead of the old
|
||||
// hardcoded legacy floor.
|
||||
let cap = provider_capability(ApiProvider::Atlascloud, "deepseek-ai/deepseek-v4-flash");
|
||||
assert_eq!(
|
||||
cap.context_window,
|
||||
crate::models::LEGACY_DEEPSEEK_CONTEXT_WINDOW_TOKENS
|
||||
crate::models::DEEPSEEK_V4_CONTEXT_WINDOW_TOKENS
|
||||
);
|
||||
assert_eq!(cap.max_output, 4096);
|
||||
assert!(!cap.thinking_supported);
|
||||
assert_eq!(cap.max_output, 384_000);
|
||||
assert!(cap.thinking_supported);
|
||||
assert!(!cap.cache_telemetry_supported);
|
||||
assert_eq!(
|
||||
cap.request_payload_mode,
|
||||
RequestPayloadMode::ChatCompletions
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_capability_moonshot_default_model_resolves_kimi_metadata() {
|
||||
let cap = provider_capability(ApiProvider::Moonshot, DEFAULT_MOONSHOT_MODEL);
|
||||
assert_eq!(cap.context_window, 262_144);
|
||||
assert_eq!(cap.max_output, 262_144);
|
||||
assert!(cap.thinking_supported);
|
||||
assert!(!cap.cache_telemetry_supported);
|
||||
assert_eq!(
|
||||
cap.request_payload_mode,
|
||||
@@ -10788,8 +10804,26 @@ model = "deepseek-ai/deepseek-v4-pro"
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_capability_ollama_is_openai_compatible_without_thinking() {
|
||||
fn provider_capability_ollama_deepseek_tag_uses_deepseek_heuristic() {
|
||||
// #3023: known model families resolve through models.rs lookups even
|
||||
// on Ollama — a legacy DeepSeek tag gets the 128K heuristic window.
|
||||
let cap = provider_capability(ApiProvider::Ollama, "deepseek-v3.1:671b");
|
||||
assert_eq!(
|
||||
cap.context_window,
|
||||
crate::models::LEGACY_DEEPSEEK_CONTEXT_WINDOW_TOKENS
|
||||
);
|
||||
assert_eq!(cap.max_output, 4096);
|
||||
assert!(!cap.thinking_supported);
|
||||
assert!(!cap.cache_telemetry_supported);
|
||||
assert_eq!(
|
||||
cap.request_payload_mode,
|
||||
RequestPayloadMode::ChatCompletions
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_capability_ollama_unknown_model_falls_back_to_8192() {
|
||||
let cap = provider_capability(ApiProvider::Ollama, "llama3.2:3b");
|
||||
assert_eq!(cap.context_window, 8192);
|
||||
assert_eq!(cap.max_output, 4096);
|
||||
assert!(!cap.thinking_supported);
|
||||
|
||||
@@ -2863,6 +2863,33 @@ async fn pre_request_refresh_skips_compaction_below_normal_threshold() {
|
||||
assert_eq!(engine.session.messages.len(), before_len);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capacity_observation_uses_bare_kimi_context_window() {
|
||||
// #3023: capacity math reads models::context_window_for_model directly,
|
||||
// so bare Moonshot ids must resolve their real window, not the 128K
|
||||
// legacy fallback.
|
||||
let mut engine = build_engine_with_capacity(CapacityControllerConfig::default());
|
||||
engine.session.model = "kimi-k2.6".to_string();
|
||||
engine.session.messages.push(Message {
|
||||
role: "user".to_string(),
|
||||
content: vec![ContentBlock::Text {
|
||||
text: "x".repeat(40_000),
|
||||
cache_control: None,
|
||||
}],
|
||||
});
|
||||
|
||||
let estimated = engine.estimated_input_tokens() as f64;
|
||||
let turn = TurnContext::new(1);
|
||||
let observation = engine.capacity_observation(&turn);
|
||||
|
||||
let expected = estimated / 262_144.0;
|
||||
assert!(
|
||||
(observation.context_used_ratio - expected).abs() < 1e-9,
|
||||
"context_used_ratio must use kimi-k2.6's 262,144-token window (got {})",
|
||||
observation.context_used_ratio
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn pre_request_refresh_invoked_when_medium_risk() {
|
||||
let capacity = CapacityControllerConfig {
|
||||
|
||||
@@ -263,9 +263,13 @@ fn known_context_window_for_model(model_lower: &str) -> Option<u32> {
|
||||
| "qwen/qwen3.6-27b"
|
||||
| "tencent/hy3-preview"
|
||||
| "moonshotai/kimi-k2.6"
|
||||
| "moonshotai/kimi-k2.6:free" => Some(262_144),
|
||||
"z-ai/glm-5.1" | "z-ai/glm-5v-turbo" => Some(202_752),
|
||||
"minimax/minimax-m3" | "qwen/qwen3.6-flash" | "qwen/qwen3.6-plus" => Some(1_000_000),
|
||||
| "moonshotai/kimi-k2.6:free"
|
||||
| "kimi-k2.6"
|
||||
| "kimi-for-coding" => Some(262_144),
|
||||
"z-ai/glm-5.1" | "z-ai/glm-5v-turbo" | "glm-5.1" | "glm-5v-turbo" => Some(202_752),
|
||||
"minimax/minimax-m3" | "minimax-m3" | "qwen/qwen3.6-flash" | "qwen/qwen3.6-plus" => {
|
||||
Some(1_000_000)
|
||||
}
|
||||
"xiaomi/mimo-v2.5-pro" | "xiaomi/mimo-v2.5" | "mimo-v2.5-pro" | "mimo-v2.5" => {
|
||||
Some(1_000_000)
|
||||
}
|
||||
@@ -285,10 +289,12 @@ pub fn max_output_tokens_for_model(model: &str) -> Option<u32> {
|
||||
return Some(384_000);
|
||||
}
|
||||
match lower.as_str() {
|
||||
"arcee-ai/trinity-large-thinking" | "trinity-large-thinking" | "moonshotai/kimi-k2.6" => {
|
||||
Some(262_144)
|
||||
}
|
||||
"minimax/minimax-m3" => Some(524_288),
|
||||
"arcee-ai/trinity-large-thinking"
|
||||
| "trinity-large-thinking"
|
||||
| "moonshotai/kimi-k2.6"
|
||||
| "kimi-k2.6"
|
||||
| "kimi-for-coding" => Some(262_144),
|
||||
"minimax/minimax-m3" | "minimax-m3" => Some(524_288),
|
||||
"qwen/qwen3.6-35b-a3b" | "qwen/qwen3.6-27b" => Some(262_140),
|
||||
"qwen/qwen3.6-flash" | "qwen/qwen3.6-max-preview" | "qwen/qwen3.6-plus" => Some(65_536),
|
||||
"xiaomi/mimo-v2.5-pro" | "xiaomi/mimo-v2.5" | "mimo-v2.5-pro" | "mimo-v2.5" => {
|
||||
@@ -322,7 +328,9 @@ pub fn model_supports_reasoning(model: &str) -> bool {
|
||||
| "google/gemma-4-26b-a4b-it:free"
|
||||
| "moonshotai/kimi-k2.6"
|
||||
| "moonshotai/kimi-k2.6:free"
|
||||
| "kimi-k2.6"
|
||||
| "minimax/minimax-m3"
|
||||
| "minimax-m3"
|
||||
| "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free"
|
||||
| "qwen/qwen3.6-flash"
|
||||
| "qwen/qwen3.6-35b-a3b"
|
||||
@@ -335,6 +343,7 @@ pub fn model_supports_reasoning(model: &str) -> bool {
|
||||
| "mimo-v2.5-pro"
|
||||
| "mimo-v2.5"
|
||||
| "z-ai/glm-5.1"
|
||||
| "glm-5.1"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -587,6 +596,31 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bare_provider_model_ids_mirror_vendor_prefixed_rows() {
|
||||
// Direct-provider routes (Moonshot, MiniMax, Z.ai) serve bare model
|
||||
// ids without the OpenRouter vendor prefix; both spellings must
|
||||
// resolve identical metadata (#1310 ride-along on #3023).
|
||||
for (model, expected_window) in [
|
||||
("kimi-k2.6", 262_144),
|
||||
("minimax-m3", 1_000_000),
|
||||
("glm-5.1", 202_752),
|
||||
] {
|
||||
assert_eq!(context_window_for_model(model), Some(expected_window));
|
||||
assert!(model_supports_reasoning(model));
|
||||
}
|
||||
assert_eq!(context_window_for_model("kimi-for-coding"), Some(262_144));
|
||||
assert!(!model_supports_reasoning("kimi-for-coding"));
|
||||
assert_eq!(context_window_for_model("glm-5v-turbo"), Some(202_752));
|
||||
assert!(!model_supports_reasoning("glm-5v-turbo"));
|
||||
assert_eq!(max_output_tokens_for_model("kimi-k2.6"), Some(262_144));
|
||||
assert_eq!(
|
||||
max_output_tokens_for_model("kimi-for-coding"),
|
||||
Some(262_144)
|
||||
);
|
||||
assert_eq!(max_output_tokens_for_model("minimax-m3"), Some(524_288));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deepseek_models_with_k_suffix_use_hint() {
|
||||
assert_eq!(context_window_for_model("deepseek-v3.2-32k"), Some(32_000));
|
||||
|
||||
Reference in New Issue
Block a user