Skip to main content

litellm_rs/core/providers/github_copilot/
model_info.rs

1//! GitHub Copilot Model Information
2//!
3//! Contains model metadata and capability information for GitHub Copilot models.
4
5/// GitHub Copilot model information
6#[derive(Debug, Clone)]
7pub struct GitHubCopilotModel {
8    /// Model ID used in API calls
9    pub model_id: &'static str,
10    /// Display name for the model
11    pub display_name: &'static str,
12    /// Context window size
13    pub max_context_length: u32,
14    /// Maximum output tokens
15    pub max_output_length: Option<u32>,
16    /// Whether the model supports tools/function calling
17    pub supports_tools: bool,
18    /// Whether the model supports vision/images
19    pub supports_multimodal: bool,
20    /// Whether the model supports streaming
21    pub supports_streaming: bool,
22    /// Whether the model supports extended thinking/reasoning
23    pub supports_reasoning: bool,
24}
25
26/// Static model registry for GitHub Copilot
27/// These are models accessible through the GitHub Copilot API
28static GITHUB_COPILOT_MODELS: &[GitHubCopilotModel] = &[
29    // Exact IDs documented by GitHub's CLI reference, reviewed 2026-10-03.
30    // https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-command-reference
31    // Retired and utility-only models are not advertised as selectable models.
32    // https://docs.github.com/en/copilot/reference/ai-models/supported-models
33    // Limits depend on the account/client; zero/None means not published here.
34    GitHubCopilotModel {
35        model_id: "gpt-6-astra",
36        display_name: "GPT-6 Astra",
37        max_context_length: 0,
38        max_output_length: None,
39        supports_tools: true,
40        supports_multimodal: true,
41        supports_streaming: true,
42        supports_reasoning: true,
43    },
44    GitHubCopilotModel {
45        model_id: "gpt-6-sol",
46        display_name: "GPT-6 Sol",
47        max_context_length: 0,
48        max_output_length: None,
49        supports_tools: true,
50        supports_multimodal: true,
51        supports_streaming: true,
52        supports_reasoning: true,
53    },
54    GitHubCopilotModel {
55        model_id: "gpt-6-luna",
56        display_name: "GPT-6 Luna",
57        max_context_length: 0,
58        max_output_length: None,
59        supports_tools: true,
60        supports_multimodal: true,
61        supports_streaming: true,
62        supports_reasoning: true,
63    },
64    GitHubCopilotModel {
65        model_id: "claude-opus-5.5",
66        display_name: "Claude Opus 5.5",
67        max_context_length: 0,
68        max_output_length: None,
69        supports_tools: true,
70        supports_multimodal: true,
71        supports_streaming: true,
72        supports_reasoning: true,
73    },
74];
75
76/// Get all available GitHub Copilot models
77pub fn get_available_models() -> Vec<&'static str> {
78    GITHUB_COPILOT_MODELS.iter().map(|m| m.model_id).collect()
79}
80
81/// Get model information by ID
82pub fn get_model_info(model_id: &str) -> Option<&'static GitHubCopilotModel> {
83    GITHUB_COPILOT_MODELS
84        .iter()
85        .find(|m| m.model_id == model_id)
86}
87
88/// Check if a model supports vision
89#[cfg(test)]
90pub fn is_vision_model(model_id: &str) -> bool {
91    get_model_info(model_id).is_some_and(|m| m.supports_multimodal)
92}
93
94/// Check if a model supports tools
95#[cfg(test)]
96pub fn supports_tools(model_id: &str) -> bool {
97    get_model_info(model_id).is_some_and(|m| m.supports_tools)
98}
99
100/// Check if a model supports reasoning/extended thinking
101pub fn supports_reasoning(model_id: &str) -> bool {
102    get_model_info(model_id).is_some_and(|m| m.supports_reasoning)
103}
104
105/// Check if a model is a Claude model (for special handling)
106pub fn is_claude_model(model_id: &str) -> bool {
107    model_id.to_lowercase().contains("claude")
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_get_available_models() {
116        let models = get_available_models();
117        assert!(!models.is_empty());
118        assert!(models.contains(&"gpt-6-sol"));
119        assert!(models.contains(&"claude-opus-5.5"));
120        assert!(models.contains(&"gpt-6-astra"));
121    }
122
123    #[test]
124    fn retired_and_utility_only_models_are_not_advertised() {
125        for id in [
126            "gpt-4o",
127            "gpt-4o-mini",
128            "gpt-4-turbo",
129            "o1-preview",
130            "o1-mini",
131            "o1",
132            "o3-mini",
133            "claude-3.5-sonnet",
134            "claude-3-7-sonnet",
135            "claude-sonnet-4",
136            "gpt-5.1-codex",
137            "gemini-2.0-flash",
138        ] {
139            assert!(get_model_info(id).is_none(), "{id}");
140            assert!(!get_available_models().contains(&id), "{id}");
141        }
142    }
143
144    #[test]
145    fn test_get_model_info() {
146        let model = get_model_info("gpt-6-sol");
147        assert!(model.is_some());
148        let model = model.unwrap();
149        assert_eq!(model.model_id, "gpt-6-sol");
150        assert!(model.supports_tools);
151        assert!(model.supports_multimodal);
152    }
153
154    #[test]
155    fn test_get_model_info_nonexistent() {
156        let model = get_model_info("nonexistent-model");
157        assert!(model.is_none());
158    }
159
160    #[test]
161    fn test_is_vision_model() {
162        assert!(is_vision_model("gpt-6-sol"));
163        assert!(is_vision_model("claude-opus-5.5"));
164        assert!(!is_vision_model("unknown"));
165    }
166
167    #[test]
168    fn test_supports_tools() {
169        assert!(supports_tools("gpt-6-sol"));
170        assert!(supports_tools("claude-opus-5.5"));
171        assert!(!supports_tools("unknown"));
172    }
173
174    #[test]
175    fn test_supports_reasoning() {
176        assert!(supports_reasoning("gpt-6-astra"));
177        assert!(supports_reasoning("gpt-6-luna"));
178        assert!(supports_reasoning("claude-opus-5.5"));
179        assert!(!supports_reasoning("unknown"));
180    }
181
182    #[test]
183    fn test_is_claude_model() {
184        assert!(is_claude_model("claude-opus-5.5"));
185        assert!(is_claude_model("claude-3-7-sonnet"));
186        assert!(is_claude_model("claude-sonnet-4"));
187        assert!(!is_claude_model("gpt-6-sol"));
188        assert!(!is_claude_model("gpt-6-astra"));
189    }
190}