Skip to main content

vtcode_config/constants/models/
openai.rs

1pub const DEFAULT_MODEL: &str = "gpt-5.6-sol";
2pub const SUPPORTED_MODELS: &[&str] = &[
3    GPT,
4    GPT_6_ASTRA,
5    GPT_6_SOL,
6    GPT_6_1_SOL,
7    GPT_6_LUNA,
8    "gpt-5.6",       // GPT-5.6 alias (routes to gpt-5.6-sol)
9    "gpt-5.6-sol",   // GPT-5.6 Sol flagship model
10    "gpt-5.6-terra", // GPT-5.6 Terra balanced model
11    "gpt-5.6-luna",  // GPT-5.6 Luna efficient model
12    "gpt-5.1",       // GPT-5.3 Codex optimized for agentic coding with xhigh reasoning support
13    "gpt-5.1-mini",
14    "gpt-oss-20b",
15    "gpt-oss-120b",
16];
17
18/// Models that require the OpenAI Responses API
19pub const RESPONSES_API_MODELS: &[&str] = &[
20    GPT,
21    GPT_6_ASTRA,
22    GPT_6_SOL,
23    GPT_6_1_SOL,
24    GPT_6_LUNA,
25    GPT_5_6,
26    GPT_5_6_SOL,
27    GPT_5_6_TERRA,
28    GPT_5_6_LUNA,
29    GPT_5_1,
30    GPT_5_6_SOL,
31    GPT_5_1_MINI,
32];
33
34/// Models that support the OpenAI reasoning parameter payload
35pub const REASONING_MODELS: &[&str] = &[
36    GPT,
37    GPT_6_ASTRA,
38    GPT_6_SOL,
39    GPT_6_1_SOL,
40    GPT_6_LUNA,
41    GPT_5_6,
42    GPT_5_6_SOL,
43    GPT_5_6_TERRA,
44    GPT_5_6_LUNA,
45    GPT_5_1,
46    GPT_5_6_SOL,
47];
48
49/// Models that support the native OpenAI `service_tier` request parameter.
50pub(crate) const SERVICE_TIER_MODELS: &[&str] = RESPONSES_API_MODELS;
51
52/// Models that do not expose structured tool calling on the OpenAI platform
53pub const TOOL_UNAVAILABLE_MODELS: &[&str] = &[];
54
55/// GPT-OSS models that use harmony tokenization
56pub const HARMONY_MODELS: &[&str] = &[GPT_OSS_20B, GPT_OSS_120B];
57
58/// Models that reject non-streaming requests on the OpenAI API. The provider
59/// advertises no non-streaming capability for them and coerces generation to
60/// an internally-streamed request (see `OpenAIProvider::requires_streaming_responses`).
61pub const STREAMING_REQUIRED_MODELS: &[&str] = &[GPT, GPT_5_6_SOL, GPT_5_6_LUNA];
62
63// Convenience constants for commonly used models
64pub const GPT: &str = "gpt";
65pub const GPT_6_ASTRA: &str = "gpt-6-astra";
66pub const GPT_6_SOL: &str = "gpt-6-sol";
67pub const GPT_6_1_SOL: &str = "gpt-6.1-sol";
68pub const GPT_6_LUNA: &str = "gpt-6-luna";
69pub const GPT_5_6_SOL: &str = "gpt-5.6-sol";
70pub const GPT_5_6_TERRA: &str = "gpt-5.6-terra";
71pub const GPT_5_6_LUNA: &str = "gpt-5.6-luna";
72pub const GPT_5_6: &str = "gpt-5.6";
73pub const GPT_5_1: &str = "gpt-5.1";
74pub const GPT_5_1_MINI: &str = "gpt-5.1-mini";
75pub const GPT_OSS_20B: &str = "gpt-oss-20b";
76pub const GPT_OSS_120B: &str = "gpt-oss-120b";
77
78// Deprecated constants retained for backward compatibility in tests and internal code
79pub const GPT_5: &str = "gpt-5";
80pub const GPT_5_MINI: &str = "gpt-5-mini";
81pub const GPT_5_NANO: &str = "gpt-5-nano";
82pub const GPT_5_CODEX: &str = "gpt-5-codex";
83pub(crate) const GPT_5_1_CODEX: &str = "gpt-5.1-codex";
84pub(crate) const GPT_5_1_CODEX_MAX: &str = "gpt-5.1-codex-max";
85pub(crate) const GPT_5_1_CODEX_MINI: &str = "gpt-5.1-codex-mini";
86pub const GPT_5_2_CODEX: &str = "gpt-5.2-codex";
87const CODEX_MINI_LATEST: &str = "codex-mini-latest";
88pub const O3: &str = "o3";
89pub const O4_MINI: &str = "o4-mini";
90
91/// Mapping of deprecated OpenAI model IDs to their recommended replacements.
92///
93/// Mappings follow the official OpenAI deprecation table:
94/// <https://developers.openai.com/api/docs/deprecations>.
95/// Replacements are chosen from models currently in `SUPPORTED_MODELS`.
96pub const DEPRECATED_MODEL_REPLACEMENTS: &[(&str, &str, &str)] = &[
97    // (deprecated_id, replacement_id, human-readable reason)
98    // GPT-5 / o3 family — shut down Dec 11, 2026
99    (GPT_5, "gpt-5.6-sol", "GPT-5 is deprecated; use GPT-5.6 Sol for frontier work"),
100    (GPT_5_MINI, "gpt-5.6-terra", "GPT-5 Mini is deprecated; use GPT-5.6 Terra for balanced tasks"),
101    (GPT_5_NANO, "gpt-5.6-luna", "GPT-5 Nano is deprecated; use GPT-5.6 Luna for lightweight tasks"),
102    (O3, "gpt-5.6-sol", "o3 is deprecated; use GPT-5.6 Sol for reasoning tasks"),
103    (O4_MINI, "gpt-5.6-terra", "o4-mini is deprecated; use GPT-5.6 Terra for fast reasoning"),
104    // Codex variants — shut down July 23, 2026 (Apr 1, 2026 for 5.x/5.1.x).
105    // Per OpenAI/GitHub Copilot deprecation notices, the direct successor is
106    // gpt-5.3-codex (the current Codex-optimised model).
107    (GPT_5_CODEX, GPT_5_6_SOL, "GPT-5 Codex is deprecated; use GPT-5.3 Codex for agentic coding"),
108    (GPT_5_1_CODEX, GPT_5_6_SOL, "GPT-5.1 Codex is deprecated; use GPT-5.3 Codex for agentic coding"),
109    (
110        GPT_5_1_CODEX_MAX,
111        GPT_5_6_SOL,
112        "GPT-5.1 Codex Max is deprecated; use GPT-5.3 Codex for long-running coding",
113    ),
114    (
115        GPT_5_1_CODEX_MINI,
116        GPT_5_6_SOL,
117        "GPT-5.1 Codex Mini is deprecated; use GPT-5.3 Codex for cost-effective coding",
118    ),
119    (GPT_5_2_CODEX, GPT_5_6_SOL, "GPT-5.2 Codex is deprecated; use GPT-5.3 Codex for agentic coding"),
120    (
121        CODEX_MINI_LATEST,
122        GPT_5_6_SOL,
123        "codex-mini-latest is deprecated; use GPT-5.3 Codex for cost-effective coding",
124    ),
125];
126
127/// Returns the recommended replacement for a deprecated OpenAI model, if known.
128///
129/// Returns `Some((replacement_id, reason))` when the model is a known
130/// deprecated ID, or `None` when it is either current or unrecognized.
131#[must_use]
132pub fn deprecated_model_replacement(model: &str) -> Option<(&'static str, &'static str)> {
133    DEPRECATED_MODEL_REPLACEMENTS
134        .iter()
135        .find(|(deprecated, _, _)| *deprecated == model)
136        .map(|(_, replacement, reason)| (*replacement, *reason))
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn deprecated_gpt5_maps_to_gpt56_sol() {
145        let (replacement, reason) = deprecated_model_replacement(GPT_5).expect("gpt-5 is deprecated");
146        assert_eq!(replacement, "gpt-5.6-sol");
147        assert!(reason.contains("GPT-5.6 Sol"));
148    }
149
150    #[test]
151    fn deprecated_codex_models_map_to_gpt53_codex() {
152        for (deprecated, expected) in [
153            (GPT_5_CODEX, GPT_5_6_SOL),
154            (GPT_5_1_CODEX, GPT_5_6_SOL),
155            (GPT_5_1_CODEX_MAX, GPT_5_6_SOL),
156            (GPT_5_1_CODEX_MINI, GPT_5_6_SOL),
157            (GPT_5_2_CODEX, GPT_5_6_SOL),
158            (CODEX_MINI_LATEST, GPT_5_6_SOL),
159        ] {
160            let (replacement, _reason) =
161                deprecated_model_replacement(deprecated).unwrap_or_else(|| panic!("{deprecated} should be deprecated"));
162            assert_eq!(replacement, expected, "replacement for {deprecated}");
163        }
164    }
165
166    #[test]
167    fn current_models_have_no_replacement() {
168        assert!(deprecated_model_replacement(GPT_5_6_SOL).is_none());
169        assert!(deprecated_model_replacement(GPT_5_6_SOL).is_none());
170        assert!(deprecated_model_replacement("gpt-5.6-sol").is_none());
171    }
172
173    #[test]
174    fn unknown_models_have_no_replacement() {
175        assert!(deprecated_model_replacement("nonexistent-model").is_none());
176        assert!(deprecated_model_replacement("").is_none());
177    }
178
179    #[test]
180    fn supported_models_excludes_deprecated() {
181        let deprecated_ids: Vec<&str> = DEPRECATED_MODEL_REPLACEMENTS.iter().map(|(id, _, _)| *id).collect();
182        for deprecated in &deprecated_ids {
183            assert!(
184                !SUPPORTED_MODELS.contains(deprecated),
185                "deprecated model {deprecated} should not appear in SUPPORTED_MODELS"
186            );
187        }
188    }
189
190    #[test]
191    fn replacement_targets_are_current_models() {
192        // Every replacement must be a currently supported (non-deprecated) model.
193        for (_, replacement, _) in DEPRECATED_MODEL_REPLACEMENTS {
194            assert!(
195                SUPPORTED_MODELS.contains(replacement),
196                "replacement target {replacement} must be in SUPPORTED_MODELS"
197            );
198            assert!(
199                deprecated_model_replacement(replacement).is_none(),
200                "replacement target {replacement} must not itself be deprecated"
201            );
202        }
203    }
204}