Fix two issues with reasoning support in the Copilot provider:
- Responses API path: use the user's thinking_effort setting instead of
hardcoding Medium effort
- Chat Completions path: compute and pass thinking_budget when thinking
is enabled, instead of unconditionally setting it to None
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes#52140
Release Notes:
- Fixed a bug where copilot wouldn't use the thinking level the user's
have set
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
Fixes#54140
When `RulesLibrary::count_tokens` calls
`CloudLanguageModel::count_tokens` for Google cloud models, it does so
inside a `cx.update` closure, which holds a mutable borrow on the global
`AppCell`. The Google provider branch then called
`token_provider.auth_context(&cx.to_async())`, which created a new
`AsyncApp` handle and tried to take a shared borrow on the same
`RefCell` — causing a "RefCell already mutably borrowed" panic.
This only affects Google models because they are the only provider that
counts tokens server-side via an HTTP request (requiring
authentication). The other providers (Anthropic, OpenAI, xAI) count
tokens locally using tiktoken, so they never call `auth_context` during
`count_tokens`.
The fix makes `CloudLlmTokenProvider::auth_context` generic over `impl
AppContext` instead of requiring `&AsyncApp`. This allows the
`count_tokens` call site to pass `&App` directly (which reads entities
without re-borrowing the `RefCell`), while all other call sites that
already pass `&AsyncApp` (e.g. `stream_completion`, `refresh_models`)
continue to work unchanged.
Release Notes:
- Fixed a crash ("RefCell already mutably borrowed") that could occur
when counting tokens with Google cloud language models.
<img width="767" height="428" alt="Screenshot 2026-04-16 at 11 29 13 AM"
src="https://github.com/user-attachments/assets/e8b450fa-aefc-4dec-a286-b211bd492011"
/>
Add Claude Opus 4.7 (`claude-opus-4-7`) to the anthropic, bedrock, and
opencode provider crates.
Key specs:
- 1M token context window
- 128k max output tokens
- Adaptive thinking support
- AWS Bedrock cross-region inference (global, US, EU, AU)
Release Notes:
- Added Claude Opus 4.7 as an available language model
Reimplements #36722 while fixing the race that required the revert in
#36932.
When no default model is configured, this picks an environment fallback
by authenticating all providers. It always prefers the Zed cloud
provider when it's authenticated, and waits for its models to load
before picking another provider as the fallback, so we don't flicker
from Zed models to Anthropic while sign-in is in flight.
The fallback is recomputed whenever provider state changes (via
`ProviderStateChanged`/`AddedProvider`/`RemovedProvider` events), so the
selection becomes correct as soon as cloud models arrive.
### What changed vs. the original PR
- `language_models::init` now owns `authenticate_all_providers`
(previously done in `LanguageModelPickerDelegate` and `agent`'s
`LanguageModels`).
- After all authentications settle, and on any subsequent provider state
change, `update_environment_fallback_model` recomputes the fallback.
- The fallback logic prefers Zed cloud: if the cloud provider is
authenticated, only use it (waiting for its models to load). Otherwise,
fall through to the first authenticated provider with a default or
recommended model.
- `LanguageModelRegistry::default_model()` falls back to
`environment_fallback_model` when no explicit default is set.
- Existing `Thread`s that are empty are updated to the new default when
`DefaultModelChanged` fires, so a blank thread started before sign-in
switches to Zed models once the user signs in.
Release Notes:
- agent: Automatically select a model when there's no selected model or configured default
It seems their verification got stricter, at least stricter than
Anthropics. Only set the output config if we have an effort.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#54036
Release Notes:
- copilot_chat: Fix invalid reasoning effort for some models.
Co-authored-by: John Tur <john-tur@outlook.com>
Closes#52717
Mistral's streaming API sometimes sends `"id": "null"` (the literal
string, not JSON null) in continuation chunks for tool calls. Our stream
handler treated this as a valid ID, overwriting the real tool call ID
from the first chunk. When the corrupted ID was sent back in the next
request, Mistral's API rejected it with "Tool call id has to be defined
in serving mode."
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed issue where Mistral models erroring out with "Tool call id has
to be defined" when using tools.
- `language_model` no longer depends on provider-specific crates such as
`anthropic` and `open_ai` (inverted dependency)
- `language_model_core` was extracted from `language_model` which
contains the types for the provider-specific crates to convert to/from.
- `gpui::SharedString` has been extracted into its own crate (still
exposed by `gpui`), so `language_model_core` and provider API crates
don't have to depend on `gpui`.
- Removes some unnecessary `&'static str` | `SharedString` -> `String`
-> `SharedString` conversions across the codebase.
- Extracts the core logic of the cloud `LanguageModelProvider` into its
own crate with simpler dependencies.
Release Notes:
- N/A
---------
Co-authored-by: John Tur <john-tur@outlook.com>
Some model like glm-5、kimi-k2.5 support reasoning, but require
reasoning_effort parameter
This pr add support for setting reasoing_effort for openai compatible
models
Tested using the following config:
```json
{
"language_models": {
"openai_compatible": {
"My LiteLLM": {
"available_models": [
{
"name": "glm-5",
"display_name": "glm-5",
"max_tokens": 73728,
"reasoning_effort": "low"
},
{
"name": "kimi-k2.5",
"display_name": "kimi-k2.5",
"max_tokens": 262144,
"reasoning_effort": "low"
}
]
}
}
}
}
```
Release Notes:
- Added a setting to control `reasoning_effort` in custom
OpenAI-compatible models
This PR decouples `language_model`'s dependence on Zed-specific
implementation details. In particular
* `credentials_provider` is split into a generic `credentials_provider`
crate that provides a trait, and `zed_credentials_provider` that
implements the said trait for Zed-specific providers and has functions
that can populate a global state with them
* `zed_env_vars` is split into a generic `env_var` crate that provides
generic tooling for managing env vars, and `zed_env_vars` that contains
Zed-specific statics
* `client` is now dependent on `language_model` and not vice versa
Release Notes:
- N/A
A couple of things that this PR wants to accomplish:
* remove dependency on `settings` crate from `language_model`
* refactor provider-specific code into submodules - to be honest, I
would go one step further and put all provider-specific bits in
`language_models` instead but I realise we have cloud logic in
`language_model` which uses those too making it tricky
* move anthropic-specific telemetry into `language_models` crate - I
think it makes more sense for it to be there
Anyhow, I would very appreciate if you could have a look @mikayla-maki
and @maxdeviant and lemme know what you think, if you would tweak
something, etc.
Release Notes:
- N/A
When debugging a remote SSH connection, I came across an unformatted
format string in the output log. I changed the raw `.context(fmt)` call
to a `.with_context(|| format!(fmt))`. I ran a quick sweep through the
codebase to identify and fix two other instances of the same issue.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
This PR moves the `CompletionIntent` enum from the `cloud_llm_client`
crate to the `language_model` crate, as it is no longer part of the
Cloud interface.
Release Notes:
- N/A
## Context
Ensure subagent threads build requests with the Subagent intent instead
of UserPrompt. This allows us to properly
attribute this as a tool call for certain providers instead of a user
request.
## Self-Review Checklist
<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- copilot_chat: Fix subagent requests being marked as user requests.
**Observed behavior:** Inline assistant failed for GPT-4.1,
Gemini, and other non-Anthropic models. Claude worked correctly because
Anthropic's API accepts `"any"` as a valid value.
## Fix
Renamed `ToolChoice::Any` → `ToolChoice::Required` in both
`copilot_chat.rs` and `responses.rs`, matching the convention used by
other OpenAI-compatible providers (`open_ai`, `lmstudio`,
`open_router`).
`copilot_chat::ToolChoice` is a wire type only for the
`/chat/completions`
path — Anthropic models go through `into_anthropic()` and never touch
it,
so no per-model logic is needed.
Also fixes the same serialization bug in `responses::ToolChoice`, which
was not covered by the original approach, and adds regression tests for
both.
## Affected models
- `gpt-4.1` via copilot_chat provider
- `gemini-*` via copilot_chat provider
- Likely affects all OpenAI-compatible models routed through
copilot_chat
## Screenshots
**Bug (only Claude works, Gemini and GPT-4.1 fail):**
<img width="598" height="209" alt="image"
src="https://github.com/user-attachments/assets/bbd418d9-7de3-4191-9ca9-fd1961534e23"
/>
**Fix:**
<img width="532" height="154" alt="image"
src="https://github.com/user-attachments/assets/86bb0f8e-67e6-4417-9b78-b1b7ad328e9e"
/>
**Result:** After the fix, all models work correctly via inline
assistant.
## Release Notes
- Fix inline assistant 400 errors for GPT-4.1, Gemini, and other
non-Anthropic models via the copilot_chat provider (`tool_choice` was
sending `"any"` instead of `"required"`)
## Context
I was getting some leak detection failures in evals and tracked it down
to these entities getting passed into observe/subscribe callbacks and
causing cycles.
Release Notes:
- N/A
Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
## Context
We seemed to have disabled it in #28056, because our agent did not
support parallel tool calls at the time.
## Self-Review Checklist
<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A or Added/Fixed/Improved ...
## Context
Deepseek seems to have started to return empty text deltas, which causes
issues cause their upstream API does not like empty text blocks to be
included in their request.
In practice this caused issues like `An assistant message with
'tool_calls' must be followed by tool messages responding to each
'tool_call_id'..., because the payload looked like this:
```
User {
content: "Call the now tool a bunch of times",
},
Assistant {
content: Some(
"",
),
},
Tool {
content: "The current datetime is 2026-03-23T13:21:24.084848+00:00.",
tool_call_id: "call_00_iozCfHXJAPR13XwHiAwJ9OEw",
},
```
Now we filter out that empty text, which seems to fix the issue. This
matches our implementation for OpenAI
Closes#51854
<!-- What does this PR do, and why? How is it expected to impact users?
Not just what changed, but what motivated it and why this approach.
Link to Linear issue (e.g., ENG-123) or GitHub issue (e.g., Closes#456)
if one exists — helps with traceability. -->
## How to Review
<!-- Help reviewers focus their attention:
- For small PRs: note what to focus on (e.g., "error handling in
foo.rs")
- For large PRs (>400 LOC): provide a guided tour — numbered list of
files/commits to read in order. (The `large-pr` label is applied
automatically.)
- See the review process guidelines for comment conventions -->
## Self-Review Checklist
<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- deepseek: Fixed issue with tool calling (`An assistant message with
'tool_calls' must be followed by tool messages responding to each
'tool_call_id'...`)
Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Per Opencode's website:
> Zen gives you access to a curated set of AI models that OpenCode has
tested and benchmarked specifically for coding agents. No need to worry
about inconsistent performance and quality, use validated models that
work.
> - [x] Testing select models and consulting their teams
> - [x] Working with providers to ensure they're delivered properly
> - [x] Benchmarking all model-provider combinations we recommend
There are so many models available, but only a few work well with coding
agents. Most providers configure them differently with varying results.
The models under the Zen umbrella typically have a more reliable
token(s) per second speed with minimal outages. The opencode ecosystem
has improved my workflow if not many others' !
Release Notes:
- Added [Opencode Zen](https://opencode.ai/zen) to list of providers
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
## Context
This PR fixes one of the issues in #51905, where model outputs are full
of errant `\` characters.
heres the problem: As the response is streamed back to zed, we
accumulate the message chunks and and need to convert those chunks to
valid json, to do that we use `partial_json_fixer::fix_json`, when the
last character of a chunk is `\`, the `fix_json` has to escape that
backslash, because its inside of a string (if it isn't, its invalid json
and the tool call will crash) and other wise you would end up escaping
the end `"` and everything would be messed up.
why is this a problem for zed:
T_0 is the output at some step.
T_1 is the output at the next step.
the `fix_json` system is meant to be used by replacing T_0 with T_1,
however in the editor, replacing the entirety of T_0 with T_1 would be
slow/cause flickering/etc.. so we calculate the difference between T_0
and T_1 and just add it to the current buffer state. So when a chunk
ends on `\`, we end up with something like `... end of line\\"}` at the
end of T_0,
in T_1, this becomes `... end of line\n ...`. then when we add the new
chunk from T_1, it just picks up after the \n because its tracking the
length to manage the deltas.
## How to Review
utils.rs:
fix_streamed_json => remove trailing backslashes from incoming json
streams so that `partial_json_fixer::fix_json` doesn't try to escape
them.
other files: call fix_streamed_json before passing to `serde_json`
I had claude write a bunch of tests while I was working on the fix,
which I have kept in for now, but the end functionality of
fix_streamed_json is really simple now, so maybe these arent really
needed.
## Videos
Behavior Before:
https://github.com/user-attachments/assets/f23f5579-b2e1-4d71-9e24-f15ea831de52
Behavior After:
https://github.com/user-attachments/assets/40acdc23-4522-4621-be28-895965f4f262
## Self-Review Checklist
<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- language_models: fixed partial json streaming
This adds support for the thinking toggle + reasoning effort for the
Anthropic provider
Release Notes:
- anthropic: Added support for selecting reasoning effort
---------
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
Release Notes:
- Support for Native Thinking toggle instead of model variants
---------
Co-authored-by: Ona <no-reply@ona.com>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
The conversations on Grok 4 were failing right away on the first message
in a conversation when using Zed provided model directly, but not the
xAI API directly.
The reason we were seeing this is that when sending the JSON schemas for
built-in tools to the cloud API, we didn't use the transform we use for
xAI in a BYOK context. The xAI API doesn't support the full JSON schema
spec, and specifically for the spawn_agent tool, we were generating a
`oneOf` type for a field. Applying that transformation in the cloud case
too fixes the issue.
Release Notes:
- Fixed broken (failing on first message) xAI models over the Zed
provider on profiles using the spawn_agent tool, including the default
Ask and Write profiles.
Co-authored-by: Neel <neel@zed.dev>
Allow function call outputs to carry either plain text or a list
of input content items, so image tool results are serialized as
image content instead of a raw base64 string.
Release Notes:
- N/A
We were sending the raw tool debug output as JSON to the model rather
than whatever the tool intended as content for the model.
Which meant we were sending unneeded information to the model, which
matters in the edit tool case.
Release Notes:
- N/A
### Split token display for xAI
Extends the split input/output token display (introduced in #46829 for
OpenAI) to all xAI models.
Instead of the combined `48k / 1M` token counter, xAI models now show:
- **↑** input tokens used / input token limit
- **↓** output tokens used / output token limit
#### Before
<img width="513" height="128" alt="Screenshot 2026-02-08 at 11 07 13 AM"
src="https://github.com/user-attachments/assets/14e5cb4a-9b5c-4081-bbfb-407a737bf234"
/>
#### After
<img width="610" height="126" alt="Screenshot 2026-02-08 at 11 05 36 AM"
src="https://github.com/user-attachments/assets/92396dcb-8905-4f87-9b9e-d8b0f63225ba"
/>
#### Changes
- **x_ai.rs** — Override `supports_split_token_display()` to return
`true` on `XAiLanguageModel`. All built-in Grok models already implement
`max_output_tokens()`, so no additional plumbing was needed.
- **cloud.rs** — Add `XAi` to the `matches!` pattern in
`CloudLanguageModel::supports_split_token_display()` so cloud-routed xAI
models also get the split display.
#### Tests
- `test_xai_supports_split_token_display` — Verifies all built-in Grok
model variants return `true` for split token display.
- `test_xai_models_have_max_output_tokens` — Validates all built-in Grok
models report `max_output_tokens` that is `Some`, positive, and less
than `max_token_count` (required for the UI to compute the input token
limit).
- `test_split_token_display_supported_providers` — Confirms the cloud
provider match pattern includes `OpenAi` and `XAi` while excluding
`Anthropic` and `Google`.
Release Notes:
- Changed the display of tokens for xAI models to reflect the
input/output limits.
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
## Summary
When no stop tokens are provided, Zed was sending an empty array
(`"stop": []`) to Ollama. This caused Ollama to override the model's
default stop tokens (defined in its Modelfile) with nothing, resulting
in models like rnj-1:8b generating infinitely with literal stop tokens
appearing in the output.
## Problem
Models with custom stop tokens in their Modelfile (like `<|eot_id|>` for
rnj-1:8b) would generate forever because:
1. Agent thread creates request with `stop: Vec::new()` (empty)
2. Ollama provider converts this to `stop: Some(vec![])`
3. Serializes as `"stop": []` in JSON
4. Ollama interprets this as "override default stop tokens with nothing"
5. Model generates forever, outputting stop tokens as literal text
## Solution
1. In `crates/language_models/src/provider/ollama.rs`:
- Only send `stop` when explicitly provided
- When empty, use `None` so the field is omitted from JSON
2. In `crates/ollama/src/ollama.rs`:
- Add `#[serde(skip_serializing_if = "Option::is_none")]` to all
`ChatOptions` fields
- Ensures `None` values are omitted, not serialized as `null`
## Testing
Added 4 new tests in `crates/ollama/src/ollama.rs`:
- `test_chat_options_serialization`: Verifies None fields are omitted
- `test_chat_request_with_stop_tokens`: Verifies stop tokens are
serialized when provided
- `test_chat_request_without_stop_tokens_omits_field`: Verifies empty
stop is omitted
All 11 ollama tests pass, plus 1 language_models ollama test.
Fixes#47798
Release Notes:
- Fixed Ollama models with custom stop tokens generating infinitely by
not overriding model defaults when no stop tokens are specified.
## Summary
This PR enables token usage reporting in streaming responses for
OpenAI-compatible APIs (OpenAI, xAI/Grok, OpenRouter, etc).
## Problem
Currently, the token counter UI in the Agent Panel doesn't display usage
for some OpenAI-compatible providers because they don't return usage
data during streaming by default. According to OpenAI's API
documentation, the `stream_options.include_usage` parameter must be set
to `true` to receive usage statistics in streaming responses.
## Solution
- Added StreamOptions struct with `include_usage` field to the open_ai
crate
- Added `stream_options` field to the Request struct
- Automatically set `stream_options: { include_usage: true }` when
`stream: true`
- Updated edit_prediction requests with `stream_options: None`
(non-streaming)
## Testing
Tested with xAI Grok models - token counter now correctly shows usage
after sending a message.
## References
- [OpenAI Chat Completions API -
stream_options](https://platform.openai.com/docs/api-reference/chat/create#chat-create-stream_options)
- [xAI API Documentation](https://docs.x.ai/api)
Previously, if you wanted to have a button that contains icons on both
edges, you'd need to use a `ButtonLike` component, which takes any
children. Meanwhile, the `Button` would only take one icon, where you
could control its position through the `IconPosition` enum. This has
always felt unnecessarily limiting. So, this PR removes this limitation
by adding two new methods to the button: `start_icon` and `end_icon`.
In the meantime, I have also been bothered by the unnecessary
indirection in the `IconButton` due to the existence of the `ButtonIcon`
component. So I figured I could also completely eliminate that by adding
some of its methods directly to the `IconButton` and in the Button, just
using a regular `Icon` component.
---
## Before
```rust
Button::new("id", "Label")
.icon(IconName::Plus)
.icon_position(IconPosition::Start)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
```
## After
```rust
Button::new("id", "Label")
.start_icon(Icon::new(IconName::Check))
.end_icon(Icon::new(IconName::ChevronDown).size(IconSize::XSmall))
```
This should have no visual impact to the UI.
Release Notes:
- N/A
The edit prediction, web search and completions endpoints in Cloud all
use tokens called LlmApiToken. These were independently created, cached,
and refreshed in three places: the cloud language model provider, the
edit prediction store, and the cloud web search provider. Each held its
own LlmApiToken instance, meaning three separate requests to get these
tokens at startup / login and three redundant refreshes whenever the
server signaled a token update was needed.
We already had a global singleton reacting to the refresh signals:
RefreshLlmTokenListener. It now holds a single LlmApiToken that all
three services use, performs the refresh itself, and emits
RefreshLlmTokenEvent only after the token is fresh. That event is used
by the language model provider to re-fetch models after a refresh. The
singleton is accessed only through `LlmApiToken::global()`.
I have tested this manually, and it token acquisition and usage appear
to be working fine.
Edit: I've tested it with a long running session, and refresh seems to
be working fine too.
Release Notes:
- N/A
---------
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This will help with test times (in some cases), as nextest cannot figure
out whether a given rdep is actually an alive edge of the build graph
Closes #ISSUE
Before you mark this PR as ready for review, make sure that you have:
- [ ] Added a solid test coverage and/or screenshots from doing manual
testing
- [ ] Done a self-review taking into account security and performance
aspects
- [ ] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- N/A
Hello,
This pull request aims to improve usage of lmstudio ai provider for
remote lmstudio nodes and support api key authentication.
This has been tested on my local network from a headless lms node. See
attached demo vid
Release Notes:
- lmstudio: Added support for specifying an API key via the UI
https://github.com/user-attachments/assets/7594cf49-3198-4171-b3e9-c3264cf35b6e
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Add GPT-5.4 and GPT-5.4-pro as Bring Your Own Key model options for the
OpenAI provider.
**GPT-5.4** (`gpt-5.4`):
- 1,050,000 token context window, 128K max output
- Supports chat completions, images, parallel tool calls
- Default reasoning effort: none
**GPT-5.4-pro** (`gpt-5.4-pro`):
- 1,050,000 token context window, 128K max output
- Responses API only (no chat completions)
- Default reasoning effort: medium (supports medium/high/xhigh)
Also fixes context window sizes for GPT-5 mini and GPT-5 nano (272K →
400K) to match current OpenAI docs.
Closes AI-78
Release Notes:
- Added GPT-5.4 and GPT-5.4-pro as available models when using your own
OpenAI API key.
This PR updates the model-fetching behavior for the Zed provider to wait
until the user is fully signed-in before we attempt to fetch the models.
We now subscribe to the `UserStore` and listen for the
`PrivateUserInfoUpdated` event. If we receive that event and the user is
not currently signed out, then we should be all set to fetch the models.
Closes CLO-424.
Release Notes:
- N/A
Gemini 3 Pro Preview has been deprecated in favor of Gemini 3.1 Pro.
This removes the `Gemini3Pro` variant from the `Model` enum and all
associated match arms, updates eval model lists, docs, and test
fixtures.
A serde alias (`"gemini-3-pro-preview"`) is kept on `Gemini31Pro` so
existing user settings gracefully migrate to the replacement model.
Closes AI-66
Release Notes:
- Removed deprecated Gemini 3 Pro Preview model; existing configurations
automatically migrate to Gemini 3.1 Pro.
This is already expected on the cloud side. This lets us know under
which organization the user is logged in when requesting an llm_api
token.
Closes CLO-337
Release Notes:
- N/A
Closes#50569
Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Previously, OpenRouter responses containing only usage data (without any
choices) would cause an error. Now the mapper properly emits usage
updates
for these events without failing.
Release Notes:
- Fixed an error when OpenRouter returns a usage-only event with empty
choices.
## Summary
- add a new `ai_gateway` language model provider in zed using the
openai-compatible chat completions path
- register ai gateway in provider wiring, settings schema, and default
settings
- add vercel ai gateway icon and provider list entry
- parse ai gateway model capabilities from tags (`tool-use`, `vision`)
and supported parameters
- clean up ai gateway oidc auth failures into a concise actionable error
message
Release Notes:
- Added Vercel AI Gateway as a new LLM provider in Zed.
This is a staff only toggle for now, since the consequences of
activating it are not obvious and quite dire (tokens costs 6 times
more).
Also, persist thinking, thinking effort and fast mode in DbThread so the
thinking mode toggle and thinking effort are persisted.
Release Notes:
- Agent: The thinking mode toggle and thinking effort are now persisted
when selecting a thread from history.
Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Adds `gpt-5.3-codex` as a built-in model under the OpenAI provider for
BYOK usage.
Model specs:
- 400,000 context window
- 128,000 max output tokens
- Reasoning token support (default medium effort)
- Uses the Responses API (like other codex models)
- Token counting falls back to the gpt-5 tokenizer
Closes AI-59
Release Notes:
- Added support for GPT-5.3-Codex as a bring-your-own-key model in the
OpenAI provider.
Now that the cloud-side StreamEnded support has landed, enable it on the
Zed client:
- Send the
`x-zed-client-supports-stream-ended-request-completion-status` header so
cloud knows to send `StreamEnded` status events.
- Track whether `StreamEnded` was received during the stream.
- Emit `StreamEndedUnexpectedly` error when the stream closes without a
`StreamEnded` status, indicating the response was truncated.
Concretely, this means that the agent panel will now display an
abnormally terminated response stream for model calls through a Zed
subscription as an error instead of just stopping.
Release Notes:
- The agent panel now displays an abnormally terminated response stream
for model calls through a Zed subscription as an error instead of just
stopping.
<img width="435" height="211" alt="Screenshot 2026-02-17 at 1 32 48 PM"
src="https://github.com/user-attachments/assets/136c188d-5001-4526-961e-9f7faccc5f7a"
/>
Add support for the new Claude Sonnet 4.6 model across the anthropic,
bedrock, and language_models crates. Includes base, thinking, and 1M
context variants.
Closes AI-39
Release Notes:
- Added BYOK support for Claude Sonnet 4.6