use edgequake_llm::CopilotModel;
pub fn copilot_model_id_reject_reason(model_id: &str) -> Option<&'static str> {
let id = model_id.trim().trim_start_matches("copilot/");
if id.is_empty() || id.eq_ignore_ascii_case("auto") {
return None;
}
if id.ends_with("-picker") || id.contains("flash-picker") {
return Some(
"Copilot picker/routing models (names ending in `-picker`) cannot be used as the agent model. Try `/model copilot/auto` or a chat-capable model such as `copilot/gpt-4.1-mini`.",
);
}
None
}
fn supports_endpoint(model: &CopilotModel, endpoint: &str) -> bool {
model
.supported_endpoints
.as_ref()
.map(|endpoints| {
endpoints.is_empty()
|| endpoints
.iter()
.any(|candidate| candidate.eq_ignore_ascii_case(endpoint))
})
.unwrap_or(true)
}
pub fn copilot_model_is_agent_selectable(model: &CopilotModel) -> bool {
if copilot_model_id_reject_reason(&model.id).is_some() {
return false;
}
let picker_enabled = model.model_picker_enabled.unwrap_or(true);
let is_chat = model
.capabilities
.as_ref()
.and_then(|capabilities| capabilities.model_type.as_deref())
.map(|model_type| model_type.eq_ignore_ascii_case("chat"))
.unwrap_or(true);
picker_enabled && is_chat && supports_endpoint(model, "/chat/completions")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rejects_picker_suffix_ids() {
assert!(copilot_model_id_reject_reason("mai-code-1-flash-picker").is_some());
assert!(copilot_model_id_reject_reason("copilot/mai-code-1-flash-picker").is_some());
assert!(copilot_model_id_reject_reason("copilot/auto").is_none());
}
#[test]
fn filters_copilot_catalog_entries() {
let response: edgequake_llm::CopilotModelsResponse =
serde_json::from_value(serde_json::json!({
"data": [
{
"id": "gpt-4.1",
"model_picker_enabled": true,
"supported_endpoints": ["/chat/completions"],
"capabilities": { "type": "chat" }
},
{
"id": "mai-code-1-flash-picker",
"model_picker_enabled": true,
"supported_endpoints": ["/chat/completions"],
"capabilities": { "type": "chat" }
},
{
"id": "gpt-5.4",
"model_picker_enabled": true,
"supported_endpoints": ["/responses"],
"capabilities": { "type": "chat" }
}
]
}))
.expect("copilot response");
let selectable: Vec<_> = response
.data
.iter()
.filter(|model| copilot_model_is_agent_selectable(model))
.map(|model| model.id.as_str())
.collect();
assert_eq!(selectable, vec!["gpt-4.1"]);
}
}