Claude Fable 5.1 introduces two breaking Messages API changes that
produce 400 errors with request shapes Zed currently sends. This change
adapts the shared Anthropic request path so the model works out of the
box, without restructuring how requests are built.
The first change is thinking-block prefix binding. Fable 5.1 binds each
thinking block to the exact conversation prefix that produced it, and
replaying a block after anything earlier changed (the system prompt, the
tools array, or an edited turn) fails the whole request with a 400
reading "The block is bound to a different conversation". Zed routinely
rebuilds the system prompt and tool list between requests (rules file
changes, profile switches, MCP servers coming online), so this would
surface as a hard error mid-thread. Requests to Fable 5.1 now send the
`thinking-binding-controls-2026-08-01` beta header with
`thinking.block_binding.prefix_mismatch_behavior: "drop_block"`, which
makes the API drop invalidated blocks and continue instead of rejecting
the request. Claude Mythos 5.1 doesn't run this check and is excluded.
The cloud and Copilot Chat paths pass `block_binding: None` since their
proxies control the upstream beta headers; opting in there belongs
server-side.
The second change is that forced tool use (`tool_choice: "any"` or
`"tool"`) now returns a 400. Zed sends `"any"` from inline assist's
streaming-tools path, which is on by default. The Anthropic and
Zed-cloud providers now report `tool_choice: any` as unsupported for
Fable/Mythos 5.1, and inline assist already degrades gracefully to
prompt-guided auto tool choice, which is Anthropic's recommended
migration.
Finally, `claude-fable-5-1` and `claude-mythos-5-1` are added to the
compaction model list. This matters more than a routine table update:
with prefix binding, server-side compaction is the sanctioned way to
trim history without invalidating thinking blocks. Everything else
already carries over via the existing `claude-fable-5` id prefix logic
(data-retention consent, Opus 4.8 refusal fallback, which remains a
permitted fallback target for 5.1). Bedrock is intentionally untouched.
Deeper follow-up work is deferred: keeping conversation history
append-only so blocks aren't invalidated in the first place (turn-scoped
system messages, mid-conversation tool changes) and monitoring
`input_transformations` for drop reporting.
Testing:
- New unit tests covering the `block_binding` wire format (sent for
`claude-fable-5-1` only) and beta-header wiring in `Model::from_listed`.
- `cargo nextest run` for `anthropic`, `language_models`,
`language_models_cloud`, and `copilot_chat`; `cargo fmt --check`.
Release Notes:
- Improved support for Claude Fable 5.1
Zed asked each language model which JSON Schema dialect it wanted, and
rewrote every tool's schema into that dialect before sending it.
`LanguageModelToolSchemaFormat` had grown three variants, and providers
picked between them by model name, so Grok and Gemini took a lossy path
while everything else did not.
The subset exists because Google's `FunctionDeclaration.parameters`
field accepts an OpenAPI-flavored schema rather than JSON Schema, and
`adapt_schema_to_format` tried to translate into it. The translation was
best-effort: constructs it could not represent were left in place and
the function still returned `Ok`. The shape schemars produces for a Rust
`String | Vec<String>` union survives as a nested `anyOf` whose outer
node carries no `type`, and Vertex rejects the entire request over it,
taking every other tool down with it. Where the translation did fail,
the caller logged the error and dropped the tool, so the model silently
lost a capability.
Google now offers `parametersJsonSchema` alongside `parameters`, which
takes plain JSON Schema, and every other provider we ship documents JSON
Schema for function parameters. So the first commit switches
`into_google` to `parametersJsonSchema`, and the second deletes the
dialect: `LanguageModelToolSchemaFormat`,
`LanguageModel::tool_input_format`, `adapt_schema_to_format`, and the
per-model branching in every provider go away, along with
`x_ai::Model::requires_json_schema_subset`.
What remains is `normalize_tool_schema`, which every tool now passes
through. It strips `$schema`, `title`, and `description` from the root,
which no provider reads and which cost tokens; gives an object schema an
explicit `"properties": {}`, which OpenAI requires; and inlines
same-document `$ref`s. That last part is carried over from the deleted
code and matters only for context servers: MCP's Python SDK derives
input schemas through pydantic, which emits `$defs` and `$ref` for any
nested model or enum, and `zod-to-json-schema` emits `definitions` for
reused shapes, while Google rejects references outright. Built-in tools
never contain one, because `root_schema_for` inlines subschemas during
generation. A schema whose references cannot all be resolved is passed
through untouched and the reason logged, so a provider explains what is
wrong instead of receiving something half-rewritten.
## Providers whose behavior changes
| Provider | Models affected | Before | After |
|---|---|---|---|
| Google | all | `JsonSchemaSubset` in `parameters` | full JSON Schema
in `parametersJsonSchema` |
| Zed Cloud | Google, xAI | `JsonSchemaSubset` | full JSON Schema |
| Copilot Chat | Google, xAI, unknown vendors | `JsonSchemaSubset` |
full JSON Schema |
| xAI | Grok 4.3, 4.5, 4.6, 4.20 Reasoning, 4.20 Non-Reasoning |
`JsonSchemaSubset` | full JSON Schema |
| OpenRouter | model ids containing `gemini` or `grok` |
`JsonSchemaSubset` | full JSON Schema |
| Vercel AI Gateway | all | `JsonSchemaSubset` | full JSON Schema |
| OpenAI-compatible | all | `JsonSchemaSubset` | full JSON Schema |
| Bedrock Mantle | all | `JsonSchemaSubset` | full JSON Schema |
| Everything else | — | `JsonSchema` | unchanged apart from
normalization |
One deliberate difference for the last row: the old `JsonSchema` path
also injected `additionalProperties: false` into object roots, and
normalization does not. Nothing depends on it. Serde ignores unknown
fields, so a model inventing an argument never broke deserialization,
and OpenAI's strict function calling — the one feature that requires the
flag — is never enabled: every `ToolDefinition::Function` in the tree
passes `strict: None`. It was also only ever applied on the `JsonSchema`
path, so Google, Grok, Vercel and Bedrock Mantle users never received
it. Dropping it makes behavior uniform rather than removing a guarantee.
## Verification
This was checked against live providers rather than by reasoning about
documentation. A harness in the Delta repository dumps all 24 built-in
tool schemas from this branch and submits them with `tool_choice: none`
to each provider, so the only thing under test is whether the provider
accepts the schemas. Anthropic, OpenAI (chat and responses), Gemini,
xAI, Baseten, OpenRouter (Gemini and Grok), Vercel AI Gateway (Gemini
and Grok), Copilot (Gemini and Grok), the ChatGPT subscription, Bedrock
Converse, Bedrock Mantle (GPT and Grok), and Zed Cloud (Anthropic,
OpenAI, and Google) all accepted them. DeepSeek, Mistral, and OpenCode
were not probed for lack of a key.
The failure this fixes is reproducible on the route that broke. Vertex,
not the Gemini Developer API, is what enforces the constraint: the
harness pins the `grep` declaration production generated, replays it to
Vertex through Zed Cloud in the legacy `parameters` field, and gets back
the exact `INVALID_ARGUMENT` naming `parameters.globs`, while the same
route accepts this branch's schemas through `parametersJsonSchema`. The
Gemini Developer API accepts the broken shape on every model tried, so a
direct API key would never have caught it.
Testing:
- `cargo nextest run -p language_model_core -p google_ai -p agent` for
the schema, `into_google`, MCP and built-in tool tests
- New tests cover reference inlining for the shapes pydantic and zod
produce, recursive references, and unresolvable references
- `built_in_tool_schemas_are_normalized` asserts every built-in tool is
present and normalized
- `crates/agent/examples/dump_tool_schemas.rs` prints the definitions
the harness consumes
- 21 live provider probes with the complete tool set
Release Notes:
- Fixed Gemini rejecting requests because Zed translated tool schemas
into a restricted dialect it could not represent
Language model event mappers run as part of lazy completion streams.
Because these streams are polled on the main thread, repairing and
parsing large streamed tool inputs can freeze the UI.
This moves completion stream mapping to background executors. A bounded
channel preserves event order and backpressure, while dropping the
stream cancels its background task. The change covers all providers that
perform this work.
Release Notes:
- Fixed UI hangs when language model providers stream large tool inputs.
Language model providers can reject a request inside an otherwise
successful response stream. Those failures were represented by
overlapping completion-error variants and provider-specific code enums,
and OpenAI Responses errors such as `cyber_policy` fell through to
`Other`. Agent sessions consequently retried permanent provider
rejections and user interfaces lost the provider's actionable message.
This gives every provider-originated failure one shared representation.
`ProviderRejection` preserves the provider, exact message, retry delay,
raw provider code, and an HTTP status only when one was actually
reported. `ProviderErrorCategory` supplies the normalized meaning used
by shared UI and policy code. Provider adapters map their native wire
errors into that category explicitly, so typed SDK exceptions and errors
embedded in successful streams no longer fabricate HTTP statuses.
Retry selection is independent from error construction.
`LanguageModelCompletionError::retry_delay` owns transient
classification and a bounded schedule of 5, 10, 20, then 40 seconds. A
provider-supplied `retry_after` overrides that schedule. The scheduling
layer adds positive jitter of up to 10%, while interactive requests and
evaluation runs retain their own attempt budgets. Permanent status-less
errors such as `cyber_policy` do not retry. OpenRouter also keeps its
numeric body code distinct from an optional HTTP status, including for
errors embedded in a stream.
Testing performed:
- `corgi test -p language_model_core`
- `corgi test -p anthropic` (33 tests)
- `corgi test -p open_ai` (77 tests)
- `cargo nextest run -p open_router -p copilot_chat -p
language_models_cloud -p language_models` (125 tests)
- `cargo nextest run -p agent -p agent_ui` (1,153 tests; 11 skipped)
- `cargo check -p open_router -p copilot_chat -p language_models_cloud
-p language_models -p agent -p agent_ui`
- `./script/clippy -p language_model_core -p anthropic -p open_ai -p
open_router -p copilot_chat -p language_models_cloud -p language_models
-p agent -p agent_ui` completed the release Clippy phase; Cargo Shear
then reported the repository's existing warnings
- `cargo fmt --all --check`
Suggested .rules additions
None.
Release Notes:
- Fixed permanent language model provider rejections being retried and
displayed without their actionable provider message.
Language model transport errors currently retain only a provider display
name after an HTTP request fails. Downstream clients therefore cannot
tell users which configured endpoint was unreachable without parsing the
source error or hard-coding provider names.
Make the request hostname a required part of
`LanguageModelCompletionError::HttpSend` and preserve it through the
Anthropic, OpenAI-compatible, OpenRouter, Vercel AI Gateway, and Zed
Cloud transports. Each transport captures the parsed hostname from the
request URI before sending it, using the configured base URL as the
defensive fallback. This supports production, development, and custom
endpoints without string matching.
Tests exercise transport failures through the real request paths and
verify hostnames for Anthropic, ChatGPT Subscription, generic
OpenAI-compatible providers, and Zed Cloud.
Testing:
- `cargo fmt --check`
- `cargo nextest run -p anthropic -p open_ai -p open_router -p
language_models_cloud -p language_models` — 209 tests passed
- `cargo check -p agent -p agent_ui --all-targets`
- `git diff --check`
- `./script/clippy -p language_model_core -p anthropic -p open_ai -p
open_router -p language_models_cloud -p language_models` — clippy
passed; the script subsequently failed in the repository-wide `cargo
shear --deny-warnings` step on 203 pre-existing target and doctest
configuration warnings
Release Notes:
- Improved language model connection errors to identify the unreachable
host.
Explicit compaction (`LanguageModel::compact`) was previously
implemented only for OpenAI-routed cloud models, which use a dedicated
compact operation proxied through `/completions/compact`. Anthropic
models only compacted automatically when a request's `compact_at_tokens`
trigger was crossed, leaving consumers without a provider-backed way to
request compaction immediately.
Anthropic has no compact-on-demand operation, but the `compact_20260112`
context-management edit provides the necessary pieces: the lowest
trigger the API accepts, 50,000 input tokens, combined with
`pause_after_compaction`, which stops the response after the compaction
block. Explicit compaction requests remove tools so the internal
summarizer must produce replacement context while retaining Anthropic's
default summarization prompt. The resulting readable summary, optional
opaque provider state, and usage are collected consistently.
This implements explicit compaction for both direct and hosted Anthropic
models. Hosted requests use the normal `/completions` endpoint; gateway
support for forwarding the compaction fields landed in
zed-industries/cloud#3216. Models expose the 50,000-token minimum so
callers can disable explicit compaction below the provider's floor.
Calls made below that floor still fail if the stream produces no
finalized compaction context.
The existing OpenAI compact operation is moved into a provider-specific
helper without changing its request, endpoint, response handling, or
provider-state ownership.
Testing:
- `cargo nextest run -p anthropic -p language_models_cloud -p
language_models`
- `./script/clippy -p anthropic -p language_model -p
language_models_cloud -p language_models`
- `cargo fmt --all --check`
- `git diff --check`
Release Notes:
- N/A
---------
Co-authored-by: Anant Goel <anant@zed.dev>
# Objective
Add explicit conversation compaction for OpenAI Responses API models,
available through both direct OpenAI connections and Zed Cloud models.
Keep finalized replacement context provider-neutral and separate from
the lifecycle events emitted while automatic compaction is in progress.
## Solution
- Add opt-in explicit compaction support to the `LanguageModel` trait.
- Separate streamed `CompactionUpdate` lifecycle events from finalized
`CompactedContext`.
- Represent provider-native compacted context as an opaque, versioned
state owned by the originating provider.
- Construct compact requests through the same OpenAI request conversion
used for completions, then narrow the request to fields supported by
`/responses/compact`.
- Preserve and validate the complete canonical replacement window
returned by OpenAI.
- Replay the replacement window before messages sent after compaction,
without resending the superseded transcript.
- Support explicit compaction through both the direct OpenAI provider
and `CloudLanguageModel`.
- Update automatic OpenAI and Anthropic compaction to use the same
finalized context representation.
- Reject empty, malformed, incorrectly versioned, and incorrectly owned
provider state.
The corresponding Cloud change adds the `/completions/compact` proxy
route: https://github.com/zed-industries/cloud/pull/3099.
The downstream Delta UI integration is
https://github.com/zed-industries/delta/pull/1739.
## Testing
- `cargo nextest run -p anthropic -p open_ai -p language_models_cloud`
- `cargo check -p language_models --tests`
- `cargo fmt --all --check`
- `git diff --check`
The focused tests cover request construction, canonical-window
preservation and replay, direct and Cloud transports, automatic
compaction lifecycle events, malformed provider state, provider
ownership, format compatibility, and HTTP failure handling.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Added: System messages are now sent through the `instructions` field
in OpenAI Responses API requests.
# Objective
Allow zed's language model stack to express OpenAI Responses API custom
tools (freeform text-input tools with an optional lark/regex grammar),
so downstream consumers can offer tools like a freeform `apply_patch` to
GPT models.
## Solution
- `LanguageModelRequestTool` now carries a Function-vs-Custom input
variant; `LanguageModelCustomToolFormat` models text/grammar formats.
- `LanguageModelToolUse.input` becomes a typed
`LanguageModelToolUseInput::{Json, Text}`. Serialization is tagged so
persisted Text inputs round-trip losslessly; legacy plain JSON values
still deserialize as `Json`.
- `open_ai` gains the custom tool wire types (tool definition,
`custom_tool_call`/`custom_tool_call_output` input items with
string-or-content-part outputs, output item, and
`custom_tool_call_input` delta/done stream events). The Responses event
mapper accumulates raw text deltas into `ToolUse` events, and history
replay derives custom-vs-function tool results from the matching
`ToolUse` by id.
- All non-OpenAI providers and the Chat Completions path error
explicitly when a request contains custom tools — no silent drops or
empty-schema coercions.
Release Notes:
- N/A
# Objective
Fix OpenAI-compatible reasoning/thinking support. Previously,
`OpenAiCompatibleLanguageModel` never reported thinking support, so
configured `reasoning_effort` values did not reliably reach the wire and
Responses API reasoning state could miss `include:
["reasoning.encrypted_content"]`.
Fixes#58289
Addresses #59207 for OpenAI-compatible Responses models configured with
`reasoning_effort`.
## Solution
- Treat a non-`none` configured `reasoning_effort` as OpenAI-compatible
thinking support.
- Expose common OpenAI-style effort levels in the agent UI, using the
configured effort as the default.
- Honor selected reasoning effort for OpenAI-compatible chat-completions
requests.
- Send `reasoning_effort: "none"` when thinking is disabled for a
configured reasoning model.
- Preserve native OpenAI behavior by continuing to use native
model-specific supported efforts and `max_completion_tokens`.
- Add an OpenAI-compatible `max_tokens_parameter` capability for
endpoints that expect output limits as `max_tokens`.
- Parse common streamed thinking fields (`reasoning` and
`reasoning_content`).
- Add provider setup UI and docs for configuring OpenAI-compatible
reasoning models.
## Testing
- `cargo fmt -p language_model_core -p agent_ui -p language_models`
- `cargo test -p language_models provider::open_ai_compatible::tests
--lib`
- `cargo test -p language_models provider::open_ai::tests --lib`
- `cargo test -p open_ai completion::tests --lib`
- `cargo test -p agent_ui
agent_configuration::add_llm_provider_modal::tests --lib`
- `git --no-pager diff --check`
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Improved OpenAI-compatible provider setup for reasoning models.
---------
Co-authored-by: Anant Goel <anant@zed.dev>
Adds provider-side context compaction support to the Anthropic and
OpenAI API clients. Client plumbing only; not wired into the UI.
Release Notes:
- N/A
Claude Fable 5 always thinks and cannot honor a request with thinking
disabled, but the cloud models listing gives clients no way to tell it
apart from models where thinking is optional (e.g. Claude Opus 4.6):
both report `supports_thinking: true` plus the same adaptive effort
levels. As a result, the agent panel shows a thinking toggle for Fable
even though turning it off isn't actually supported.
zed-industries/cloud#2789 adds a `supports_disabling_thinking` field to
the models listing. This PR mirrors it through
`cloud_llm_client::LanguageModel` (serde-defaulted to `false`, so a
server without the field is treated as "don't claim thinking can be
turned off") and exposes it as
`LanguageModel::supports_disabling_thinking()`, forwarded from the
listing by `CloudLanguageModel`. The agent panel now hides the thinking
toggle for models that report `false`, showing only the effort selector.
The trait default is `true`: every non-cloud provider in the tree treats
thinking as toggleable today, and only the cloud listing knows about
always-thinking models.
Draft until zed-industries/cloud#2789 lands and deploys.
Release Notes:
- Fixed the agent panel offering a thinking toggle for models that
cannot run with thinking disabled.
Stop the Zed cloud LLM provider from funneling completion failures
through anyhow::Error and collapsing them into
LanguageModelCompletionError::Other (which surfaced as a generic
"Request failed.").
- perform_llm_completion now returns a typed
LanguageModelCompletionError, mapping each failure to its real variant
(SerializeRequest, HttpSend, ApiReadResponseError, and ApiError-derived
status variants).
- response_lines yields a typed ResponseStreamError so mid-stream read/
deserialize failures become ApiReadResponseError/DeserializeResponse
without a runtime downcast.
- Add a first-class PaymentRequired variant for HTTP 402 and remove the
now-dead PaymentRequiredError struct and its anyhow downcast checks.
Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
<img width="325" height="201" alt="Screenshot 2026-06-09 at 1 38 32 PM"
src="https://github.com/user-attachments/assets/a6518073-1e17-41ff-a8fc-cb279fcd4436"
/>
Adds support for Anthropic's Claude Fable 5 model when using your own
Anthropic API key. Because Fable 5 cannot be offered under Zero Data
Retention (Anthropic retains inference logs for 30 days), this gates the
model behind an explicit data-retention consent: a new
telemetry.anthropic_retention setting (default off, surfaced in the
Privacy section of the settings UI), and a hard, non-retryable check in
the cloud completion path that raises a typed error when consent is
missing.
When Fable 5 declines a request, it transparently falls back to Claude
Opus 4.8 (matching Anthropic's server-side behavior), and the agent
panel shows a callout for the consent error with "Switch to Opus 4.8" /
"Accept" actions that resume the failed turn so the user's message
continues without retyping.
Closes AI-382
Release Notes:
- Add Claude Fable 5 to Anthropic BYOK
---------
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
#56472 broke Copilot chat
> Failed to connect to API: 400 Bad Request {"message":"cache_control:
Extra inputs are not permitted"}
This PR makes it so that we still use the legacy caching approach for
Copilot
Release Notes:
- N/A
Code had been assuming (erroneously, but understandably) that
LlmApiToken::acquire would give them a valid token.
This is not true, as those tokens expire and you must call refresh
explicitly.
Add some helpers to do the retry for you, and rename acquire to cached
to be
clearer about the intent.
Closes #ISSUE
Release Notes:
- Fixed some rare cases where API requests would fail with Unauthorized
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>
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
- `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>