use edgequake_llm::{ChatMessage, CompletionOptions, LLMProvider, ToolDefinition};
pub const MODEL_NOT_SUPPORTED_HINT: &str = "GitHub Copilot rejected this model for agent chat+tools (model_not_supported). \
Try `/model copilot/auto` or `/model copilot/gpt-4.1-mini`. \
Run `edgecrab doctor` — the agent ping exercises chat+tools, not plain completion.";
pub fn is_copilot_model_not_supported_error(message: &str) -> bool {
let lower = message.to_ascii_lowercase();
lower.contains("model_not_supported")
}
pub fn agent_probe_tools() -> Vec<ToolDefinition> {
vec![ToolDefinition::function(
"ping",
"Health-check stub; do not call unless asked.",
serde_json::json!({
"type": "object",
"properties": {},
"additionalProperties": false
}),
)]
}
pub async fn probe_agent_chat_with_tools(provider: &dyn LLMProvider) -> Result<(), String> {
let messages = [ChatMessage::user(
"Reply with exactly the single word PONG. Do not call any tools.",
)];
let tools = agent_probe_tools();
let opts = CompletionOptions {
temperature: Some(0.0),
max_tokens: Some(32),
..Default::default()
};
provider
.chat_with_tools(&messages, &tools, None, Some(&opts))
.await
.map(|_| ())
.map_err(|err| err.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn detects_model_not_supported_errors() {
assert!(is_copilot_model_not_supported_error(
r#"{"error":{"code":"model_not_supported","message":"nope"}}"#
));
assert!(!is_copilot_model_not_supported_error("bad credentials"));
}
}