Add GPT-5.2 support (#44656)

Richard Feldman created

<img width="429" height="188" alt="Screenshot 2025-12-11 at 3 45 26 PM"
src="https://github.com/user-attachments/assets/fe9f1b86-7268-4c63-a8c2-75ac671012c9"
/>


Release Notes:

- Added GPT-5.2 support when using your own OpenAI key

Change summary

crates/language_models/src/provider/open_ai.rs | 8 ++++++--
crates/open_ai/src/open_ai.rs                  | 8 ++++++++
2 files changed, 14 insertions(+), 2 deletions(-)

Detailed changes

crates/language_models/src/provider/open_ai.rs 🔗

@@ -278,6 +278,7 @@ impl LanguageModel for OpenAiLanguageModel {
             | Model::FiveMini
             | Model::FiveNano
             | Model::FivePointOne
+            | Model::FivePointTwo
             | Model::O1
             | Model::O3
             | Model::O4Mini => true,
@@ -675,8 +676,11 @@ pub fn count_open_ai_tokens(
             | Model::O4Mini
             | Model::Five
             | Model::FiveMini
-            | Model::FiveNano => tiktoken_rs::num_tokens_from_messages(model.id(), &messages), // GPT-5.1 doesn't have tiktoken support yet; fall back on gpt-4o tokenizer
-            Model::FivePointOne => tiktoken_rs::num_tokens_from_messages("gpt-5", &messages),
+            | Model::FiveNano => tiktoken_rs::num_tokens_from_messages(model.id(), &messages),
+            // GPT-5.1 and 5.2 don't have dedicated tiktoken support; use gpt-5 tokenizer
+            Model::FivePointOne | Model::FivePointTwo => {
+                tiktoken_rs::num_tokens_from_messages("gpt-5", &messages)
+            }
         }
         .map(|tokens| tokens as u64)
     })

crates/open_ai/src/open_ai.rs 🔗

@@ -87,6 +87,8 @@ pub enum Model {
     FiveNano,
     #[serde(rename = "gpt-5.1")]
     FivePointOne,
+    #[serde(rename = "gpt-5.2")]
+    FivePointTwo,
     #[serde(rename = "custom")]
     Custom {
         name: String,
@@ -123,6 +125,7 @@ impl Model {
             "gpt-5-mini" => Ok(Self::FiveMini),
             "gpt-5-nano" => Ok(Self::FiveNano),
             "gpt-5.1" => Ok(Self::FivePointOne),
+            "gpt-5.2" => Ok(Self::FivePointTwo),
             invalid_id => anyhow::bail!("invalid model id '{invalid_id}'"),
         }
     }
@@ -145,6 +148,7 @@ impl Model {
             Self::FiveMini => "gpt-5-mini",
             Self::FiveNano => "gpt-5-nano",
             Self::FivePointOne => "gpt-5.1",
+            Self::FivePointTwo => "gpt-5.2",
             Self::Custom { name, .. } => name,
         }
     }
@@ -167,6 +171,7 @@ impl Model {
             Self::FiveMini => "gpt-5-mini",
             Self::FiveNano => "gpt-5-nano",
             Self::FivePointOne => "gpt-5.1",
+            Self::FivePointTwo => "gpt-5.2",
             Self::Custom {
                 name, display_name, ..
             } => display_name.as_ref().unwrap_or(name),
@@ -191,6 +196,7 @@ impl Model {
             Self::FiveMini => 272_000,
             Self::FiveNano => 272_000,
             Self::FivePointOne => 400_000,
+            Self::FivePointTwo => 400_000,
             Self::Custom { max_tokens, .. } => *max_tokens,
         }
     }
@@ -216,6 +222,7 @@ impl Model {
             Self::FiveMini => Some(128_000),
             Self::FiveNano => Some(128_000),
             Self::FivePointOne => Some(128_000),
+            Self::FivePointTwo => Some(128_000),
         }
     }
 
@@ -244,6 +251,7 @@ impl Model {
             | Self::Five
             | Self::FiveMini
             | Self::FivePointOne
+            | Self::FivePointTwo
             | Self::FiveNano => true,
             Self::O1 | Self::O3 | Self::O3Mini | Self::O4Mini | Model::Custom { .. } => false,
         }