### Description
Related Discussions: #44499, #35742, #31851
Display cost multiplier for GitHub Copilot models in the model selectors
(Both in Chat Panel and Inline Assistant)
<img width="436" height="800" alt="image"
src="https://github.com/user-attachments/assets/c9ebd8fa-4d55-4be8-b3e1-f46dbf1f0145"
/>
### Some technical notes
Although this PR's primary intent is to show the cost multiplier for
GitHub Copilot models alone, I have included some necessary plumbing to
allow specifying costs for other providers in future. I have introduced
an enum called `LanguageModelCostInfo` for showing cost in different
ways for different models. Now, this enum is used in `LanguageModel`
trait to get the cost info.
For now to begin with, in `LanguageModelCostInfo`, I have specified two
ways of pricing: Request-based (1 Agent request - GitHub Copilot uses
this) and Token-based (1M Input tokens / 1M Output tokens). I had
initially thought about adding a `Free` type, especially for Ollama but
didn't do it after realizing that Ollama has paid plans. Right now, only
the Request-based pricing is implemented and used for Copilot models.
Feel free to suggest changes on how to improve this design better.
Release Notes:
- Show cost multiplier for GitHub Copilot models
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This PR removes the `cloud-thinking-effort` feature flag to ship the
thinking effort UI for the Zed provider.
Release Notes:
- Added support for controlling thinking effort levels with supported
models using the Zed provider.
Bedrock Converse API requires toolConfig whenever messages have tool use
or result blocks. PR #33174 handled the case where tools are defined but
tool_choice is None. This change addresses another case: the tools array
is empty (e.g. thread summarisation) but messages still have tool blocks
from conversation history. A placeholder tool satisfies the requirement.
Testing:
Tested manually by:
1. Starting a conversation with Bedrock that uses tools
2. Triggering thread summarisation
3. Confirming summarisation now succeeds instead of failing with an API
error
Release Notes:
- Fixed Bedrock thread summarization failing when conversation had tools
Add StreamEnded variant so the client can distinguish between a stream
that the cloud ran to completion versus one that was interrupted (see
CLO-258). **That logic is to be added in a follow up PR**.
Add an Unknown fallback with #[serde(other)] for forward-compatible
deserialization of future variants.
The client advertises support via a new
x-zed-client-supports-stream-ended-request-completion-status header. The
server will only send the new variant if that header is passed. Both
StreamEnded and Unknown are silently ignored at the event mapping layer
(from_completion_request_status returns Ok(None)).
Part of CLO-264 and CLO-266; cloud-side changes to follow.
Release Notes:
- N/A
---------
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This PR #47407 broke thinking models for non-zed providers (Nightly
only) because we set `thinking_allowed` to `thinking_enabled`
(previously `true`)
[here](b671c8cdc5/crates/agent/src/thread.rs (L2400)).
The value of `thinking_enabled` eventually comes from the
`LanguageModel::supports_thinking` function, which returns `false` for
all models except the ones coming from Zed.
This PR implements `thinking_enabled` for other providers.
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
Mistral Vibe, the official coding agent from Mistral, sets the
x-affinity header to the session ID to enable prompt caching. This patch
implements the same mechanism, resulting in a faster agent loop.
Release Notes:
- Added prompt caching for Mistral AI.
This small change *may* help with #39211, #35025 or #39031 although I'm
not positive it will fix it entirely. At a minimum, it should prevent
sending invalid requests to the Mistral API, which return a 400 error
and can prevent the thread from progressing if it gets stuck in a retry
loop.
This should prevent sending a message like `{ "role": "assistant",
"content": "" }` if for some reason the thread contains a message with
an empty text content and no tool calls.
Some users (including myself) have encountered this with the Devstral 2
models, although it doesn't seem trivial to reproduce:
https://github.com/zed-industries/zed/issues/37021#issuecomment-3728902562
When it occurs, error logs look something like this:
```
2026-01-24T19:53:35-08:00 ERROR [crates/agent/src/thread.rs:984] invalid type: string "Failed to connect to Mistral API: 400 Bad Request {\"object\":\"error\",\"message\":\"Assistant message must have either content or tool_calls, but not none.\",\"type\":\"invalid_request_assistant_message\",\"param\":null,\"code\":\"3240\"}", expected struct EditFileToolOutput
2026-01-24T19:53:35-08:00 ERROR [crates/agent/src/thread.rs:984] invalid type: string "Failed to connect to Mistral API: 400 Bad Request {\"object\":\"error\",\"message\":\"Assistant message must have either content or tool_calls, but not none.\",\"type\":\"invalid_request_assistant_message\",\"param\":null,\"code\":\"3240\"}", expected struct EditFileToolOutput
2026-01-24T19:53:35-08:00 ERROR [crates/agent/src/thread.rs:984] invalid type: string "Failed to connect to Mistral API: 400 Bad Request {\"object\":\"error\",\"message\":\"Assistant message must have either content or tool_calls, but not none.\",\"type\":\"invalid_request_assistant_message\",\"param\":null,\"code\":\"3240\"}", expected struct EditFileToolOutput
```
Release Notes:
- Fixed agent sometimes sending invalid messages to Mistral API
Closes #N/A (no existing issue - implemented to enable image input for
Bedrock models)
This PR enables the "@" image mention feature for Bedrock models that
support vision capabilities.
**Changes:**
- Added `supports_images()` method to Bedrock `Model` enum
- Wired up image support in the Bedrock language model provider
- Added `MessageContent::Image` handling to convert base64 images to
Bedrock's expected format
- Added tool result image support
**Supported models:** Claude 3/3.5/4 family, Amazon Nova Pro/Lite, Meta
Llama 3.2 Vision, Mistral Pixtral
Release Notes:
- Added image input support for Amazon Bedrock models with vision
capabilities
Remove GPT-4o, GPT-4.1, GPT-4.1-mini, and o4-mini from BYOK model
options in Zed before OpenAI retires these models.
These models are being retired by OpenAI (ChatGPT workspace support ends
April 3, 2026), so they have been removed from the available models list
in Zed's BYOK provider.
Closes AI-4
Release Notes:
- Removed deprecated GPT-4o, GPT-4.1, GPT-4.1-mini, and o4-mini models
from OpenAI BYOK provider
Release Notes:
- Changed the way context window is set for ollama at the provider level
instead of per model.
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Release Notes:
- Added `allow_extended_context` to the Bedrock settings which enables
1M context windows on models that support it
---------
Co-authored-by: Ona <no-reply@ona.com>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Normalize handling of empty tool call arguments across all LLM
providers. Many providers return empty strings for tool calls with no
arguments, which would previously fail JSON parsing.
- Created shared parse_tool_arguments() helper in provider/util.rs that
treats empty strings as empty JSON objects ({})
- Refactored 10 occurrences across 9 provider files to use the helper
- Ensures consistent behavior across all providers (anthropic, bedrock,
copilot_chat, deepseek, lmstudio, mistral, open_ai, open_router)
Closes: #48955
Release Notes:
- Fixed tool calls with no arguments failing when using certain LLM
providers
Closes#37525
By default, thread summary uses default_fast_model (if set), otherwise
default_model, which resolves to openrouter/auto for openrouter
provider. This may cause the summary to be generated by a different
model than the one used by the agent, potentially leading — in cases
such as Claude Opus 4.5 — to summary costs exceeding main agent
execution costs.
The current logic in registry.rs prioritizes default_fast_model over
default_model, which overrides the user-selected model (assigned only to
default_model). Setting default_fast_model = None for the OpenRouter
provider preserves the fallback to openrouter/auto when no model is
chosen, while respecting the user's explicit model selection when one is
provided.
```rust
pub fn set_default_model(&mut self, model: Option<ConfiguredModel>, cx: &mut Context<Self>) {
match (self.default_model.as_ref(), model.as_ref()) {
(Some(old), Some(new)) if old.is_same_as(new) => {}
(None, None) => {}
_ => cx.emit(Event::DefaultModelChanged),
}
self.default_fast_model = maybe!({
let provider = &model.as_ref()?.provider;
let fast_model = provider.default_fast_model(cx)?;
Some(ConfiguredModel {
provider: provider.clone(),
model: fast_model,
})
}); // This sets default fast model (in our case openrouter/auto)
self.default_model = model; //This sets default_model to user selected model
}
```
And latter on :
```rust
pub fn thread_summary_model(&self) -> Option<ConfiguredModel> {
#[cfg(debug_assertions)]
if std::env::var("ZED_SIMULATE_NO_LLM_PROVIDER").is_ok() {
return None;
}
self.thread_summary_model
.clone()
.or_else(|| self.default_fast_model.clone()) // We pick fast_model over default model here
.or_else(|| self.default_model.clone())
}
```
Which results in user choice being ignored.
Proposed behavior:
Use the model explicitly selected by the user in Zed agent
configuration.
If no model is specified, fall back to the configured default.
The resolution is to set in : provider/open_router.rs
```rust
fn default_fast_model(&self, _cx: &App) -> Option<Arc<dyn LanguageModel>> {
None
}
```
This will have a consequence of default_fast_model not being provided
and falling back to user choice - but once the fast model is set via for
example a configuration property - the default_fast_model is picked over
default_model
Release Notes:
- open_router: Use user's default model when comments and thread summary
Release Notes:
- Added Claude Opus 4.6 and 4.6 Thinking with Cross region inference for
US, EU, and Global endpoints.
---------
Co-authored-by: Ona <no-reply@ona.com>
TODO:
- [x] Review code
- [x] Decide whether to keep ignored API tests
Release Notes:
- Fixed a bug where cancelling a thread mid-thought would cause further
anthropic requests to fail
- Fixed a bug where the model configured on a thread would not be
persisted alongside that thread
This PR updates the model selector to highlight the latest models that
are available through the Zed provider:
<img width="388" height="477" alt="Screenshot 2026-02-06 at 1 46 41 PM"
src="https://github.com/user-attachments/assets/70760399-ecf6-46e3-80a7-cb998216c192"
/>
Closes CLO-205.
Release Notes:
- Added a "Latest" indicator to highlight the latest models available
through the Zed provider.
This PR adds support for setting the reasoning effort for OpenAI models
through the Zed provider.
This is gated behind the `cloud-thinking-effort` feature flag.
Release Notes:
- N/A
Co-authored-by: Tom Houlé <tom@tomhoule.com>
This PR renames the `cloud-thinking-toggle` feature flag to
`cloud-thinking-effort`.
This feature flag has expanded slightly in scope, so we want the name to
be more representative of what it gates.
Release Notes:
- N/A
Co-authored-by: Tom Houlé <tom@tomhoule.com>
Closes#46506
Release Notes:
- Fixed an issue where the codestral URL used for credentials would be
different than the one used for requests causing authentication errors
This PR adds a new `supported_effort_levels` method to the
`LanguageModel` trait.
This can be used to retrieve the list of effort levels that the model
supports, which will eventually be used to drive the UI for selecting
the thinking effort.
Right now this list will only be populated for Cloud models.
Release Notes:
- N/A
The previous URL pointed to the model access page which no longer exists
(not a 404, tho). The model catalog page is the current location for
selecting and requesting access to Bedrock models.
| Before | After |
|--------|--------|
| <img width="1732" height="1125" alt="Screenshot 2026-02-04 at 12 50
13"
src="https://github.com/user-attachments/assets/f513e7c9-aa70-439a-afd0-ef8177ada463"
/> | <img width="1732" height="1125" alt="Screenshot 2026-02-04 at 12 52
11"
src="https://github.com/user-attachments/assets/6609215e-1bbb-4ed1-b57d-422ed7893498"
/> |
Release Notes:
- Fixed Bedrock model catalog URL in Agent Panel settings
This PR reworks the `Plan` type, now that we don't need to be concerned
about the legacy plan versions.
We've also made the deserialization layer more robust, which should make
it easier to add new plan variants in the future without needing to go
through this same song and dance.
Release Notes:
- N/A
This PR adds a new `needs_llm_token_refresh` helper method for checking
if the LLM token needs to be refreshed.
We were duplicating the check for the `x-zed-expired-token` header in a
number of spots, and it will be gaining an additional case soon.
Release Notes:
- N/A
- **title_bar: Extract platform_title_bar from title_bar**
- **file_finder no longer depends on search and agent_servers no longer
depend on language_models**
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
The rate limiter's semaphore guard was being held for the entire
duration of a turn, including during tool execution. This caused
deadlocks when subagents tried to acquire permits while parent requests
were waiting for them to complete.
## The Problem
In `run_turn_internal`, the stream (which contains the `RateLimitGuard`
holding the semaphore permit) was kept alive throughout the entire loop
iteration - including during **tool execution**:
1. Parent request acquires permit
2. Parent starts streaming, consumes response
3. Parent starts executing tools (subagents)
4. **Stream/guard still held** while tools execute
5. Subagents try to acquire permits → blocked because parent still holds
permit
6. Deadlock if all permits are held by parents waiting for subagent
children
## The Fix
Two changes were made:
1. **Drop the stream early**: Added an explicit `drop(events)` after the
stream is fully consumed but before tool execution begins. This releases
the rate limit permit so subagents can acquire it.
2. **Removed the `bypass_rate_limit` workaround**: Since the root cause
is now fixed, the bypass mechanism is no longer needed.
Note: no release notes because subagents are still feature-flagged, and
this rate limiting change isn't actually observable without them.
Release Notes:
- N/A
Users had trouble signing in due to us relying on the Copilot::global
being set, which was never the case. We've decided to use a dedicated
LSP instance just for handling auth of Copilot Chat and other goodies.
That instance is subscribed to by local Copilot instances for projects.
When the Auth instance changes it's state, local instances are prompted
to re-check their own sign in status.
Closes#47352
Co-authored-by: dino <dinojoaocosta@gmail.com>
Release Notes:
- Fixed authentication issues with Copilot.
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
This PR adds a thinking toggle for controlling whether to use thinking
for a model in the Zed provider:
<img width="645" height="142" alt="Screenshot 2026-01-22 at 12 34 01 PM"
src="https://github.com/user-attachments/assets/9aa543fe-e708-4840-8b38-1a6fbcb78388"
/>
Previously we would create separate "Thinking" variants of the models
that supported thinking in the model selector.
This only applies to Anthropic models in the Zed provider, currently.
This is gated behind the `cloud-thinking-toggle` feature flag.
Release Notes:
- N/A
---------
Co-authored-by: Neel <neel@zed.dev>
This PR removes the `open-ai-responses-api` feature flag and makes it so
all OpenAI requests to the Zed provider use the Responses API.
We've been running this in Nightly/Preview for a week now without any
issues.
Closes CLO-104.
Release Notes:
- N/A
Support for Kimi K2 Thinking
Release Notes:
- Added support for thinking traces when using OpenAI-API-compatible AI providers
---------
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
## Problem
When subagents use the `edit_file` tool, it creates an `EditAgent` that
makes its own model request to get the edit instructions. These "nested"
requests compete with the parent subagent conversation requests for rate
limiter permits.
The rate limiter uses a semaphore with a limit of 4 concurrent requests
per model instance. When multiple subagents run in parallel:
1. 3 subagents each hold 1 permit for their ongoing conversation streams
(3 permits used)
2. When all 3 try to use `edit_file` simultaneously, their edit agents
need permits too
3. Only 1 edit agent can get the 4th permit; the other 2 block waiting
4. The blocked edit agents can't complete, so their parent subagent
conversations can't complete
5. The parent conversations hold their permits, so the blocked edit
agents stay blocked
6. **Deadlock**
## Solution
Added a `bypass_rate_limit` field to `LanguageModelRequest`. When set to
`true`, the request skips the rate limiter semaphore entirely. The
`EditAgent` sets this flag because its requests are already "part of" a
rate-limited parent request.
(No release notes because subagents are still feature-flagged.)
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
This PR removes the code for the legacy plans.
No more users will be on this plan as of January 17th, so it's fine to
land these changes now (as they won't be released until the 21st).
Closes CLO-76.
Release Notes:
- N/A
This feature cost $15.
Up -> Tokens we're sending to the model
Down -> Tokens we've received from the model.
<img width="377" height="69" alt="Screenshot 2026-01-14 at 12 31 01 PM"
src="https://github.com/user-attachments/assets/fc15824f-de5d-466b-8cc1-329f3c1940bb"
/>
Release Notes:
- Changed the display of tokens for OpenAI models to reflect the
input/output limits.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- **copilot: Fix double lease panic when signing out**
- **Extract copilot_chat into a separate crate**
- **Do not use re-exports from copilot**
- **Use new SignIn API**
- **Extract copilot_ui out of copilot**
Closes#7501
Release Notes:
- Fixed Copilot providing suggestions from different Zed windows.
- Copilot edit predictions now support jumping to unresolved
diagnostics.
This PR makes it so we use a proper type for the Responses API `input`
rather than a `serde_json::Value`.
It should have never used `serde_json::Value` to begin with.
Release Notes:
- N/A
## Motivation
This PR unifies the async execution infrastructure between GPUI and
other components that depend on the `scheduler` crate (such as our cloud
codebase). By having a scheduler that lives independently of GPUI, we
can enable deterministic testing across the entire stack - testing GPUI
applications alongside cloud services with a single, unified scheduler.
## Summary
This PR completes the integration of the `scheduler` crate into GPUI,
unifying async execution and enabling deterministic testing of GPUI
combined with other components that depend on the scheduler crate.
## Key Changes
### Scheduler Integration (Phases 1-5, previously completed)
- `TestDispatcher` now delegates to `TestScheduler` for timing, clock,
RNG, and task scheduling
- `PlatformScheduler` implements the `Scheduler` trait for production
use
- GPUI executors wrap scheduler executors, selecting `TestScheduler` or
`PlatformScheduler` based on environment
- Unified blocking logic via `Scheduler::block()`
### Dead Code Cleanup
- Deleted orphaned `crates/gpui/src/platform/platform_scheduler.rs`
(older incompatible version)
## Intentional Removals
### `spawn_labeled` and `deprioritize` removed
The `TaskLabel` system (`spawn_labeled`, `deprioritize`) was removed
during this integration. It was only used in a few places for test
ordering control.
cc @maxbrunsfeld @as-cii - The new priority-weighted scheduling in
`TestScheduler` provides similar functionality through
`Priority::High/Medium/Low`. If `deprioritize` is important for specific
test scenarios, we could add it back to the scheduler crate. Let me know
if this is blocking anything.
### `start_waiting` / `finish_waiting` debug methods removed
Replaced by `TracingWaker` in `TestScheduler` - run tests with
`PENDING_TRACES=1` to see backtraces of pending futures when parking is
forbidden.
### Realtime Priority removed
The realtime priority feature was unused in the codebase. I'd prefer to
reintroduce it when we have an actual use case, as the implementation
(bounded channel with capacity 1) could potentially block the main
thread. Having a real use case will help us validate the design.
## Testing
- All GPUI tests pass
- All scheduler tests pass
- Clippy clean
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ GPUI │
│ ┌──────────────────────┐ ┌────────────────────────────┐ │
│ │ gpui::Background- │ │ gpui::ForegroundExecutor │ │
│ │ Executor │ │ - wraps scheduler:: │ │
│ │ - scheduler: Arc< │ │ ForegroundExecutor │ │
│ │ dyn Scheduler> │ └────────────┬───────────────┘ │
│ └──────────┬───────────┘ │ │
│ │ │ │
│ └──────────┬──────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Arc<dyn Scheduler> │ │
│ └───────────┬───────────┘ │
│ ┌──────────────┴──────────────┐ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌────────────────────┐ │
│ │ PlatformScheduler│ │ TestScheduler │ │
│ │ (production) │ │ (deterministic) │ │
│ └──────────────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
Release Notes:
- N/A
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Yara <git@yara.blue>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
This PR adds support for using the OpenAI Responses API through the Zed
provider.
This is gated behind the `open-ai-responses-api` feature flag.
Part of CLO-34.
Release Notes:
- N/A
Add support for OpenAI's /responses endpoint for models that don't
support /chat/completions API. This enables compatibility with newer
model variants (`gpt-5-codex`, `gpt-5-pro`, `o3-pro`, etc) while
maintaining compatibility with existing configs
Changes:
- Add `supports_chat_completions` flag to model capabilities that
defaults to true for existing behavior
- Implement responses API client with streaming support as per [OpenAI
documentation](https://app.stainless.com/api/spec/documented/openai/openapi.documented.yml).
- Add `ResponseEventMapper` to convert responses events to completion
events for maintainer simplicity
- Update UI to allow toggling `chat_completions` capability
- Add `gpt-5-codex` model
Closes#38858
Release Notes:
- Added support for `gpt-5-codex` model
---------
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>