"msg.string_contents();" return more than just content. It also return
tool result (which need special handling, and should be emitted from the
tool role) and thinking (which need already implemented special
handling).
This resulted in thinking being sent as content, which apparently
ollama’s gemma4 parser didn’t handled well, and caused a number of issue
that manifested by 1. outputting end of though token where unappropriate
and 2. repeating things endlessly
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] 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)
(no UI/UX impact)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable (a quick
review, without benchmark, show that this should be at least as fast as
the previous code. This is called only exceptionally anyway.)
Closes#55537
Release Notes:
- Fixed "thinking" text being badly formatted when sent to Ollama
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)
- [x] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Release Notes:
- Mistral: Added Ministral 3 models and removed deprecated models
---------
Signed-off-by: Gabriel Linder <linder.gabriel@gmail.com>
OpenCode API endpoints for DeepSeek were [moved from
Anthropic-compatible to
OpenAI-compatible](https://github.com/anomalyco/opencode/pull/24500) and
DeepSeek requires interleaved reasoning enabled to work. I ran a
_"rename this variable to potato"_ test and I can confirm DeepSeek V4
Flash and Pro both work now 🎉
Some other OpenCode Go models were marked [on
models.dev](https://github.com/anomalyco/models.dev/tree/dev/providers/opencode-go/models)
as supporting `interleaved_reasoning` so they too got that enabled. Kimi
K2.5 and Kimi K2.6 continue to fail with
https://github.com/zed-industries/zed/issues/51743
(https://github.com/zed-industries/zed/pull/55085 seems to hint at this
being [an OpenCode
issue](https://github.com/zed-industries/zed/issues/51743#issuecomment-4336785765)?),
but all other models seem to work fine both with `interleaved_reasoning`
and without it 🤷 I assume it's better to have that turned on? Again, the
intersection of OpenAI Chat Completions API, different models, different
inference providers, how they all work together is something I know
nothing about!
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
Release Notes:
- OpenCode Go: use correct DeepSeek endpoints
- OpenCode: add support for interleaved_reasoning
Follow up to #54826, after which the fallback model would be selected
instead of the cloud model when starting Zed
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
Removes the Vercel v0 Provider, as the v0 API has been
depredated/removed (https://api.v0.dev/v1)
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
Release Notes:
- agent: Removed Vercel v0 provider as it has been deprecated by Vercel
Leftovers after https://github.com/zed-industries/zed/pull/53651
Updated models:
- **Zen**: GPT 5.5 and GPT 5.5 Pro - not tested because I don't have a
Zen subscription and I stubbornly refuse to get one
- **Go**: DeepSeek V4 Pro and DeepSeek V4 Flash - failing due to
https://github.com/anomalyco/opencode/issues/24224
- **Go**: MiMo V2.5 and MiMo V2.5 Pro - tested, confirmed working
- **Free**: Ling 2.6 Flash, [available for "a limited
time"](https://x.com/opencode/status/2046717718028513694) - tested,
confirmed working
- **Free**: Hy3 Preview, [available until May
8](https://x.com/opencode/status/2047328981435756824) - tested,
confirmed working
When testing the new models and comparing with OpenCode CLI, I realized
the
[variants](https://opencode.ai/docs/models/#built-in-variants)/thinking
effort configuration was not supported by the Zed Agent implementation.
I added that for OpenCode Go models, after manually checking what each
model supports in OpenCode. Reasoning levels and everything seems to
work (UI looks good, model works) but I have no idea how to specifically
test reasoning levels without doing a full benchmark 🤷
I did not add the same thing for OpenCode Zen models because I could not
figure out a way to get the supported variants.
@benbrandt let me know if you want me to take this out of this PR and to
keep just the model updates!
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
Release Notes:
- OpenCode: add new models (GPT 5.5, DeepSeek V4, MiMo V2.5, Ling 2.6,
Hy3)
- OpenCode Go: add support for configurable reasoning effort levels
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
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
Closes #ISSUE
Release Notes:
- N/A
From the
[docs](https://developers.openai.com/api/docs/guides/migrate-to-responses#responses-benefits):
> Better performance: Using reasoning models, like GPT-5, with Responses
will result in better model intelligence when compared to Chat
Completions. Our internal evals reveal a 3% improvement in SWE-bench
with same prompt and setup.
Agentic by default: The Responses API is an agentic loop, allowing the
model to call multiple tools, like web_search, image_generation,
file_search, code_interpreter, remote MCP servers, as well as your own
custom functions, within the span of one API request.
Lower costs: Results in lower costs due to improved cache utilization
(40% to 80% improvement when compared to Chat Completions in internal
tests).
Stateful context: Use store: true to maintain state from turn to turn,
preserving reasoning and tool context from turn-to-turn.
Flexible inputs: Pass a string with input or a list of messages; use
instructions for system-level guidance.
Encrypted reasoning: Opt-out of statefulness while still benefiting from
advanced reasoning.
Future-proof: Future-proofed for upcoming models.
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 #ISSUE
Release Notes:
- Always use Responses API for OpenAI models
This PR fixes an issue introduced in
https://github.com/zed-industries/zed/pull/54397 where the Zed Cloud
provider would not be reflected as "authenticated" if a connection to
Collab was attempted, but could not be established.
This was especially noticable when running Zed against a local version
of Cloud and not having Collab running.
This restores the original logic prior to that change.
Release Notes:
- N/A
**TL;DR**: add support for OpenCode Go (flat-rate monthly subscription)
along the already-implemented OpenCode Zed (pay-as-you-go billing).
> [!WARNING]
> This code was written by LLMs, under the supervision of a so-called
developer that never wrote Rust profesionally and that spends more time
in Pages&Keynote than in an IDE.
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
## Background
OpenCode offers a few different ways to access models:
- **free access to 3 models**, with feedback and data used to improve
the model. These models use the OpenCode Zen API endpoints, but have
different usage limits (200 requests per 5 hours) and have a different
privacy policy. Some people disable or block the free models, some
people are super-excited to have access to LLMs for free, and some
people like using the free models to test new LLMs (at launch MiMo-V2
had 2 free weeks of usage, for example).
- **pay-as-you-go access to 30 models** as part of the [OpenCode
Zen](https://opencode.ai/zen) subscription. These models use the same
OpenCode Zen API endpoints.
- **flat-rate monthly access to 7 models** as part of the [OpenCode
Go](https://opencode.ai/go) subscription. These models use the OpenCode
Zen API endpoints with an extra `/go` appended to the path. There are
5-hour, weekly, and monthly usage limits and, additionally, users can
toggle a switch in the OpenCode Console to use Zen models with their
pay-as-you-go billing after the Go limits are hit.
There's also a currently-paused [OpenCode
Black](https://opencode.ai/black) flat-rate subscription with way higher
usage limits and with access to more models, with $100 and $200 monthly
plans.
The whole thing is a bit messy, but it's great value and highly reliable
LLM access!
<br>
https://github.com/zed-industries/zed/pull/49589 added support for
OpenCode Zen by implementing a new `opencode` provider. OpenCode Go
[could be used by overriding the API
URL](https://github.com/zed-industries/zed/pull/49589#issuecomment-4130300454),
but that is a terrible user experience: some models have to be manually
added, the model list always shows the 30-something OpenCode Zen models,
and free models cannot be used at all.
I was annoyed by the experience of using OpenCode Go with Zed and this
past week I had to test a bunch of LLMs and providers and harnesses, so
I took this on as a test case 🙂
## Implementation
This PR makes the OpenCode provider more general (not just for Zen) and
adds an `OpenCodeModelSubscription` concept which is then used to
implement support for OpenCode Go. The free models are also broken out
into their own subscription for a prettier model list.
For a better user experience, the different subscriptions can be enabled
or disabled, both in the settings file and in the UX:
<img width="434" height="176" alt="Screenshot showing the OpenCode
provider configuration, with the newly added toggles"
src="https://github.com/user-attachments/assets/3520e114-00c8-4794-84bf-35cd72d9c57e"
/>
The code was written by LLMs, but I do understand it and I did a bunch
of "manual" iterations and "manual" tweaks. Still, my Rust experience is
non-existent so **I won't feel offended if y'all reject this PR**! I did
consider alternatives (adding a new `opencode-go` provider and renaming
this to `opencode-zen`, for example, or adding support for custom API
URLs in OpenCode custom models which would've been the smallest code
change but a terrible user experience, and so on) but all alternatives
would have been, in my opinion, a worse user experience.
**Tests I did**:
- confirmed OpenCode Go models work as expected
- confirmed OpenCode Zen Free models work as expected
- confirmed I get an error when trying to use OpenCode Zen models since
I don't have that subscription
- confirmed the subcription toggles work as expected (model are
shown/hidden, settings file is updated)
**Notes**:
- this PR is best reviewed commit-by-commit. I did not create a separate
PR for the model updates to minimize delays
- my exeprience with Rust is roughly zero, but I tried to strike a
balance between idiomatic Rust and easy-to-read code
- users of the OpenCode provider might have to do some re-configuration
after this PR is merged since the model identifiers now include the
subscription, eg `claude-haiku-4-5` is now `zen/claude-haiku-4-5`. Since
this is a relatively new provider and the impact is small, I preffered
that rather than adding complex migration/mapping logic.
- does changing the provider name from "OpenCode Zen" to "OpenCode"
break anything for y'all at Zed?
- does changing the telemetry id from `"opencode/<model-id>"` to
`"opencode/<subscription>/<model-id>"` break anything for y'all at Zed?
---
Release Notes:
- OpenCode provider: add support for OpenCode Go
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
## Summary
Users who add custom OpenAI models under
`language_models.openai.available_models` can set `capabilities.images:
true` to declare that the endpoint accepts image inputs. Today, that
setting is silently ignored: the Agent panel's image-attach button stays
disabled regardless, and the only workaround is to switch to a built-in
OpenAI model, attach the image, and switch back.
Root cause: `Model::Custom` does not carry a `supports_images` field,
and the OpenAI provider's `supports_images()` for the `Custom` arm
hardcodes `false`.
## Changes
1. `crates/settings_content/src/language_model.rs`: add `images: bool`
to `OpenAiModelCapabilities` with `#[serde(default)]` so existing
settings.json files keep working unchanged.
2. `crates/open_ai/src/open_ai.rs`: add `supports_images: bool` to
`Model::Custom` with a matching serde default.
3. `crates/language_models/src/provider/open_ai.rs`: pass
`model.capabilities.images` into the `Model::Custom` variant in
`provided_models`, and return the stored value from `supports_images()`
for `Custom`.
Existing `Model::Custom { .. }` match sites (`completion.rs:829`,
various in `open_ai.rs`) all use `..` so they continue to compile
without change.
## Testing
- `cargo check -p settings_content -p open_ai -p language_models`:
clean.
- I was not able to complete `./script/clippy` locally: the build
stalled on the first-time `webrtc-sys` download for livekit-rust-sdks
(TLS close_notify failure on docs.rs mirror). Happy to rerun once CI has
cached artifacts.
- Manually verified the capability plumbing by tracing: settings.json ->
`OpenAiModelCapabilities.images` -> `Model::Custom { supports_images }`
-> `supports_images()` -> `Thread::prompt_capabilities` ->
`SessionCapabilities.supports_images()` -> `build_add_context_menu` gate
in `thread_view.rs`.
## Related Issues
Closes#50752
Release Notes:
- Fixed custom OpenAI models ignoring the `capabilities.images` setting
in `language_models.openai.available_models`.
This contribution was developed with AI assistance (Codex).
---------
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
No, sadly, the title is not a typo. See
https://www.githubstatus.com/incidents/zsg1lk7w13cf for the context.
I'll read with joy and popcorn through that root cause analysis.
It makes literally zero sense what happened here, but for some completly
bonkers reason GitHub completely messed up the merge queue with
https://github.com/zed-industries/zed/pull/54632.
I have no idea how it happened. It makes literally zero sense. A PR
going into the merge queue should have the same LoC when getting out of
it. GitHub obviously does not check this. GitHub causes extra work with
a feature that is supposed to save time.
Thanks, I guess.
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This PR brings back the button to filter remote branches when accessing
the title bar's branch picker with the mouse. It was unintentionally
removed when we introduced the new worktree picker.
Release Notes:
- N/A
Starting with Claude Opus 4.7, Anthropic omits thinking content from
responses by default; callers must pass `display: "summarized"` to keep
seeing thinking summaries. Without opting in, the agent UI shows a long
pause with no visible thinking, and users get no progress indication
during extended reasoning.
This extends the adaptive-thinking wire type with an optional `display`
field and requests `Summarized` from every call site that builds an
adaptive thinking request (direct Anthropic, Copilot Chat proxy, Zed
Cloud, and Bedrock).
## Notes
- Applied at the adaptive-thinking layer rather than special-casing Opus
4.7. The `display` parameter is accepted by every
adaptive-thinking-capable model, and the previous behavior (visible
summaries) is what users already see on Opus 4.6 / Sonnet 4.6, so there
is no behavior change for those models.
Release Notes:
- Restored thinking summaries for Claude Opus 4.7.
Drop the `count_tokens` API and related implementations across
providers, and remove the unused `tiktoken-rs` dependency.
I was going to update the dependency becuase they finally released a fix
we needed. But then I realized we only used this api in one place, the
Rules library. And for most models it would have been wildly incorrect
becuase we use tiktoken, i.e. OpenAI tokenizers, for almost every model,
which is going to give incorrect results.
Given that, I just removed these because the difference in how we get
these has caused plenty of confusion in the past.
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
Release Notes:
- Added interleaved_reasoning option to openai compatible models
---
This PR adds the interleaved_reasoning option for OpenAI-compatible
models, addressing the issue described in
https://github.com/ggml-org/llama.cpp/issues/20837.
In my testing, enabling interleaved_reasoning not only resolved the
tool-calling issues encountered by Qwen3.5 models in llama.cpp, but also
appeared to improve the model's coding capabilities. I have also
verified the outgoing requests using a proxy to ensure the parameter is
being sent correctly.It is also likely that this change will benefit
other models and providers as well.
Note: While I used AI to assist with the implementation, I have reviewed
and tested the changes. As I am relatively new to Rust and the Zed
codebase, I would appreciate any feedback or suggestions for
improvement. I am happy to make further adjustments if needed.
Thank you all for building such an amazing editor!
Co-authored-by: Oleksiy Syvokon <oleksiy@zed.dev>
The agent settings UI unconditionally showed "You have access to Zed's
hosted models through your Organization" for all Business plan users,
even when the org admin had turned off the Zed AI model provider. Now
the copy reads "Zed's hosted models are disabled by your organization's
configuration" when is_zed_model_provider_enabled is false.
Also added component preview entries for both Business plan states.
Closes CLO-667
Release Notes:
- N/A
---------
Co-authored-by: Neel <neel@zed.dev>
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)