Add GPT-5 support through OpenAI API (#35822)

Richard Feldman created

(This PR does not add GPT-5 to Zed Pro, but rather adds access if you're
using your own OpenAI API key.)

<img width="772" height="333" alt="Screenshot 2025-08-07 at 2 23 18 PM"
src="https://github.com/user-attachments/assets/42e75082-118a-4737-89b6-a740ae33b169"
/>

---

**NOTE:** If your API key is not through a verified organization, you
may see this error:

<img width="549" height="253" alt="Screenshot 2025-08-07 at 2 04 54 PM"
src="https://github.com/user-attachments/assets/d0b6d739-9c39-4af3-88d7-0c9609b0e6ba"
/>

Even if your org is verified, you still may not have access to GPT-5, in
which case you could see this error:

<img width="543" height="98" alt="Screenshot 2025-08-07 at 2 09 18 PM"
src="https://github.com/user-attachments/assets/e3ed31e3-2a11-4f07-8f3c-5b410fbe4540"
/>

One way to test if you're in this situation is to visit
https://platform.openai.com/chat/edit?models=gpt-5 and see if you get
the same "you don't have access to GPT-5" error on OpenAI's official
playground. It looks like this:

<img width="581" height="196" alt="Screenshot 2025-08-07 at 2 15 25 PM"
src="https://github.com/user-attachments/assets/ea1454ca-3c10-4703-8126-c02cb92a34f2"
/>

Release Notes:

- Added GPT-5, as well as its mini and nano variants. To use this, you
need to have an OpenAI API key configured via the `OPENAI_API_KEY`
environment variable.

Change summary

crates/language_models/src/provider/open_ai.rs |  4 +++
crates/open_ai/src/open_ai.rs                  | 26 +++++++++++++++++++
2 files changed, 29 insertions(+), 1 deletion(-)

Detailed changes

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

@@ -674,6 +674,10 @@ pub fn count_open_ai_tokens(
             | Model::O3
             | Model::O3Mini
             | Model::O4Mini => tiktoken_rs::num_tokens_from_messages(model.id(), &messages),
+            // GPT-5 models don't have tiktoken support yet; fall back on gpt-4o tokenizer
+            Model::Five | Model::FiveMini | Model::FiveNano => {
+                tiktoken_rs::num_tokens_from_messages("gpt-4o", &messages)
+            }
         }
         .map(|tokens| tokens as u64)
     })

crates/open_ai/src/open_ai.rs 🔗

@@ -74,6 +74,12 @@ pub enum Model {
     O3,
     #[serde(rename = "o4-mini")]
     O4Mini,
+    #[serde(rename = "gpt-5")]
+    Five,
+    #[serde(rename = "gpt-5-mini")]
+    FiveMini,
+    #[serde(rename = "gpt-5-nano")]
+    FiveNano,
 
     #[serde(rename = "custom")]
     Custom {
@@ -105,6 +111,9 @@ impl Model {
             "o3-mini" => Ok(Self::O3Mini),
             "o3" => Ok(Self::O3),
             "o4-mini" => Ok(Self::O4Mini),
+            "gpt-5" => Ok(Self::Five),
+            "gpt-5-mini" => Ok(Self::FiveMini),
+            "gpt-5-nano" => Ok(Self::FiveNano),
             invalid_id => anyhow::bail!("invalid model id '{invalid_id}'"),
         }
     }
@@ -123,6 +132,9 @@ impl Model {
             Self::O3Mini => "o3-mini",
             Self::O3 => "o3",
             Self::O4Mini => "o4-mini",
+            Self::Five => "gpt-5",
+            Self::FiveMini => "gpt-5-mini",
+            Self::FiveNano => "gpt-5-nano",
             Self::Custom { name, .. } => name,
         }
     }
@@ -141,6 +153,9 @@ impl Model {
             Self::O3Mini => "o3-mini",
             Self::O3 => "o3",
             Self::O4Mini => "o4-mini",
+            Self::Five => "gpt-5",
+            Self::FiveMini => "gpt-5-mini",
+            Self::FiveNano => "gpt-5-nano",
             Self::Custom {
                 name, display_name, ..
             } => display_name.as_ref().unwrap_or(name),
@@ -161,6 +176,9 @@ impl Model {
             Self::O3Mini => 200_000,
             Self::O3 => 200_000,
             Self::O4Mini => 200_000,
+            Self::Five => 272_000,
+            Self::FiveMini => 272_000,
+            Self::FiveNano => 272_000,
             Self::Custom { max_tokens, .. } => *max_tokens,
         }
     }
@@ -182,6 +200,9 @@ impl Model {
             Self::O3Mini => Some(100_000),
             Self::O3 => Some(100_000),
             Self::O4Mini => Some(100_000),
+            Self::Five => Some(128_000),
+            Self::FiveMini => Some(128_000),
+            Self::FiveNano => Some(128_000),
         }
     }
 
@@ -197,7 +218,10 @@ impl Model {
             | Self::FourOmniMini
             | Self::FourPointOne
             | Self::FourPointOneMini
-            | Self::FourPointOneNano => true,
+            | Self::FourPointOneNano
+            | Self::Five
+            | Self::FiveMini
+            | Self::FiveNano => true,
             Self::O1 | Self::O3 | Self::O3Mini | Self::O4Mini | Model::Custom { .. } => false,
         }
     }