From 2cb697e9f42a5b5988e5d3ab73ffb18fd112eb20 Mon Sep 17 00:00:00 2001 From: Liam <33645555+lj3954@users.noreply.github.com> Date: Thu, 28 Aug 2025 15:32:15 +0000 Subject: [PATCH] copilot: Use updated Copilot Chat model schema (#33007) Use the latest Copilot Chat model schema, matching what is used in VSCode, to get more data about available models than was previously accessible. Replace hardcoded default model (gpt-4.1) with the default model included in JSON. Other data like premium request multipliers could be used in the future if Zed implements a way for models to display additional details about themselves, such as with tooltips on hover. Release Notes: - N/A --------- Co-authored-by: Peter Tripp --- crates/copilot/src/copilot_chat.rs | 52 +++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/crates/copilot/src/copilot_chat.rs b/crates/copilot/src/copilot_chat.rs index e8e2251648e4b941fe616b4524337fe565513950..bfddba0e2f8a41e3ed234b21ee52454d104c9dd2 100644 --- a/crates/copilot/src/copilot_chat.rs +++ b/crates/copilot/src/copilot_chat.rs @@ -62,12 +62,6 @@ impl CopilotChatConfiguration { } } -// Copilot's base model; defined by Microsoft in premium requests table -// This will be moved to the front of the Copilot model list, and will be used for -// 'fast' requests (e.g. title generation) -// https://docs.github.com/en/copilot/managing-copilot/monitoring-usage-and-entitlements/about-premium-requests -const DEFAULT_MODEL_ID: &str = "gpt-4.1"; - #[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq)] #[serde(rename_all = "lowercase")] pub enum Role { @@ -101,22 +95,39 @@ where Ok(models) } -#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Model { + billing: ModelBilling, capabilities: ModelCapabilities, id: String, name: String, policy: Option, vendor: ModelVendor, + is_chat_default: bool, + // The model with this value true is selected by VSCode copilot if a premium request limit is + // reached. Zed does not currently implement this behaviour + is_chat_fallback: bool, model_picker_enabled: bool, } +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +struct ModelBilling { + is_premium: bool, + multiplier: f64, + // List of plans a model is restricted to + // Field is not present if a model is available for all plans + #[serde(default)] + restricted_to: Option>, +} + #[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] struct ModelCapabilities { family: String, #[serde(default)] limits: ModelLimits, supports: ModelSupportedFeatures, + #[serde(rename = "type")] + model_type: String, } #[derive(Default, Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] @@ -602,6 +613,7 @@ async fn get_models( .into_iter() .filter(|model| { model.model_picker_enabled + && model.capabilities.model_type.as_str() == "chat" && model .policy .as_ref() @@ -610,9 +622,7 @@ async fn get_models( .dedup_by(|a, b| a.capabilities.family == b.capabilities.family) .collect(); - if let Some(default_model_position) = - models.iter().position(|model| model.id == DEFAULT_MODEL_ID) - { + if let Some(default_model_position) = models.iter().position(|model| model.is_chat_default) { let default_model = models.remove(default_model_position); models.insert(0, default_model); } @@ -630,7 +640,9 @@ async fn request_models( .uri(models_url.as_ref()) .header("Authorization", format!("Bearer {}", api_token)) .header("Content-Type", "application/json") - .header("Copilot-Integration-Id", "vscode-chat"); + .header("Copilot-Integration-Id", "vscode-chat") + .header("Editor-Version", "vscode/1.103.2") + .header("x-github-api-version", "2025-05-01"); let request = request_builder.body(AsyncBody::empty())?; @@ -801,6 +813,10 @@ mod tests { let json = r#"{ "data": [ { + "billing": { + "is_premium": false, + "multiplier": 0 + }, "capabilities": { "family": "gpt-4", "limits": { @@ -814,6 +830,8 @@ mod tests { "type": "chat" }, "id": "gpt-4", + "is_chat_default": false, + "is_chat_fallback": false, "model_picker_enabled": false, "name": "GPT 4", "object": "model", @@ -825,6 +843,16 @@ mod tests { "some-unknown-field": 123 }, { + "billing": { + "is_premium": true, + "multiplier": 1, + "restricted_to": [ + "pro", + "pro_plus", + "business", + "enterprise" + ] + }, "capabilities": { "family": "claude-3.7-sonnet", "limits": { @@ -848,6 +876,8 @@ mod tests { "type": "chat" }, "id": "claude-3.7-sonnet", + "is_chat_default": false, + "is_chat_fallback": false, "model_picker_enabled": true, "name": "Claude 3.7 Sonnet", "object": "model",