# Objective
- Fix V4 edit prediction requests failing for local Windows projects
because native path separators do not match Unix-formatted context paths
on the server.
## Solution
- Canonicalize serialized buffer paths through the existing `RelPath`
representation.
## 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Suggested .rules additions
- Paths serialized for edit prediction APIs must use `RelPath`'s Unix
representation rather than platform-native `PathBuf` formatting.
---
Release Notes:
- N/A
# Objective
Fixes#59129.
`vim::HelixJumpToWord` currently treats its two-character target labels
as text input. When an IME is active, the printable label keys can
therefore enter the IME composition window instead of completing the
jump.
## Solution
- Treat an active Helix jump as command input rather than character
input, preventing the platform input handler from preferring the IME for
its label keys.
- After normal keybinding resolution, handle action-less, unmodified
label keydowns directly from the keystroke's ASCII-equivalent key. This
preserves label matching on non-ASCII keyboard layouts while leaving
Escape, custom bindings, and Ctrl/Alt/Cmd/Function shortcuts untouched.
- Stop propagation after consuming a label key so the platform does not
subsequently forward it to the IME.
- Keep the existing committed-text handling as a fallback for other
input paths.
This is complementary to #61270: that PR handles pending GPUI keybinding
chords before IME input, while this change handles Helix jump labels
after the initiating action has resolved. The changes are also
file-disjoint.
## Testing
- Added a regression test using the issue's `s` → `vim::HelixJumpToWord`
binding. The test verifies that:
- no GPUI keybinding chord is pending;
- Helix jump does not accept text input or prefer the IME;
- both raw label keydown events are consumed; and
- the expected jump completes.
- Manually tested on macOS with both ABC and Japanese Romaji input
sources.
## 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:
- Fixed Helix jump-to-word label input being intercepted by IMEs.
Closes#60985
Clicking a link to a Markdown file from a Markdown preview now opens the
target in a preview instead of the raw editor buffer. `alt`-click opens
the raw source editor instead.
- If there exists existing preview of that file it is reused. A link
back to the file being previewed navigates in place.
- `file.md#heading-slug` scrolls the preview to the linked heading.
- `file.md:42:5`, `file.md#L42` and `file.md#L42C5` open the preview
scrolled to that position with the cursor placed there. Non-Markdown
targets keep the existing behavior from #60864 (raw editor at the
position).
Added tests covering these and more cases.
Release Notes:
- Improved Markdown preview links: links to Markdown files now open in a
preview (scrolled to the linked heading or position) instead of the raw
file, and `alt`-click opens the raw source instead.
- Fixed GitHub-style `#L<line>C<column>` link fragments not placing the
cursor at the linked position.
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#53517
Release Notes:
- Added Helix trim whitespace from selections action on `_`.
---------
Co-authored-by: Tom Houlé <tom@tomhoule.com>
Browser Fetch APIs must run on the main thread, while GPUI image loading
can invoke its HTTP client from background WASM workers. This routes
`FetchHttpClient` requests through the web dispatcher's main-thread
mailbox, installs the client by default for web applications, and
removes thread-affine browser state from the safely movable dispatcher.
Release Notes:
- N/A
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#54231
Related to the Opire Helix keymap bounty on #4642.
/claim #4642
Opire payout: @jamilahmadzai
Release Notes:
- Fixed Helix mode append so pressing Escape without inserting text
restores the original cursor or selection instead of leaving it one
character ahead.
---------
Co-authored-by: Tom Houlé <tom@tomhoule.com>
## Objective
- Fixes#61437 — Wide tables in doc comments get clipped instead of
being scrollable
## Solution
- Changed `.overflow_hidden()` to `.overflow_x_scroll()` on the table
rendering div in `crates/markdown/src/markdown.rs`
- When `table_columns_min_size` is true (as in the hover popover style),
grid columns use min-content sizing. Wide column content exceeds the
table width, and `.overflow_hidden()` clips it. `.overflow_x_scroll()`
makes the overflow scrollable.
- This same pattern is already used for code blocks in the same file
(line 2367).
## Testing
- Change is a single property affecting element rendering/layout
- Visual verification needed: hover a doc comment with a wide markdown
table, verify horizontal scrollbar appears and content is accessible
- Existing markdown tests should pass unchanged
## Recording
https://github.com/user-attachments/assets/d07aa6eb-ac9d-453f-9e51-453a33302cbd
---
Release Notes:
- Fixed wide tables in documentation hover popovers being clipped
instead of horizontally scrollable
# Objective
Enable the Project Panel Undo/Redo feature flag in all channels except
stable. This gives us control over when it lands in Stable, while also
allowing us to have it sit in Preview for longer than a single week, if
we want to.
## Solution
Update `ProjectPanelUndoRedoFeatureFlag::enabled_for_all` to be true on
all release channels except `ReleaseChannel::Stable`. The feature flag
doesn't allow us to scope it per environment so there's no way we could
enable the flag for all but only have it impact Preview, should have
added that safeguard in the beginning as stable is already relying on
the feature flag exclusively.
## Testing
N/A
## Self-Review Checklist:
- [x] 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
---
Release Notes:
- N/A
# Objective
Update the Project Panel's documentation to document which operations
support undo and redo behavior so it's easier for users to discover this
feature.
This Pull Request should stay in draft and only be merged after both
https://github.com/zed-industries/zed/pull/59709 and
https://github.com/zed-industries/zed/pull/59595 are merged, as
documentation mentions behavior that is being updated in both Pull
Requests.
Release Notes:
- N/A
# Objective
Update the version of `trash-rs` used in order to contain the fix for
the panic when restoring a non-existing trash item in Linux –
41c6c800d8
.
## Solution
N/A
## Testing
N/A
## Self-Review Checklist:
- [x] 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
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- N/A
As in, make it consistent with the other panels, where we use a blue
border for the focused state and a different background color for the
selected state. It's been a long time coming little design fix to the
collab panel.
<img width="450" alt="Screenshot 2026-07-27 at 8 01@2x"
src="https://github.com/user-attachments/assets/70724483-8092-4993-afd4-5faa3d3fae51"
/>
Release Notes:
- N/A
# Objective
Fixes#47119
## Solution
Strip empty-string arguments from the resolved build task in
debugger_ui::session:🏃:RunningState::resolve_scenario after
template substitution, before spawning the build command. This is the
correct place to do this as:
1.It's the first point in the pipeline where the empty strings exist as
concrete values rather than unsubstituted template variables.
2. It acts as a general safety net for any future locator that produces
a shell-command build step with placeholder args.
3. Other languages (Go, Node, Python) use build: None and pass
structured JSON directly to their DAP adapters, so they never hit this
code path.
## Testing
Performed visual and self testing by replicating the 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 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
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed unexpected argument '' upon trying to debug while cargo is
indexing
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Closes#5049.
When the system is in light mode but Zed uses a dark theme, the macOS
window chrome — the window border and the titlebar — is rendered light,
leaving a pale, low-contrast edge that makes the window look washed out.
Zed's own content renders correctly; the affected chrome is drawn by
AppKit, not Zed.
Why it happens: `NSWindow` conforms to `NSAppearanceCustomization`, so a
window's appearance is inherited app → window → view and resolved
through `effectiveAppearance` unless an explicit appearance is set. Zed
never set one, so every window inherited the *system* appearance and
AppKit drew the chrome for light mode regardless of the dark theme.
The fix uses the override AppKit provides for exactly this: set
`NSApplication.appearance` app-wide, so every window inherits it. VSCode
(`window.systemColorTheme`) and JetBrains IDEs do the same.
<img width="2600" height="1346" alt="after-light"
src="https://github.com/user-attachments/assets/c31376af-8f51-4c36-a62f-55714f63b59c"
/>
## GPUI
- Add `App::set_window_appearance(Option<WindowAppearance>)`, the setter
paired with the existing `App::window_appearance()` getter. `Some(_)`
forces a light/dark appearance; `None` clears the override and follows
the system again.
- macOS sets `NSApplication.appearance` (`None` → `nil`); no-op on other
platforms.
- Demo: `cargo run -p gpui --example window_appearance`.
## Zed
- An explicit light/dark theme (or a static theme) forces the matching
chrome; `System` follows the OS.
- Wired once at startup via a global settings observer, so every window
— including the settings window — stays in sync.
| Before | After |
| --- | --- |
| <img width="3630" height="1878" alt="before-light"
src="https://github.com/user-attachments/assets/44c9ab66-c0cf-433a-93b0-17446b34a284"
/> | <img width="3686" height="1832" alt="SCR-20260609-nzjk"
src="https://github.com/user-attachments/assets/32b0412b-0913-4e68-acba-bf39dcb6aa6a"
/> |
References:
[`NSAppearanceCustomization`](https://developer.apple.com/documentation/appkit/nsappearancecustomization)
·
[`NSApplication.appearance`](https://developer.apple.com/documentation/appkit/nsapplication/appearance)
Release Notes:
- Fixed the macOS window border and titlebar not matching the selected
theme when the system appearance differed (for example, a dark theme
under a light system theme).
([#5049](https://github.com/zed-industries/zed/issues/5049))
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes#60733
# Objective
Markdown Preview treats a relative `path:line[:column]` destination as a
literal filename. When that file does not exist, the link falls through
to the system URL handler instead of opening the workspace file at the
requested position.
## Solution
- Recognize position suffixes on relative Markdown links.
- Convert GitHub-style `#L42` fragments into the same positioned target
used by `path:42`, so both forms share one resolution and opening path.
- Resolve links with `workspace::path_link::possible_open_target` using
the Markdown source directory. This keeps the remote-project path
resolution added in #61438.
- Open resolved targets with `editor::items::open_resolved_target`,
including its one-based row and column handling.
- Preserve valid URI schemes and fall back to the existing Markdown link
behavior when no workspace target resolves.
## Testing
- Extended the Markdown Preview GPUI regression test to cover relative
`path:line:column`, GitHub-style `#Lline`, subfolder-relative
resolution, and custom URI schemes.
- `git diff --check` passes.
- The focused Rust test could not start in the current macOS environment
because the Rust toolchain binaries hang in the dynamic loader before
Cargo runs. PR Actions are awaiting maintainer approval.
## Self-Review Checklist:
- [x] I have reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed UI and icon guidelines
- [x] Tests cover the new and changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed Markdown Preview links using workspace-relative paths with line
and column suffixes.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
# Objective
- Treat a follow-up sent during pending tool approval as a denial the
agent can understand.
## Solution
- Preserve the follow-up interruption through permission handling and
return a specific denial result to the model.
## 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:
- Agent: Fixed agents not recognizing follow-up messages as denial of
pending tool calls.
Long-lived streaming responses (LLM completions) can stall when the
socket goes silent but the connection is never closed, leaving a read
that never returns to hang the request indefinitely. Add an opt-in
read_timeout parameter.
Release Notes:
- N/A
# Objective
Fix a nightly crash where Zed aborts on a bounds-check panic in the
inlay hint cache.
`LspStore::inlay_hints` captures a `RowChunk` before awaiting the
language server, then reads the hint cache with that chunk's id
afterwards. If the buffer shrank meanwhile, `latest_lsp_data` has
already rebuilt the cache with fewer chunks, so the stale id indexes out
of bounds. Chunks are 50 rows, so the reported crash only needed a
~150-250 line deletion, not a drastic edit.
Regressed in #61523. Nightly only; the regressing commit is in no
release tag, so this never reached preview or stable.
Fixes ZED-AGY
Fixes FR-142
## Solution
- Return an empty result when the buffer version no longer matches, so a
stale chunk id can never index the rebuilt cache. The stale *writes*
were already guarded by this version check; only the read sat outside
it.
- An empty result is already treated as "not fetched", so the chunk is
simply re-requested on the next refresh.
## Testing
`test_inlay_hint_response_after_buffer_shrinks` reproduces the abort
deterministically and passes with the fix. Note that it drives the race
through a fake language server rather than a real one.
## 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:
- N/A
Some crates in zed use `include_str!("../../zed/RELEASE_CHANNEL")`,
which breaks when used as a dependency in a crane nix build (each crate
is built in isolation).
This adds a compile time env var to skip that check, which allows crates
in the zed repo to be used as dependencies in a crane build.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
Closes FR-139
Most focus-lost issues that close the agent panel in Zen mode stem from
panels returning a transient child editor's focus handle from
`Focusable::focus_handle`. The Zen-mode check closes the zoomed panel
when the focused element is not a descendant of the panel's focus
handle, so any focus movement inside the panel that landed outside that
child editor looked like the panel losing focus.
This PR separates the two roles that handle was serving:
- `Focusable::focus_handle` now always returns a stable handle tracked
at the panel's root element, used for containment checks (Zen-mode
auto-close, `toggle_panel_focus`, dock focus subscriptions).
- The new `Panel::activation_focus_handle` returns what should receive
focus when the panel is activated (e.g. a filter/commit/message editor)
and must be a focus-tree descendant of the root handle. All "focus the
panel" callsites in workspace/dock now use it.
Migrated panels: `AgentPanel` (including thread views and the toolbar
title editor), `CollabPanel`, `GitPanel`, `OutlinePanel`, and
`TerminalPanel` (previously delegated to the active pane, so focus in a
non-active pane dropped containment). `CollabPanel` activation falls
back to the panel root when signed out or collaboration is disabled,
since the filter editor isn't rendered in those states. Also fixes
duplicate element ids for tool calls with multiple content blocks.
Tests: a regression test that clicks tool-call output and focuses the
thread title editor while zoomed (both previously closed Zen mode), and
a dock-level test asserting the activation handle receives focus on
panel activation while the panel root reports containment.
Release Notes:
- Fixed zoomed panels (e.g. the agent panel in Zen mode) closing
unexpectedly when focus moved to elements inside the panel, such as tool
call output or the thread title editor.
Fixes Amazon Bedrock adaptive-thinking requests so the selected effort
reaches Anthropic models, and routes Claude Opus 4.7 and 4.8 through
their documented Japanese and Canadian inference profiles.
Release Notes:
- Fixed Amazon Bedrock effort selection and regional routing for Claude
Opus 4.7 and 4.8.
# Objective
I expected a different label for reverting a file deletion like Zed
already has for reverting a file creation.
## Solution
This PR implements a new label and prompt. VS Code also shows a
different prompt while keeping the label static but I think it makes
more sense to let both adapt.
## Testing
Just deleted a file and checked menu label and prompt.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] 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)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
## Showcase
<img width="363" height="139" alt="image"
src="https://github.com/user-attachments/assets/6be7e5b9-7250-449e-9cba-ea5a2099dd3a"
/>
<img width="349" height="240" alt="image"
src="https://github.com/user-attachments/assets/d87d5b4b-ff29-4976-8078-314c94a71896"
/>
---
Release Notes:
- Git Panel: Added specific label and prompt to context menu for
reverting a deleted file
## Context
Closes#61394
The Text Finder persists the last query per workspace (in the
`text_finder_queries` table) so it can seed itself on reopen.
Persistence happens in `TextFinder::on_before_dismiss`, but it was
guarded by `if !query.is_empty()`, so clearing the query and dismissing
never wrote anything. The stale non-empty query stayed in the database
and got restored on the next open, making it impossible to "clear and
keep it cleared."
This removes the guard so dismissal always persists the current query,
including an empty one. The read side already treats an empty stored
query as "nothing to restore" (`load_last_search` returns `None` for an
empty string), so an empty write cleanly clears the seed instead of
leaving the previous query behind.
Manual test below :
[Screencast from 2026-07-24
15-24-33.webm](https://github.com/user-attachments/assets/ba305f54-8ec2-4d3d-be0b-e2eb001bb204)
## How to Review
**`crates/search/src/text_finder.rs`**
`on_before_dismiss` no longer gates the write on a non-empty query. It
always calls `store_last_search` with the picker's current query and
options. `store_last_search` still early-returns for workspaces without
a `database_id`, so unpersisted workspaces are unaffected, and
`load_last_search` still maps an empty persisted query to `None`, so
`seed_query` won't resurrect it. The active-item selection still takes
priority over the persisted value on reopen, so seeding from a live
editor selection is unchanged.
The tests' shared `init_test` now installs a test `db::AppDatabase`
global. This is required because the new test is the first one to
actually reach `TextFinderDb::global(cx)`. The existing
`test_dismiss_from_within_workspace_update` leaves the workspace's
`database_id` as `None`, so it short-circuits before touching the DB.
`test_clearing_query_does_not_restore_previous_query` exercises the real
persistence path: it assigns a workspace `database_id`
(`set_random_database_id` + `flush_serialization`), opens the finder
with a query, dismisses, and asserts the query round-trips through
`seed_query`; then it reopens, clears the query via `set_query("")`,
dismisses, and asserts `seed_query` is now `None`. The positive
round-trip assertion keeps the negative case from passing vacuously.
## Self-Review Checklist
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed the project search / Text Finder restoring a previous query
after it had been cleared and dismissed
Closes https://github.com/zed-industries/zed/issues/60777
# Objective
- Due to #59426, forcing docString softmark to hardmark, an regression
has appeared. It causes all docString on different language to load
newLine (`\n`) by default, instead of soft wrap.
- By checking the issue, turns out we should not setting
`soft_break_as_hard_break: true`, this will make the hover docString
less
- Details can refer to #60777
## Solution
- Revert settings by removing the line in `hover_popover.rs:742`
## Testing
- About the testing result and comparsion, you can refer to #60777
- Updated test `test_hover_markdown_preserves_soft_breaks` to
`test_hover_markdown_soft_breaks_reflow_per_commonmark`
## 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:
- Fixed an issue where hover documentation could have too many line
breaks.
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
## Problem
When `api_url` points to a proxy or gateway that appends `data: [DONE]`
to the SSE stream, every streaming completion fails with:
```
error deserializing Anthropic API response: expected value at line 1 column 2
```
In the UI this surfaces as **"error deserializing Anthropic API response
— Retrying (Attempt 3 of 3)"** followed by **"Connection Interrupted"**,
even though the proxy returned a well-formed stream and the model's full
response was already delivered before the terminator. The failure is
100% reproducible on multi-turn tool-use conversations (Zed reads the
stream to completion after each turn, so it always reaches the trailing
`[DONE]`) and intermittent on single-turn conversations (depending on
whether the connection closes before the line is read). The same class
of error appears in the `google_ai` crate as `Error parsing JSON: ...
"[DONE]"`.
Neither side is at fault here. Zed's current parser is a correct
implementation of the Anthropic and Gemini specs, which terminate
streams by connection close and never emit `[DONE]`; at the same time,
appending a `[DONE]` terminator is a common, legitimate convention among
SSE gateways. This PR is a compatibility improvement that makes Zed
robust to that widely-used stream shape, so streaming works whether or
not the upstream emits the terminator.
## Why Zed crashes but the Anthropic SDK does not
The Anthropic TypeScript and Python SDKs handle this correctly
**without** any explicit `[DONE]` check. Their SSE parser uses a
two-layer architecture:
1. **SSE framing layer** — parses `event:` / `data:` fields into
`{event, data}` objects without inspecting the data payload.
2. **Event dispatch layer** — only calls `JSON.parse` on events whose
`event` name is in a known whitelist (`message_start`,
`content_block_delta`, etc.). A bare `data:` line with no preceding
`event:` line yields `event: null`, which is not in the whitelist and is
silently ignored.
So when a proxy sends `data: [DONE]`, the SDK produces `{event: null,
data: "[DONE]"}`, the dispatch layer drops it, and `JSON.parse` is never
run on `[DONE]`. Claude Code and Cline both use the Anthropic SDK under
the hood, so they inherit this behavior and never crash on `[DONE]`.
Zed's `anthropic` and `google_ai` crates use a simpler single-layer
parser: strip the `data:` prefix, then unconditionally
`serde_json::from_str` the remainder. There is no event-name dispatch,
so `[DONE]` goes straight into the JSON parser — `[` looks like an array
start, `D` is not a valid value, serde reports `expected value at line 1
column 2`, and the stream dies.
## Fix
Add a one-line guard after prefix stripping: if the trimmed payload is
`[DONE]`, return `None` from the `filter_map` closure. This is a
lightweight equivalent of the SDK's whitelist-ignore behavior — same
result (silently skip the terminator), without restructuring the parser
into a full event-name dispatch architecture.
Two commits, one per crate:
1. `anthropic` — guard in `stream_completion_with_rate_limit_info`
2. `google_ai` — identical guard in `stream_generate_content`
## Scope
The other ten SSE-based providers in this repo (`open_ai`, `deepseek`,
`mistral`, `open_router`, `lmstudio`, `llama_cpp`, `copilot_chat`)
already handle `[DONE]` because their upstream specs (OpenAI-compatible)
define it as a required stream terminator. `ollama` (NDJSON) and
`bedrock` (AWS SDK event stream) do not use SSE. After this PR, every
SSE parser in Zed handles `[DONE]` without error.
## Safety
- Official Anthropic and Gemini APIs never send `[DONE]`; the guard is a
no-op on direct connections.
- `line.trim() == "[DONE]"` handles both `data: [DONE]` and
`data:[DONE]`.
- Returning `None` drops the line silently; the stream concludes on the
next EOF as usual.
Release Notes:
- Fixed streaming completions failing with "error deserializing
Anthropic API response" when the SSE endpoint appends a `[DONE]` stream
terminator (affects custom `api_url` proxies for Anthropic and Google
Gemini)
# Objective
Currently, when a model provides the wrong parameters to the edit file
tool, it gets back the opaque error message `data did not match any
variant of untagged enum ValueOrJsonString`.
At least some models (DeepSeek in my experience) can't figure out what
to do from this point, and keep trying the same wrong parameter names in
the tool call before eventually falling back to using `ed`.
This may address https://github.com/zed-industries/zed/issues/58622.
## Solution
Rather than attempting to deserialize to the `ValueOrJsonString` enum,
try to deserialize as a JSON string and then as a value in turn, so that
deserialization errors better propagate.
## Testing
Using DeepSeek V4 Pro.
Tried it out in a reloaded conversation where the edit tool was
consistently failing.
Asked it to stress-test the edit tool. Only one edit failed after a few
successful attempts, and returned the error message "missing field
`new_text`".
Subsequent edits worked again rather than resulting in a doom loop. I
don't think the model noticed what happened, but it seemed to help.
<img width="366" height="551" alt="image"
src="https://github.com/user-attachments/assets/6f9c0c8d-bf94-4670-bad0-0ead5c1fff4e"
/>
...
<img width="346" height="153" alt="image"
src="https://github.com/user-attachments/assets/2afa2901-9a90-4142-aa9d-ff32a7be0d0c"
/>
---
Release Notes:
- Improved edit_file tool error messaging.
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
Objective:
Allow users to configure the font families used by agent panel content
separately from the main UI and buffer fonts.
Solution:
- Add `agent_ui_font_family` for agent responses in the agent panel.
- Add `agent_buffer_font_family` for the agent panel message editor and
user messages.
- Keep context menus on the primary UI font family.
- Document the new settings and expose them in the settings UI.
Testing:
- Ran `cargo fmt`.
- Ran `cargo check -p settings_content -p theme_settings -p markdown -p
agent_ui -p settings_ui -p ui`.
- Ran `git diff --check`.
- Manually tested the agent panel font behavior in a dev build.
Release Notes:
- Added settings for configuring agent panel UI and buffer font
families.
Co-authored-by: Finn Evers <finn@zed.dev>
This should hopefully fix the issue with the version bumps we were
seeing - to bypass push protections, the token seems to need workflow
permissions for some reason as well.
Release Notes:
- N/A
# Objective
Make hsla functions `const`.
## Solution
Made Hsla-related functions `const fn`.
## Testing
> Did you test these changes? If so, how?
Ran `cargo test -p gpui color` to verify the color-related tests pass.
> Are there any parts that need more testing?
No additional testing is required since this change only changes
existing color functions to `const fn`.
> How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Reviewers can run `cargo test -p gpui color` to verify the changes.
> If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Tested on macOS. No platform-specific behavior is expected.
## 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:
- N/A
Agent checkpointing is implemented by staging selected files to a
temporary git index file, then creating a commit. To avoid checkpointing
commonly-excluded files even when the user doesn't have them in their
gitignore, we write a temporary override to .git/info/exclude while
running the staging. However, this causes us to do an unnecessary git
scan when a checkpoint happens, because in general we want to do this
when `.git/info/exclude` changes (the user might have edited it).
This PR fixes that by doing the staging in two steps:
- First, we stage any tracked files
- Then we get a list of untracked files to include and stage those
explicitly. The list is obtained by running `git ls-files` with a custom
ignore file in addition to the `--standard` ignores; we write that
custom ignore file to a path ending in `tmp` under .git, which means
that our worktree code will not start a git scan in response to its
events (the same way it already works for the temporary index file).
.git/info/exclude is never touched. Note that we already listed all
untracked files before this PR, in order to exclude the large ones.
Release Notes:
- Fixed Zed doing unnecessary work when the agent created a checkpoint.
# Objective
Fixes#59952.
Zed crash-loops on launch. The faulting thread aborts inside the Rust
standard library while closing a directory handle during background
worktree scanning: `std`'s `DirStream::drop`
(`library/std/src/sys/fs/unix.rs`) `assert!`s that `closedir()` succeeds
unless the error is `EINTR`. That handle originates in
`RealFs::read_dir`, which wraps `std::fs::read_dir(path)` in
`stream::iter(...)` and carries the live `ReadDir` across async
boundaries; the worktree `BackgroundScanner` (`scan_dir` →
`forcibly_load_paths`) later drops the stream. If `closedir()` returns a
non-`EINTR` error (e.g. `EBADF` under file-descriptor pressure — seen
alongside repeated `unable to start FSEvent stream` warnings on a large
dependency tree), `std` panics inside `Drop`. Zed's
`crashes::panic_hook` turns any panic into `process::abort()`, and
because the same workspace is re-scanned every launch, this is a
permanent crash loop. (`catch_unwind` can't help: the hook aborts before
unwinding.)
## Solution
Stop relying on `std`'s asserting close. Add a `read_dir_entries(path)`
helper that reads entries eagerly so the directory handle is opened and
closed within a single call:
- On unix, read via libc (`opendir`/`readdir`/`closedir`) and
**deliberately ignore a failing `closedir`**, so a close error degrades
gracefully instead of aborting the process.
- On non-unix, keep `std::fs::read_dir` (which has no such assert) but
collect eagerly so the handle is dropped within the call.
`RealFs::read_dir` now calls this helper. The change is scoped to
`crates/fs/src/fs.rs`; the watcher, scanner, and panic hook are
untouched.
## Testing
- Added unit tests in `crates/fs/src/fs.rs` for `read_dir_entries`:
entry listing, `.`/`..` exclusion, empty directories, and the
missing-directory error path.
- `cargo test -p fs read_dir` → 3 passed.
- `RUSTFLAGS="-D warnings" cargo build -p fs`, `cargo clippy -p fs
--all-features --all-targets -- -D warnings`, and `cargo fmt -p fs
--check` are all clean.
- Tested on macOS (aarch64). The `fs` crate compiles within the full
`cargo build -p zed` graph. I could not produce a running app binary in
my environment (the `gpui_macos` Metal step needs full Xcode, not just
Command Line Tools) — reviewers on a full Xcode setup can `cargo run -p
zed`.
- The original `closedir` `EBADF` is not deterministically reproducible,
so the fix is structural rather than verified against a live repro; the
tests guard the read path and behavior.
## 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 — N/A (no UI change)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed Zed crash-looping on launch when `closedir` fails during
background directory scanning
([#59952](https://github.com/zed-industries/zed/issues/59952)).
---------
Co-authored-by: Cole Miller <cole@zed.dev>
Save tasks can suspend while waiting for prompts, formatting, or
filesystem I/O. Holding only a WeakEntity<Pane> allowed the pane to be
released during those suspension points, surfacing an internal 'entity
released' error as a failed save.
Instead upgrade the pane once the save operation starts so we can ensure
it finishes.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
## Summary
- Dragging a binary file (docx, xlsx, pdf, etc.) into the agent panel's
message editor inserted a mention link, then asynchronously tried to
load its content as a text buffer. That failed with "Binary files are
not supported", which surfaced an error toast **and** deleted the
mention text that had already been inserted.
- `confirm_mention_for_file` now catches that specific failure and falls
back to `Mention::Link` (a path-only reference, same as directory
mentions already use), instead of failing the whole mention and
reverting the edit.
## Test plan
- [ ] Drag a `.docx` or `.xlsx` file into the agent panel chat input —
the file path mention should stay inserted with no error toast.
- [ ] Drag a regular text file in — content mention still works as
before (unaffected code path).
Release Notes:
- Fixed dragging a binary file (docx, xlsx, pdf, etc.) into the agent
panel deleting the inserted reference and showing a "Binary files are
not supported" error
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Closes FR-112
Otherwise, if a multibuffer snapshot changed under the hood for example
one of the paths changed, without doing an explicit validity check, we
would panic during comparison instead.
Release Notes:
- Fixed panic when hovering links during an under-the-hood multibuffer
changes.
Closes FR-133
`cosmic-text`'s BiDi line shaping machinery (`ShapeLine::new`) asserts
that every BiDi paragraph is following the same direction. It turns out
that our `gpui_wgpu` line shaping adapter would not account for that
leading to panics if text contained multiple BiDi paragraphs with
multiple directions. Not super common but worth fixing as the fix is not
super complicated. At the same time, I'd like to point out that there is
a patch submitted to `cosmic-text` that redoes shaping logic so that
this is no longer illegal:
https://github.com/pop-os/cosmic-text/pull/508 If it gets accepted, we
can revert this fix.
Release Notes:
- Fixed panic in `gpui_wgpu` if text contained multiple BiDi paragraphs
with mismatched directions.
# Objective
- The column filter popover was a static `ContextMenu`: no search, and
it didn't scale to columns with many unique values.
## Solution
- Replaced it with a `Picker<ColumnFilterDelegate>` with fuzzy search
and match highlighting over the column's unique values.
- Row order is frozen at open time (available first, then values hidden
by other filters under a "Hidden by other filters" header) so toggling a
value doesn't reshuffle the list.
- Added a footer with `{selected} / {total} rows selected` and "Clear
all".
- Added `fuzzy` and `picker` deps to `csv_preview`.
## Testing
- Search narrows to fuzzy matches with highlighting.
- Toggling a value updates its checkmark and footer count without
closing or reordering the list.
- Values excluded by another column's filter show disabled under "Hidden
by other filters".
- "Clear all" clears the column's filters and keeps the popover open.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
| Before | After |
| --- | --- |
| <img width="660" height="351" alt="image"
src="https://github.com/user-attachments/assets/c78084a2-d327-4d48-9c05-f35383455713"
/> | <img width="660" height="354" alt="image"
src="https://github.com/user-attachments/assets/910d52ef-4530-4ac7-91ac-3db318cf6c19"
/> |
**+ search**
<img width="972" height="574" alt="image"
src="https://github.com/user-attachments/assets/1a26d0fc-c96c-4973-818d-7d053e8cce73"
/>
---
Release Notes:
- N/A
Scroll events are delivered to the window under the pointer even when it
isn't focused, but we cap inactive windows at ~30fps to save energy, so
scrolling an unfocused window visibly drops frames. We now exempt
high-rate input from the cap using the existing `InputRateTracker`: a
trackpad scroll stream lifts it while events are arriving and for one
second after the last burst, then the cap resumes on its own.
## 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed dropped frames when scrolling unfocused windows.
The `dev: dump input latency histogram` and `dev: dump accessibility
tree` actions called `Project::create_local_buffer`, which panics on
remote projects — so running either one as a guest in a collab session
aborted the whole app. Both now use the async `Project::create_buffer` +
`set_text` instead (the same pattern `open_log_file` uses), which routes
through the collab protocol on remote projects.
Since the collab-created buffer is visible to other participants, the
latency report now includes a "Reported from <username>'s machine" line
when the project is shared, using the collab username so we don't expose
anything that isn't already shared with the session.
While restructuring the handler I also split snapshotting from
formatting: the histogram snapshot (and the delta baseline) is captured
synchronously when the action fires, and the report string is built on a
background task. The accessibility tree dump stays synchronous because
gpui doesn't currently expose the captured tree data outside the window
borrow, and adding public API for a debug action's JSON pretty-print
didn't seem worth it.
Release Notes:
- Fixed a crash when running the `dev: dump input latency histogram` or
`dev: dump accessibility tree` actions in a shared project.
# Objective
Fixes#59333.
Selection mentions created with "Add to Agent Thread" could not be
clicked to open the referenced file, while selection mentions created by
pasting were navigable.
## Solution
The ready selection-mention crease did not receive its `MentionUri` or
`Workspace`, so `MentionCrease` could not install its click handler.
Pass the workspace through the action-completion callback and provide
both values to the shared crease renderer, enabling its existing
navigation behavior.
## Testing
I tested these changes locally.
## 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
Before:
https://github.com/user-attachments/assets/8dd4a2d0-4b22-4fb3-8777-cf97b6436b91
After:
https://github.com/user-attachments/assets/cff1cdb3-804a-45d8-a9c5-fdd8b35b6f8f
---
Release Notes:
- Fixed selection mentions added with "Add to Agent Thread" not opening
their referenced files.
*As an LLM was used to translate the PR message, the original text is
included alongside the translation in accordance with the contributing
guidelines.
# Objective
> On Windows, GPUI accepted `WindowKind::PopUp` and `focus: false`, but
the window creation path ignored both options. This caused two problems
with the notification popup shown when an agent finished its work:
>
> * When another window had focus, the popup could appear behind it.
> * When Zed had focus, the popup could steal focus.
>
> This pull request applies `WindowKind::PopUp` and `focus: false` to
windows on Windows, bringing popup behavior in line with other operating
systems.
Windows版GPUIでは、`WindowKind::PopUp`と`focus:
false`を指定しても、それらのオプションが実際のウィンドウ生成処理では無視されていました。そのため、エージェントの作業が完了したときに表示される通知で次のような問題が発生していました。
- ほかのウィンドウにフォーカスがある場合にポップアップがほかのウィンドウの背後に隠れてしまう
- Zedにフォーカスがある場合はポップアップがフォーカスを奪ってしまう
このプルリクエストでは、Windows上でも`WindowKind::PopUp`と`focus:
false`をウィンドウに反映させるようにし、ポップアップの挙動をほかのOSと一致させます。
## Solution
> This PR updates popup creation in GPUI on Windows to match the
behavior on other platforms. When you specify `WindowKind::PopUp` and
`focus: false`, GPUI now keeps the popup above other windows without
stealing focus.
>
> Keeping a `focus: false` popup above other windows caused the IME to
commit text under composition when the popup appeared. This PR also
fixes that issue.
Windows版GPUIのポップアップの生成処理をほかのプラットフォームの挙動と一致するように変更しました。このPRでは、`WindowKind::PopUp`と`focus:
false`を指定したときにポップアップウィンドウを最前面に表示し、フォーカスを奪わないようにしました。
また、`focus:
false`のポップアップが最前面に表示されるようにしたことで、ポップアップが表示されたときにIMEで入力中のテキストが意図せず確定されるようになってしまったため、それに対する修正も含まれています。
## Testing
> I built Zed on Windows and displayed a test agent notification to
verify the following:
>
> * The popup stays above other windows when another window has focus.
> * When Zed has focus, a popup with `focus: false` does not steal focus
or interrupt IME input.
> * The buttons in the popup remain clickable.
Windows上でZedをビルドし、テスト用のエージェント通知を表示して次の項目をテストしました。
- ほかのウィンドウにフォーカスがある場合でもポップアップが最前面に表示される
- Zedにフォーカスがある場合に`focus: false`のポップアップがフォーカスを奪わず、IMEを使った入力も阻害しない
- ポップアップ内のボタンをクリックできる
## 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
> Note: I added a button to display an agent notification for testing in
this video, but this PR does not include that button.
※この動画ではテスト目的でエージェント通知を表示するボタンを追加していますが、このPRの変更には含まれていません。
### Before
The popup window is hidden when another window has focus:
https://github.com/user-attachments/assets/5312729b-1409-4c81-a169-dd031099059b
A popup with `focus: false` steals focus:
https://github.com/user-attachments/assets/dd1ac2a2-d5e8-4f8f-bc47-6cc659a10951
### After
The popup window stays on top even when another window has focus:
https://github.com/user-attachments/assets/af058921-14fc-4ca5-9698-758202c4c888
A popup with `focus: false` does not steal focus or interrupt text
input:
https://github.com/user-attachments/assets/9bc487c6-ae68-4ec0-9073-1257b91e06a9
---
Release Notes:
- Fixed Windows agent notifications appearing behind other windows,
stealing input focus, or committing active IME composition.
---------
Co-authored-by: John Tur <john-tur@outlook.com>
# Objective
- Fixes#60374
## Solution
- Moved the `documentation_label` from the `ListItem::end_slot` into the
main `h_flex` layout alongside the `main_label`.
- Added `.flex_shrink(1.0)` and `.truncate()` to the documentation
container.
- To allow it to shrink gracefully when space is tight.
- Removed `.w_full()` from the main label's container.
- To prevent it from aggressively occupying all available horizontal
space, allowing the layout to balance the width between the label and
the documentation.
## Testing
- Visual and layout fixes tested manually by verifying the completion
menu in `settings.json`.
- All unit tests in the affected crate passed: `cargo test -p editor`.
## 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
## Showcase
### Visual change
<img width="813" height="314" alt="スクリーンショット 2026-07-20 143707"
src="https://github.com/user-attachments/assets/1daa3fa4-a479-465a-b7fd-cc803242c8a2"
/>
---
Release Notes:
- Fixed(CompletionsMenu): prevent completion labels and docs from being
truncated.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>