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
Release Notes:
- Improved Bedrock error messages: region-locked models ask the user to
try a different region, rate limits and access errors are reported
cleanly instead of as raw API responses
- Streamlined Bedrock model list to 39 curated models
- Fixed API errors when using non-tool models in agent threads
---------
Co-authored-by: Ona <no-reply@ona.com>
### 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](https://github.com/zed-industries/zed/blob/b671c8cdc5a73d49d158a84f386f8fecbfbae65a/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