# Objective
Add GPT-6 Astra and Claude Fable 5.1 as built-in Amazon Bedrock models.
## Solution
- Use `bedrock-runtime` Converse for both models. Astra's Mantle
endpoint offers Responses and Chat Completions; Converse lets it reuse
Zed's Bedrock client. Fable 5.1 uses the same endpoint and API as Fable
5.
- Add the documented model IDs, geo/global profiles, token limits, and
capabilities. Astra has a 1,050,000-token context window; Fable 5.1 has
1,000,000. Both allow 128,000 output tokens.
- Handle Astra's reasoning fields, encrypted replay, and tool-result
images. Apply Fable 5.1's adaptive thinking, binding controls, and
tool-choice restrictions.
- Limit inference routing to each model's supported source Regions, keep
model-specific reasoning out of other Bedrock models' histories, group
parallel tool results before their images, and report Fable and Astra
refusals.
## Testing
- `cargo test -p bedrock -p language_models --lib`: 33 Bedrock and 116
language-model tests passed. The provider suite was rerun after the
final refusal-handling change.
- `./script/clippy -p bedrock -p language_models`, `cargo fmt -p bedrock
-p language_models -- --check`, and `cd docs && npx --yes prettier@3.5.0
--check src/`: passed.
- Live `bedrock-runtime` Converse/ConverseStream in `us-east-1`: Astra
and Fable 5.1 responded successfully. Astra's streamed encrypted
reasoning replayed on a second turn. Astra accepted forced tool use;
Fable 5.1 rejected it as expected.
- A live Astra request with two parallel tool results followed by two
sibling images succeeded. `aws bedrock list-inference-profiles`
confirmed the commercial US and EU profiles tested.
- GovCloud profile routing was not tested: no GovCloud credentials were
available. Zed's GUI was not run.
## References
- [GPT-6 Astra Bedrock model
card](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-6-astra.html)
- [Claude Fable 5.1 Bedrock model
card](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-anthropic-claude-fable-5-1.html)
Release Notes:
- Added GPT-6 Astra and Claude Fable 5.1 to the Amazon Bedrock provider.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Replace canonical v1 tool locations with a Zed-owned `ToolCallLocation`
as the next bounded ACP v2 data-model cleanup after #65350.
- Retain raw `PathBuf`, line, and item metadata, including relative
native paths and absolute protocol paths.
- Move v1/v2 location fields directly into the canonical model instead
of converting v2 locations into v1 wrappers.
- Compare raw `OsStr` spelling so component-equivalent path changes
replace retained source and invalidate old resolved projections.
- Keep resolved editor locations as projections and migrate the existing
image-output UI consumer.
- Add focused conversion, raw-equality, and patch/projection
regressions, including Unix non-UTF-8 paths.
Release Notes:
- N/A
## Summary
Removes the min width of the remote project picker to responsibly scale
with the size it actually needs and not have awkward extra padding at
the bottom.
## Testing
Manual, see screenshots
| Before | After |
| -- | -- |
| <img width="896" height="792" alt="Bildschirmfoto 2026-10-09 um 12 49
41"
src="https://github.com/user-attachments/assets/be77577d-bfba-4209-9329-e7579e507af6"
/> | <img width="896" height="792" alt="Bildschirmfoto 2026-10-09 um 12
48 55"
src="https://github.com/user-attachments/assets/b880c50b-598d-485c-a30f-a97ff4ee609b"
/> |
## Self-review
- [X] I've reviewed my diff for quality, security, reliability, and
performance.
- [ ] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [ ] Tests cover the new or changed behavior.
Release Notes:
- Fixed the remote projects picker sometimes reserving more space than
needed.
Standardize shared, application, and native session/tool-call identity
on ACP v2 ID wrappers as the next bounded ACP v2 migration slice.
- Use v2 `SessionId` and `ToolCallId` across connection APIs, canonical
thread/tool/permission state, native session storage, UI navigation, and
sidebar consumers.
- Keep legacy wire and native tool payloads as v1, converting IDs at
those boundaries by moving or cloning the existing `Arc<str>` rather
than stringifying or normalizing them.
- Preserve existing serialized ID strings, database schemas, drafts
without session IDs, subagent metadata, and mention records.
Release Notes:
- N/A
## Summary
Closes#64454
Going back (`ctrl-o` in Vim mode, the mouse back button, or the back
button in the tab bar) after switching away from a markdown preview
skipped the preview and landed on the tab before it.
Panes record history entries when an item is deactivated, but only if
the item adds itself: `Item::set_nav_history` and `Item::deactivated`
default to doing nothing, and `MarkdownPreviewView` didn't implement
either. The preview now stores its `ItemNavHistory` and pushes an entry
when deactivated, the same way other items do.
The entry carries no navigation data, so going back reactivates the
preview without restoring its scroll position. If the preview has been
closed, its entry is skipped, since it has no project path to reopen.
In Vim mode, `ctrl-o`/`ctrl-i` were only bound for editors, so pressing
them while the preview was focused opened the file dialog instead of
navigating. They're now also bound in the `MarkdownPreview` context.
## Testing
- Added `go_back_returns_to_preview_after_opening_another_file`. It
opens a markdown file and its preview, opens another file, goes back,
and asserts that the preview is active again. It fails without the fix.
- Manually tested on Linux (KDE Wayland): open a markdown file, open its
preview, open another file with the file finder, then go back with
`ctrl-o` and with the tab bar's back button. Both return to the preview,
and going forward returns to the other file.
- In Vim mode, `ctrl-o` and `ctrl-i` from the focused preview now go
back and forward instead of opening the file dialog.
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] Tests cover the new or changed behavior.
Release Notes:
- Fixed navigating back to a markdown preview tab after switching to
another file, and `ctrl-o`/`ctrl-i` in Vim mode opening the file dialog
when the preview is focused.
## Summary
Closes#65147
Fixes partially unclickable rows of wrapped links in Markdown tables,
affecting Markdown previews and rendered agent responses. A detailed
video of the bug, provided by issue author
[@machadinhos](https://github.com/machadinhos), can be found
[here](https://github-production-user-asset-6210df.s3.amazonaws.com/101654160/665208322-97183453-77c1-4364-94cf-d6f7eae85810.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20261008%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261008T220525Z&X-Amz-Expires=300&X-Amz-Signature=c92d295ab82d512815bd9d4dc011293c3c8a2b34134781823d835d757a633f11&X-Amz-SignedHeaders=host&response-content-type=video%2Fmp4).
Currently vertically centered table cells can cause hit testing to
mistake a position inside a later cell for a gap between text blocks.
Defer the first gap fallback until all text blocks have been checked,
allowing actual text hits to take precedence.
## Testing
Implemented `#[gpui::test]'s` for different table layouts and link
lengths
- 6f8a223669d9b8eb6c8c810c3467dbe8dea72230
- 87e2e59176f3258eb8c200749823ee68af87167e
- b6456a474c5daa871ad57c08894140f157296490
- 15b581003241be0b2868a663ad56a274569cc7a3
The fix passes all 188/188 tests for the markdown crate, the previous
implementation fails all newly added test cases.
```text
test tests::test_wrapped_table_links_hit_testing ... ok
test tests::test_wrapped_table_link_mouse_release ... ok
test tests::test_wrapped_table_link_unicode_and_surrounding_text ... ok
test tests::test_wrapped_table_link_column_positions_and_alignment ... ok
test tests::test_wrapped_table_link_hover_click_and_resize ... ok
test tests::test_copy_button_copies_commonmark_code_block_content ... ok
test tests::test_wrapped_table_link_interactions_in_all_columns ... ok
test result: ok. 188 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.89s
```
Build passed on **macOS** and **Windows**
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [ ] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.
Release Notes:
- Fixed wrapped links in Markdown tables being partially unclickable in
Markdown previews and agent responses
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
## Summary
I'm building a single-threaded web app on `gpui_web`, served as static
files, and I can't build it on stable Rust. `gpui_web`'s default feature
`multithreaded` pulls in `wasm_thread`, which needs the unstable
`stdarch_wasm_atomic_wait` feature gate. With `default-features = false`
the crate checks clean on stable, but `gpui_platform` depends on
`gpui_web` with defaults, so using the platform helper on wasm,
including its `single_threaded_web()`, brings the feature and nightly
back. Threads in a browser also need COOP/COEP headers and `build-std`,
so for a static site the single-threaded platform is the normal case.
This declares `gpui_web` without default features in the workspace and
has `gpui_platform` forward `multithreaded`, on by default. Nothing
changes unless a consumer opts out with `default-features = false`.
`hello_web` keeps its threads since it takes the helper's defaults.
## Testing
In this workspace, on stable: `cargo check -p gpui_platform --target
wasm32-unknown-unknown --no-default-features`. On nightly, the same with
defaults, which is the status quo path. `cargo check -p gpui_platform`
on the host, since `gpui_web` is only a wasm dependency and the feature
reference must still be accepted there. And `cargo tree -p gpui_platform
-e features --target wasm32-unknown-unknown` with and without
`--no-default-features`, showing `wasm_thread` present and then absent.
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [ ] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist). (No UI
change.)
- [ ] Tests cover the new or changed behavior. (A manifest change, the
tree and check commands above are the test.)
I used an AI assistant, which helped me trace where the feature gets
switched on. I've reviewed the changes and verified the checks above
pass on my machine.
Release Notes:
- N/A
- [GPUI] The multithreaded feature for `gpui_web` can now be forwarded
Co-authored-by: Lukas Wirth <lukas@zed.dev>
## Summary
`uniform_list` computed the visible range and each item's origin from
the scroll offset in `f32`. Past 2^27px, adjacent `f32` values are 16px
apart. In a list of 24px items, that point is about 5.6 million items
in. From there:
- items are placed with alternating 16px and 32px gaps instead of 24px;
- the visible range can start one item late, leaving a blank strip at
the top of the list (and sometimes at the bottom);
- smaller errors start earlier, such as a 1px offset at about a million
items, because the large offset is added to the viewport origin in
`f32`.
This change computes the visible item indices and the viewport-relative
item offsets in `f64`, then converts only the small offsets back to
`Pixels`. The arithmetic stays local to `uniform_list`'s prepaint, and
nothing changes for ordinary list sizes.
The stored scroll offset (`ScrollHandle`) is still `f32`, so very far
down a long list the scroll position itself stays quantized.
`scroll_to_item` can land up to half a step (8px at this depth) away
from the item's exact top, and very small scroll deltas can be lost.
Fixing that would mean changing the scroll offset representation used by
every scrollable element, so I left it out of this PR.
I hit this in a GPUI file search app showing ~9.8 million results in a
table built on `uniform_list`:
<img width="1336" height="874" alt="image"
src="https://github.com/user-attachments/assets/c25b2c1d-3151-4a87-9742-c3820c1d4aac"
/>
## Testing
- Added `test_item_positions_far_down_long_list`: 10M items of 24px in a
200px list, with the scroll offset set 16px into item 9,000,002. It
asserts which items render and their tops (`-16, 8, 32, … 176`).
- On `main` it fails: item 9,000,002 is missing and the tops are `0, 32,
64, 80, 96, 128, …`.
- With this change it passes.
- `cargo test -p gpui --lib uniform_list` passes, including the existing
`test_scroll_strategy_nearest`. `cargo clippy -p gpui --lib --tests` is
clean.
- Manually on Windows, in a real window with 9,824,090 rows of 24px, I
checked 12 scroll positions, including odd rows reached from far away.
Each check verifies consecutive rows, uniform 24px spacing, and that
rows cover the viewport top and bottom.
- Before: 7 of 12 failed.
- After: 12 of 12 passed.
To reproduce: run the new test against `main`, or render a
`uniform_list` with ~10M fixed-height items and scroll near the end.
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist). (No visible
UI changes in Zed.)
- [x] Tests cover the new or changed behavior.
I used Claude to help investigate this and write the change. I've
reviewed it and understand it.
Release Notes:
- [GPUI] Fixed layout glitches for uniform_lists with a lot of
virtualized content.
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Pull request [#61335] fixed this issue for the project search, but the
text finder (the "telescope" search) still had the same issue. This
commit copies that behavior by reusing that logic.
#### Summary
When you have the regex mode turned on in the text finder, the selected
query isn't escaped.
This recording shows how it's escaped in the project search, but not in
the telescope search:
https://github.com/user-attachments/assets/02554192-5939-4cef-9d2e-201de332568f
After the fix:
https://github.com/user-attachments/assets/4bc9501a-493d-4b28-9793-166c3a7e230c
#### Testing
To see the issue:
- Open the text finder
- Turn on the regex mode
- Select something with any "special" regex character e.g.`(`
- Call the text finder
=> The query isn't escaped
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.
Release Notes:
- Fixed text finder search queries seeded from the current selection
being interpreted as a regular expression instead of literal text when
regex mode was enabled.
[#61335]: https://github.com/zed-industries/zed/pull/61335
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
Frame and hang telemetry judged every frame against a fixed 24 ms
budget. That's too lax on 120–360 Hz displays and too strict at 30 Hz,
so the numbers couldn't be compared across users or catch regressions on
fast displays. This judges each frame against its window's display
refresh interval (from #65059), as measurement version 3.
**Frame timing.** A frame's work runs from the later of its frame signal
and its first invalidation until its submission to the platform begins,
on every platform, so time spent waiting for a late frame signal or
inside the submission doesn't count. A frame is late when its work
exceeds one refresh interval, but never less than 8.33 ms (one refresh
at 120 Hz), since frames rarely fit a single refresh on faster displays
yet; on displays whose refresh interval is unknown (X11, web) the budget
is 16.7 ms. Missed refreshes still count against the real interval.
**Frame Duration Report**, per window and refresh interval: on-time,
late, and unmeasured frame counts and missed refreshes, overall and for
frames that responded to input; work (as a percentage of the refresh
interval) and draw-time buckets, computed from hdrhistogram histograms;
GPU and CPU.
**Hang Incidents.** Threshold incidents (one event of 100 ms or more)
are unchanged. Budget incidents are split by trigger:
- `late_frame`: a presented frame over its budget, listing the events
that overlap that frame's work;
- `blocking_work`: in an interval with no measured frame, a single event
of at least the frame budget (16.7 ms in release builds), long enough to
delay a frame. Total foreground time across an interval no longer
counts, since gaps between short work don't block frames.
Draw contributors carry request-layout, prepaint, and paint times, and
any entity view phase whose own work (excluding nested views) takes 0.5
ms or more becomes a contributor named by its view type. Events also
report counts per trigger, incidents during active use (within a minute
of a key press, click, or scroll) with active seconds for rates per
active hour, stall buckets, and contributor totals summed across every
incident (`view:<type>:<phase>`, `action:…`, `task:…`).
**Verification.** With a synthetic render delay on a 240 Hz display,
on-time frames went from 99.9% at no delay to 0% at 6 ms. In a real Zed
on Linux at 360 Hz, scrolling a markdown preview with #63138's per-frame
code-block highlighting reintroduced roughly doubled missed refreshes
per frame (3.2 to 6.0) and attributed the extra time to
`MarkdownPreviewView`'s request-layout phase. Profiler overhead was
+2.3% of main-thread time in a 1,500-view GPUI stress test and about
0.3% in the Zed scroll run. Not yet verified: Windows, and input-driven
frames from real use. Time spent inside the platform submission (GPU,
compositor) isn't measured on any platform.
Release Notes:
- [GPUI] Improved frame and hang telemetry to measure frames against
each window's display refresh rate
This moves three pieces of macOS platform code into `gpui_apple` so the
upcoming iOS backend (#63068) can share them: the CoreText text system,
the Keychain credential helpers, and thermal-state reporting. macOS
behaves the same as before. Credential reads still return `None` when
nothing is stored or the prompt is canceled, deleting a missing
credential is still an error, and text rendering keeps font smoothing
and dilation. Along the way the Keychain and OpenType code switch from
hand-written FFI to the generated objc2 bindings, which also fixes an
over-release of temporary CoreText feature strings, and thermal
notifications now reach the main thread through a channel instead of a
raw-pointer `dispatch_async_f`. It also replaces the old `core-video`
crate with `objc2-core-video`, because `core-video` pulls in
`io-surface` and `cgl`, which link OpenGL and break iOS builds. That
changes GPUI's public surface API: `SurfaceSource`, `PaintSurface`, and
`Window::paint_surface` now take
`CFRetained<objc2_core_video::CVPixelBuffer>`, and LiveKit's video
frames follow suit. I tested this with the gpui, gpui_apple, and
gpui_macos test suites, including a new Metal test that renders a real
NV12 pixel buffer, plus checks of the `zed` and `remote_server` builds;
the iOS link was verified on the iOS branch. LiveKit playback and the
Keychain paths are only compile-checked, so a quick sign-in/sign-out on
macOS before relying on this is worth doing.
Release Notes:
- [GPUI] Added shared Apple CoreText text rendering, Keychain, and
thermal-state services in `gpui_apple`, and migrated `SurfaceSource`,
`PaintSurface`, and `Window::paint_surface` from `core-video`'s
`CVPixelBuffer` to `CFRetained<objc2_core_video::CVPixelBuffer>`
Upgrade ACP SDK and derive to the published **3.2.0** release and use
its prepared requests/cancellation handles to register new sessions
before processing their first updates.
Previously, `session/new` used an ordinary response future. A peer could
reply and immediately send an update before foreground session
registration, causing the update to be discarded as belonging to an
unknown session. The prepared ordered callback now delivers the result
to the creation task and waits for synchronous foreground registration
to be acknowledged before later inbound dispatch proceeds.
Caller abandonment explicitly requests RPC cancellation through the
SDK-owned handle without discarding eventual response handling. If an
abandoned caller receives a late successful session, Zed requests close
when the peer advertises support. Peer rejection, EOF, and abandonment
release the registration barrier; a failed creation does not terminate
an otherwise usable connection. Default mode/config work remains
asynchronous and is not awaited inside the barrier.
The callback does not retain `Rc<AcpConnection>` or await later traffic
on the same connection. Cancellation is request-scoped and cooperative,
not cancellation of already-completed RPCs or ongoing session work.
Client writes no longer hide already-captured agent stderr when startup
fails. A deterministic interleaving regression covers this
diagnostic-selection race without weakening the physical-process startup
assertion or adding retries. Caller-drop cancellation uses the existing
`util::defer` helper rather than a bespoke guard type.
Release Notes:
- Fixed initial ACP session updates being dropped and agent startup
diagnostics being lost.
When a language server omits the `range` field in its hover response and
syntax tree fallback fails, Zed falls back to a zero-width hover range
(`anchor..anchor`). Previously, because the check used an exact offset
match, any slight cursor movement within the same symbol would treat it
as a new hover target, immediately dismissing the existing popover and
triggering repeated requests. This caused flickering and made it
impossible to move the cursor into the popover to interact with it.
This PR fixes the issue by falling back to `surrounding_word` when
checking if an anchor is contained within a zero-width hover range,
allowing cursor movement within the same word without dismissing the
popover.
Release Notes:
- Fixed hover popovers flickering or prematurely dismissing on mouse
movement when using language servers that omit range information.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Closes#56525
# Objective
Zed's branch picker shows a "Delete Branch" trash icon for both local
and remote-tracking branches. For remote-tracking branches (e.g.
`origin/feature`), this action only deletes the local tracking ref (`git
branch -dr`) — it never contacts the remote, and the branch still exists
on the actual remote repository. The label gives no indication of this,
so users can't tell whether the action is local-only or will delete the
branch upstream.
## Solution
`Branch.is_remote()` was already used internally to pick the right git
flag (`-d`/`-dr`) when deleting, but this distinction was never surfaced
in the UI copy. This PR threads that same `is_remote` value through to
the delete tooltip and branches the displayed text on it:
- Local branch: unchanged — "Delete Branch" / "Force Delete Branch",
with the existing "Hold alt to force delete" hint.
- Remote-tracking branch: "Delete Local Tracking Branch" / "Force Delete
Local Tracking Branch", with a "Does not delete the branch on the
remote" hint.
Also updated the stale `DeleteBranch`/`ForceDeleteBranch` action
doc-comments, which still said "Deletes the selected git branch or
remote" — a leftover from an earlier (already-fixed, see #48338)
implementation that really did delete the whole remote config.
No behavior change to the underlying delete logic — this is a copy-only
fix that makes existing, correct behavior legible to the user, per
[maintainer guidance on the
issue](https://github.com/zed-industries/zed/issues/56525#issuecomment-5095069397).
## Testing
- `cargo check -p git_ui` passes.
- Manually verified in the branch picker: hovering the trash icon on a
local branch shows the original text; hovering it on a `origin/...`
remote-tracking branch shows the new "local tracking branch" text and
meta line, for both the plain and alt-held (force) states.
- No behavior/logic change, so no new automated test was added — purely
a UI string change in `DeleteBranchTooltip::render`.
- Reviewers: open a repo with at least one remote-tracking branch
visible in the branch picker (`git fetch` a repo with a branch you don't
have locally), hover the delete icon on it vs. on a local branch, and
compare tooltip text.
## 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: hovering the trash icon on `origin/feature` shows "Delete
Branch" / "Hold alt to force delete" — identical to a local branch, no
indication the remote is untouched.
After: hovering it shows "Delete Local Tracking Branch" with meta text
"Does not delete the branch on the remote".
---
Release Notes:
- Improved the branch picker to clarify that deleting a remote-tracking
branch only removes the local ref, and removed the force delete option
for remote-tracking branches since it had no effect.
---------
Co-authored-by: Agus Zubiaga <agus@zed.dev>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
## Summary
> PR #62597 changed the Threads Sidebar background color, but introduced
a regression where the background becomes transparent in some themes,
such as VSCode Dark Modern, which assigns a semi-transparent color to
`surface_background`.
>
> This PR blends the Threads Sidebar background color with `background`
to prevent it from becoming transparent.
>
> Additionally, while the default themes are unaffected, the Threads
Sidebar background was found to be inconsistent with other panels in
themes such as VSCode Dark Modern. To address this, this PR also changes
the blended color from `surface_background` to `panel_background`,
preserving the appearance of Zed's bundled themes while improving
consistency in other themes.
#62597でThreads
Sidebarの背景色が変更されましたが、`surface_background`に半透明の色が割り当てられているVSCode Dark
Modernなど一部のテーマでサイドバーの背景色が透明になってしまうリグレッションが発生しました。
このPRでは、Threads Sidebarの背景色を`background`とブレンドし、背景色が透明になることを防ぎます。
また、デフォルトのテーマでは問題ありませんが、VSCode Dark ModernなどではThreads
Sidebarの背景色がほかのパネルと一致せず一貫性がなくなることが判明したため、ブレンドする色を`surface_background`から`panel_background`に変更しました。これにより、Zedに同梱されているテーマでの外観を維持しつつ、一部のテーマで背景色に一貫性を持たせます。
Before:
<img width="867" height="457" alt="image"
src="https://github.com/user-attachments/assets/c98e5063-abee-4110-bf6c-2b7ae91d2fbc"
/>
After:
<img width="846" height="388" alt="image"
src="https://github.com/user-attachments/assets/72e253c4-a713-4245-9c18-ce57572bbb6c"
/>
Closes#65310
## Testing
> Install a theme that assigns a semi-transparent or transparent color
to `surface_background`, such as VSCode Dark Modern.
>
> Before this change, the Threads Sidebar background appears transparent
(or white on Windows). After this change, the background remains opaque.
VSCode Dark
Modernテーマなど、`surface_background`に半透明または透明の色が割り当てられているテーマをインストールします。変更前はThreads
Sidebarの背景色が透明(Windowsでは白色)になってしまいますが、変更後は不透明の背景色になります。
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.
Release Notes:
- Fixed an issue where the background color of the Threads Sidebar was
transparent in some themes
GPUI now tracks connected displays and the display each window is on.
`App` caches every display's bounds and refresh interval, rereading them
whenever a platform reports that displays may have changed, and reports
`Added`, `Removed`, and `Changed { id, changes }` through
`App::observe_displays`. Windows report only moves between displays;
`Window::refresh_interval(cx)` reads App's cache, and
`Window`/`Context::observe_window_display` fire when a window moves or
its display changes, with App updated first. This is implemented on
macOS, Windows (whose platform window is now a hidden top-level window
so it receives `WM_DISPLAYCHANGE` and `WM_ENDSESSION` with no windows
open), and Wayland, and was exercised at runtime on all three by
switching refresh rates; X11 and web report no refresh interval, and
headless Linux now reports no displays. Planned consumers are
refresh-rate-aware frame telemetry and the screen-share display picker.
Release Notes:
- [GPUI] Added `App::observe_displays`, `Window::refresh_interval`, and
`observe_window_display` for tracking connected displays, their refresh
rates, and each window's display
Replace the bounded `futures::mpsc` response-body channel with
`async-channel`, using the workspace's default-features-disabled
configuration. The browser Fetch pump runs on the main thread while
response bodies can be consumed by workers. `futures::mpsc` locks an
internal sender mutex during `poll_flush`; contention can attempt an
unsupported `Atomics.wait` on the browser main thread.
Release Notes:
- [GPUI] Fixed a browser crash when streaming Fetch response bodies to
background workers.
Pin `khronos-egl` to the Zed fork's defensive error-handling fix for
[FR-522](https://linear.app/zed-industries/issue/FR-522/zed-c82-called-optionunwrap-on-a-none-value).
An EGL call can fail while `eglGetError()` reports `EGL_SUCCESS`. The
binding currently unwraps the missing error, which caused the reported
panic during Wayland surface creation. The fork returns a distinct
`Error::Unreported` instead, preserves real EGL errors, and applies the
same rule consistently to failed-call wrappers.
- Fork commit:
[42214b3](42214b3634).
- Upstream PR:
[timothee-haudebourg/khronos-egl#37](https://github.com/timothee-haudebourg/khronos-egl/pull/37).
- This PR changes only `Cargo.toml` and `Cargo.lock`. Remove the
temporary fork patch once an upstream release includes the fix.
The new public error variant is source-breaking for exhaustive matches,
so the upstream PR explicitly leaves release/versioning to the
maintainer. This integration uses a controlled Git pin and has been
checked against the GLES downstream consumer.
Release Notes:
- [GPUI] Fixed a panic when EGL calls fail without reporting an error.
## Summary
Closes#64273
Running a case conversion (or any other `manipulate_text` command) with
several cursors inside the same word inserted the converted word once
per cursor:
| Before | Upper case result |
|---|---|
| `some_ˇvariˇable_naˇme` |
`SOME_VARIABLE_NAMESOME_VARIABLE_NAMESOME_VARIABLE_NAME` |
### Cause
`manipulate_text` expands each empty selection to its surrounding word,
so several cursors in one word produce identical ranges, and a cursor's
word can also overlap other selections. The buffer coalesces overlapping
edits by concatenating their texts, so the converted text was inserted
once per selection.
### Fix
After expanding, the ranges are sorted by start and overlapping ones are
merged, then each merged range is transformed once. Sorting matters
because expanding a cursor can move its range's start before earlier
selections (e.g. `«a»b«cd»e|f`, where the cursor's word starts at `a`).
Selections that only touch are kept separate, so non-overlapping
selections behave exactly as before.
This applies to every command that goes through `manipulate_text`: all
case conversions, ROT13/ROT47, and Base64 encode/decode.
## Testing
Added `test_multicursor_manipulate_text`, which reports every failing
case at once. It covers:
- multiple cursors in one word, and in two different words
- a cursor's word partially overlapping a selection
- a cursor's word starting before earlier selections
- a conversion that changes nothing, which keeps the cursors unchanged
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] Tests cover the new or changed behavior.
Release Notes:
- Fixed case conversion and other text transformation commands
duplicating the word when multiple cursors are inside it.
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
## Summary
What problem does this solve, how, and why does this change matter?
Use "Closes #123" for each issue resolved.
Include artifacts produced when testing: before/after screenshots, GIFs,
videos, benchmarks.
## Testing
Manually test your changes; report results, mention platforms if
relevant.
How can reviewers test this easily? Include setup and steps.
## Self-review
- [ ] I've reviewed my diff for quality, security, reliability, and
performance.
- [ ] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [ ] Tests cover the new or changed behavior.
Release Notes:
- Added telemetry for usage of checkpointing feature in the agent panel.
This telemetry is opt-in and has no effect with telemetry disabled.
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
The temporary pin is the immutable commit
[`015845a19fc31752c02367567d3b8900a406f9da`](015845a19f),
under upstream review in
[smol-rs/async-task#108](https://github.com/smol-rs/async-task/pull/108).
- Upgrade `agent-client-protocol` and its derive crate from 2.2.0 to
3.1.0, consuming the SDK's exact schema 1.10.2 dependency.
- Explicitly enable `schemars`: SDK3 makes JSON Schema support optional,
while the existing native `spawn_agent` tool derives `JsonSchema` for an
input containing `acp::SessionId`.
- Pin the canonical task-waker fix. SDK3's direct transport polling
exposed inconsistent original/clone waker vtable identity in the
previous `async-task` revision, causing repeated readiness wakeups and
starving the inherited-stdout drain timeout. The upstream fix resolves
this without a Zed-specific wrapper or weakened assertions.
Release Notes:
- N/A
Cancel outstanding ACP elicitations when the transport reaches EOF or
fails, including idle session threads and connection-scoped request
stores retained by the application.
Previously, detached elicitation waiters observed peer
`$/cancel_request`, but bare EOF did not settle their canonical entries.
Process-exit handling and turn/auth cleanup covered some workflows, not
retained idle owners.
- Register SDK `on_close` cleanup through the existing foreground queue
and await its acknowledgment. Accepted requests register before cleanup;
no process exit or active turn is required.
- Share the cleanup operation with the SDK-future failure path, because
transport errors can bypass the clean-EOF callback. Run it once, surface
cleanup failures, and preserve the original connection error if both
fail.
- Reuse existing thread/store cancellation. Session references stay weak
until synchronous application; there is no new store or connection-owner
cycle.
- Apply URL completion synchronously in foreground queue order, so final
accepted completion cannot be overtaken by disconnect cancellation.
Release Notes:
- N/A
# Objective
Fixes a regression of #51062 introduced by #56427.
Images inside center- or right-aligned HTML blocks render left-aligned
in Markdown Preview.
This is a regression: #53196 originally fixed the alignment, but the
image-rendering changes
in #56427 moved images into a wrapping flex container without carrying
over the alignment
mapping.
Text alignment still works, which makes the problem easy to miss. A
centered heading is
centered, while a centered logo or badge row is left-aligned.
## Solution
`push_image_child` turns the current container into a flex row so
multiple images can wrap.
Once the container becomes a flex row, `text_align` no longer positions
its children;
`justify_content` does.
This restores the mapping from `TextAlign::Left`, `Center`, and `Right`
to the corresponding
flex justification while preserving the `flex_wrap` and `items_start`
behavior added by
#56427.
Both `align="..."` and `style="text-align: ..."` already resolve to
`TextAlign`, so the fix
applies to both forms, including images nested inside links or headings.
## Testing
- `cargo test -p markdown --lib`
- Added `test_image_child_container_follows_text_align`, which checks
the rendered
container's justification for left, center, and right alignment.
- The existing tests from #53196 cover parsed alignment, but not the
resulting flex
container. They continued to pass when the rendering behavior regressed.
- Manually checked on macOS with a centered image, a centered row of
linked images, and a
right-aligned image.
<details>
<summary>Used this markdown to test:</summary>
```markdown
# HTML image alignment
## Centered image
<p align="center">
<img width="120" src="https://raw.githubusercontent.com/zed-industries/zed/main/crates/zed/resources/app-icon.png">
</p>
## Centered linked images
<p align="center">
<a href="https://zed.dev"><img width="96" src="https://raw.githubusercontent.com/zed-industries/zed/main/crates/zed/resources/app-icon.png" alt="Zed"></a>
<a href="https://github.com/zed-industries/zed"><img width="96" src="https://raw.githubusercontent.com/zed-industries/zed/main/crates/zed/resources/app-icon.png" alt="Zed repository"></a>
</p>
## Right-aligned image
<p align="right">
<img width="120" src="https://raw.githubusercontent.com/zed-industries/zed/main/crates/zed/resources/app-icon.png">
</p>
```
</details>
## 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
<details>
<summary>Screenshots: </summary>
| Before | After |
| --- | --- |
| <img width="469" height="786" alt="Snapzy_2026-08-25_01-04-21_153"
src="https://github.com/user-attachments/assets/b82f4dfe-df77-4ff5-8d14-a92964a2e834"
/> | <img width="469" height="786" alt="Snapzy_2026-08-25_00-59-00_221"
src="https://github.com/user-attachments/assets/edf472f1-1df9-4e5a-ba75-33d418227873"
/> |
These screenshots were captured from the standalone `markdown` crate
example (I did not build the full Zed app for this comparison).
</details>
---
Release Notes:
- Fixed image alignment in HTML blocks in Markdown Preview
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Partially addresses
[#62283](https://github.com/zed-industries/zed/issues/62283) and
[#58444](https://github.com/zed-industries/zed/issues/58444).
Before Zed sends a prompt, it waits for a Git checkpoint of every
repository in the project, even in threads that can never restore one.
In large workspaces, this can delay sends and max out the CPU. On
Windows it can be worse. The [investigation in
#62283](https://github.com/zed-industries/zed/issues/62283#issuecomment-5345773750)
found `git update-index` waiting forever for stdin EOF, so the prompt
never reaches the agent.
This skips checkpoints in threads that can't show the Restore Checkpoint
button:
- **External agents.** Zed's ACP connection doesn't support truncation,
so these threads never get the button. Only the initial checkpoint
needed skipping, because the later updates already return early for
messages with no client-generated IDs, which `AcpConnection` [never
provides](da0a7a78cf/crates/acp_thread/src/connection.rs (L188-L193)).
- **Subagents.** These now skip the initial, during-turn, and final
checkpoints. A subagent can't restore on its own, and the parent's
checkpoints already cover its edits.
`AcpThread::can_rewind_to` now holds the check that the Restore
Checkpoint button and message editing already used, and checkpoint
creation uses it too. It checks capabilities rather than the connection
type, so if `AcpConnection` later supports truncation and client message
IDs, external agents get checkpoints and the button back automatically.
Top-level Zed agent threads behave as before. Message editing still uses
`rewind`, which never touches Git checkpoints.
The new test checks that ineligible threads queue no checkpoint jobs at
any point in a turn. A top-level thread that supports truncation still
queues them.
This avoids the Windows hang for these threads, but it doesn't fix the
underlying subprocess bug, and Zed agent threads can still hit it.
Reducing or disabling the remaining checkpoints is separate work in
[#64000](https://github.com/zed-industries/zed/pull/64000) and
[#62301](https://github.com/zed-industries/zed/pull/62301).
Release Notes:
- Fixed prompts to external agents being slow to send, or never sending,
because of unneeded Git checkpoints.
When a debug session is running, pressing cmd-f (or using Edit → Find)
in the terminal panel had no effect. Three things were missing:
- The debugger panes never had a BufferSearchBar added to their toolbar,
so there was no search UI to deploy.
- SubView::as_searchable returned None for all item kinds, so even if a
search bar were present it could not find a search target.
- RunningState::render did not wrap its output with the pane search
action handlers, so buffer_search::Deploy was never handled.
Fix all three:
- Register BufferSearchBar on each debugger pane toolbar via the
PaneSearchBarCallbacks global (same pattern as terminal_panel).
- Implement SubView::as_searchable for Terminal kind, delegating to the
inner TerminalView which already implements SearchableItem.
- Wrap RunningState::render with wrap_div_with_search_actions so the
Deploy action reaches the active pane's toolbar.
- Add refresh_terminal_toolbars to re-fire toolbar.set_active_item when
the terminal entity is set, covering the case where the Terminal tab was
already active before the terminal was created. Only refreshes panes
where the Terminal subview is currently the active item.
Add a test that verifies the active debugger pane toolbar has a
BufferSearchBar after a session starts.
Self-Review Checklist:
- [ ] 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
Fixes#38409
Release Notes:
- Fixed `cmd-f` search not working in the debugger terminal panel.
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
When hovering a horizontally scrollable code block, the scrollbar track
was painted with square corners. Since GPUI content masks are
rectangular, the parent's rounded border didn't clip it, so a small
corner of the track showed outside the code block's rounded border.
This adds `Scrollbars::track_corner_radius` to round the track's outer
corners, and markdown code blocks now pass their inner corner radius
(corner radius minus border width).
Before:
<img width="400" alt="CleanShot 2026-09-30 at 3 57 50 PM@2x"
src="https://github.com/user-attachments/assets/a90372cf-c668-4469-8dea-058a795888be"
/>
After:
<img width="300" alt="CleanShot 2026-09-30 at 4 00 08 PM@2x"
src="https://github.com/user-attachments/assets/cf6c384e-3c93-4a79-9479-d390974c4b67"
/>
Release Notes:
- Fixed a visual artifact at the corners of scrollable code blocks when
hovered.
Starting Oct 7th, the free plan will no longer include Zed's hosted edit
predictions.
## Testing
- Added `test_free_plan_edit_predictions_ended_for_zed_provider`. It
covers:
- the Free vs Pro plan rule, with Cloud still reporting a 2,000
allowance
- the default vs explicitly chosen provider
- the Ollama exclusion
- the notice only firing when the user accepted predictions
- All `edit_prediction` tests pass.
- Clippy with `--deny warnings` passes on the touched crates.
- The docs pass prettier.
- Screenshots of an earlier revision were captured with the visual test
runner. The latest copy and the Copilot removal haven't been checked in
a running build.
Release Notes:
- N/A
## Summary
Connecting to my server I regularly use takes about 4 seconds. Previous
implementation used 3 sequential commands to detect the remote
environment, since windows does not support multiplexing, these queries
alone could take around 12 seconds.
This change batches those queries into a single script.
## Testing
Added some unit tests for the parsing logic, although they are still
fairly example-based. I tested the changes on my own machines as well.
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [ ] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.
Release Notes:
- Batch SSH environment queries
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
## Summary
Closes#65156.
Update the settings sidebar selection when scrolling through
subsections. Allow the final short subsections to scroll into position,
and update selection as the next header's surrounding region reaches the
top of the content viewport.
## Testing
- Built and ran Zed locally on Windows; manually verified by the
contributor.
- Passed 9 navbar tests and the settings content viewport regression
test.
- Passed `cargo fmt --package settings_ui -- --check` and `git diff
--check`.
To reproduce: open Settings, expand Window & Layout, and scroll the
content down and back up. Check that the sidebar follows the visible
subsection, including Pane Modifiers and Pane Split Direction at the
end. Clicking a sidebar subsection should still scroll to it.
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.
### Settings sidebar follows scrolling
https://github.com/user-attachments/assets/eaf298c5-ef50-4741-a90a-066120ae313a
Release Notes:
- Fixed settings sidebar selection to follow scrolling through settings
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
## First commit
Preload initial project panel icons before drawing
Preload the initial project panel icons through the asset cache.
Measurements (warm macOS launches):
- Time to complete Catppuccin Frappe icons: reductions of 4.0 ms and
16.2 ms in two runs of 10 pairs.
- Time to first nonblack captured frame: increases of 16.6 ms and 2.3
ms; all 16 icons were present in every candidate launch.
## Second commit
Reuse unchanged icon families during startup instead of loading them
twice.
Reuse icon families with unchanged source bytes and paths until
extensions finish loading.
Include file paths in theme-read errors.
Measurements (warm macOS launches):
- Time to first captured complete Catppuccin Frappe icons: paired median
reductions of 6.2 ms and 5.0 ms in two runs of 10 pairs.
- Capture gaps in the repeat run reached 216.7 ms.
Release Notes:
- Improved startup time when custom icons are used
Measurements (warm macOS launches):
- Time to captured active-file header, restoring 256 tabs with 17
selections each: reductions of 37.8 ms and 35.5 ms in two runs of 30
pairs.
- With one caret per tab: paired median reduction of 4.7 ms.
- Without tab restoration: no observed improvement.
Release Notes:
- Improved Zed's startup time when hundreds of selections are restored
Closes https://github.com/zed-industries/zed/issues/64962
Update CPAL and rodio to remove the uninterruptible ALSA write retry
loop.
Discard failed output streams so subsequent notifications can reopen the
device.
Preserve recoverable underruns, cancel stale error handlers on teardown,
and keep existing output buffer defaults.
Release Notes:
- Fixed audio thread failing to properly stop on errors
Waiting for a direct child to exit does not establish that its Windows
Job Object is empty. Helper processes can remain active after the parent
exits, but the process wrapper did not expose the job's activity to
callers.
Add the Windows-only
[`Child::has_running_processes()`](5fbb50c106/crates/util/src/process.rs (L140))
query, backed by Job Object accounting:
- `Some(true)` means the assigned job still has active processes.
- `Some(false)` means the assigned job is empty.
- `None` means no job was assigned, so descendant tracking is
unavailable.
- Query failures are returned as errors.
Spawning and the direct-child kill fallback are unchanged. The
documentation now states the limits of best-effort cleanup, including
job setup failures and descendants started before job assignment.
Release Notes:
- N/A
## Summary
Closes#65091
In the project panel, a folded directory path like `a/b/c` is rendered
as separate components. Internal drags (`DraggedSelection`) could
already be dropped on any component or separator, but external files
dragged in from the OS could only be dropped on the deepest directory.
This is the case from the issue: files dragged onto `upper_folder` in a
folded `upper_folder/lower_folder` always ended up in `lower_folder`.
This adds `ExternalPaths` drag-move and drop handlers to each folded
path component and to the separators between them, so external files
land in the directory that was actually hovered. The hover highlight
follows the same path as for internal drags.
The duplicated drag-target bookkeeping in the `DraggedSelection`
handlers is moved into `update_folded_directory_drag_target`, so both
drag types share it.
Before:
<img width="1100" height="688" alt="before"
src="https://github.com/user-attachments/assets/94af5bb9-f727-4bd0-80ed-5713790b7f65"
/>
After:
<img width="1100" height="688" alt="after"
src="https://github.com/user-attachments/assets/dee1f581-ae7d-48b0-9d08-19e671fc63e5"
/>
## Testing
Added `test_drop_external_files_on_folded_directory_components`, which
drops an external file on each of `a`, `b` and `c` in a folded `a/b/c`
and checks that it lands in that directory and that the drag state is
cleared afterwards. The test fails without the new drop handlers (the
drop on `b` ends up in the wrong directory).
Manually tested on macOS 27. The issue was reported on Windows, which I
have not tested.
1. Enable `auto_fold_dirs` and open a project containing a nested chain
of single-child directories, e.g. `a/b/c`.
2. Drag a file from the OS file manager onto `a`, `b`, `c` and onto a
`/` separator.
3. The file is created in the hovered directory, and only that component
is highlighted while dragging.
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.
Release Notes:
- Fixed dropping external files onto a specific directory in a folded
path in the project panel
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
## Summary
Opening Remote Projects could leave SSH aliases missing even though they
were present in the local SSH config. When asynchronous discovery
finishes after the initial picker refresh, the watcher reloads the
delegate but does not reset the list's cached item count. Config edits
can likewise leave visible rows stale.
Refresh the picker through `refresh_default_picker` after each SSH
config update, using the window context. This synchronizes the visible
rows with the discovered hosts and reapplies the current search query.
## Testing
- Built and ran the patched application on macOS arm64; the author
manually reviewed and verified that the fix works.
- All 37 `recent_projects` library tests passed.
- Both new rendered-UI regression tests failed with the original watcher
and passed with the fix. They cover host addition/removal, empty config,
and preserving an active search filter.
- Formatting and whitespace checks passed.
Automated test command:
```sh
cargo +1.98.1 test --locked -p recent_projects -p gpui_platform --features gpui_platform/runtime_shaders --lib
```
The runtime shader feature was used because the local machine has
Command Line Tools without the full Xcode Metal toolchain. Relevant test
results:
```text
Original watcher: 0 passed; 2 failed
Patched recent_projects suite: 37 passed; 0 failed
```
To verify manually, open Remote Projects with `read_ssh_config` enabled
and check that configured aliases appear without typing. With the picker
open, add or remove a concrete `Host` alias in the SSH config and verify
the rows update. Repeat with a search query active.
## Self-review
- [x] The change has been reviewed and manually verified by the author.
- [x] Tests cover the changed behavior, including rendered rows and
active filtering.
- [x] The fix uses the existing picker refresh path and introduces no
new UI controls.
## Suggested .rules additions
For `recent_projects` modal rendering tests, create a `MultiWorkspace`
window containing the test `Workspace`. A bare `Workspace` window does
not render the modal layer, so rendered-row assertions cannot observe
the picker.
Release Notes:
- Fixed SSH config hosts sometimes remaining missing or stale in the
remote projects picker.
---------
Co-authored-by: Finn Evers <finn.evers@outlook.de>
## Summary
> When selecting a range with shift-click, intermediate folded
directories are now fully included by resetting their active index. This
ensures drag and drop operations move or copy the entire directory.
Shiftキーを押しながらクリックして範囲を選択する際、途中にある折りたたまれたディレクトリも、アクティブインデックスをリセットすることで完全に含まれるようになりました。これにより、ドラッグ&ドロップ操作によってディレクトリ全体が移動またはコピーされるようになります。
## Follow-up changes
- Shift-up/down now also select entire folded directories: every row you
move onto resets to its outermost directory, while the starting row
keeps the segment you clicked.
- Shift-up/down now include the starting entry in the selection;
previously only the rows moved onto were marked.
- Tests cover both shift-click and shift-arrow range selection.
Before
<img width="239" height="443" alt="Zed 1 21 0 Version- 1 21 0+stable"
src="https://github.com/user-attachments/assets/f5e76da7-31b3-4a4e-83c5-763eca253a17"
/>
After
<img width="239" height="443" alt="Zed 1 21 0 Version- 1 21 0+stable
fixed"
src="https://github.com/user-attachments/assets/04de8627-85f6-475f-876d-9f82afccfeea"
/>
## Testing
> Manually verified the reported scenario: with d and f active, clicking
a, Shift-clicking other, and dragging the selection to the project root
moves the entire c/d and e/f directory chains, leaving root empty.
Automated tests also passed on macOS (Apple Silicon): all 138
project_panel tests. Both new regression tests fail without the fix and
pass with it.
報告した操作を手動で確認済みです。d・f をアクティブにした状態から、a をクリックし、other を Shift-click
してプロジェクトルートへドラッグすると、c/d・e/f が親ごと移動し、元の root は空になります。
自動テストも macOS(Apple
Silicon)で全138件成功しました。追加した回帰テスト2本は、修正なしでは失敗し、修正ありでは成功します。
## Self-review
- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [x] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.
Release Notes:
- Fixed shift-click and shift-up/down selection in the project panel not
including entire folded directories, and shift-up/down not including the
starting entry.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Tree-sitter input callbacks receive byte offsets, which can fall inside
a UTF-8 character. Both language parser entry points previously sought
to that offset, sliced the rope chunk as `str`, and only then converted
it to bytes. This could panic while reparsing after an agent edit.
- Add `Chunks::peek_bytes` and use it in both parser callbacks,
preserving the exact requested offset without allocating or rounding to
a character boundary.
- Share the chunk slice-range computation with string and bitmap peeks,
preserving their existing UTF-8 requirements. Document that constructing
a `Chunks` cursor still requires an aligned initial offset.
- Use `Rope::bytes_in_range` for query text providers and add a
query-predicate regression for error nodes starting inside multibyte
characters.
- Add parser regressions for two-, three-, and four-byte characters and
nonzero syntax-layer origins; compare results with parsing contiguous
bytes.
- Exercise forward/reverse seeks across rope chunks, bounded ranges
starting or ending inside characters, and EOF/empty input.
Release Notes:
- Fixed a crash when syntax parsing requested bytes inside a multibyte
character.
Closes#64823
While the agent replied, every streamed chunk saved the whole thread:
serializing it to JSON, compressing it, and rewriting the SQLite row.
The streamed text isn't saved until its message completes, so nearly all
of these writes were identical.
Now the thread is not saved while a message is streaming, unless a
message has completed or a setting, the title, or the draft prompt
changed since the last save.
Measured on a 16.6 MB thread (0.76 MB compressed) while the agent
replied to one prompt for ~40s:
| | Before | After |
|---|---|---|
| Full-thread saves during the reply | 836 (~21/s) | 2 |
| Zed's memory (Activity Monitor) while streaming | 1.34 GB → ~2.2 GB |
stays flat |
| CPU while streaming | ~75% of a core | ~35% of a core |
Before:
Initial:
<img width="1424" height="200" alt="CleanShot 2026-10-06 at 8 36 34
PM@2x"
src="https://github.com/user-attachments/assets/b3065bca-a881-4ff5-9eda-92ced2659554"
/>
Streaming:
<img width="1430" height="212" alt="CleanShot 2026-10-06 at 8 37 20
PM@2x"
src="https://github.com/user-attachments/assets/589842b9-7893-4750-8911-4362e981de7c"
/>
After:
Initial:
<img width="1358" height="182" alt="CleanShot 2026-10-06 at 8 41 22
PM@2x"
src="https://github.com/user-attachments/assets/ea55e40e-4d8c-4218-bf52-6285d7285963"
/>
Streaming:
<img width="1352" height="194" alt="CleanShot 2026-10-06 at 8 38 20
PM@2x"
src="https://github.com/user-attachments/assets/616ccede-6303-4da6-96e2-29803aad28aa"
/>
Release Notes:
- Improved memory and CPU usage while the agent responds in long
threads.
Closes https://github.com/zed-industries/zed/issues/65099
Before:
https://github.com/user-attachments/assets/36673f06-75b2-4d36-a8d9-4aaaa6bc1768
After:
https://github.com/user-attachments/assets/86a4e129-e1de-465f-9e70-fcec9d421c03
Issues:
- The host checked files that were not yet open for matches, but treated
every already-open buffer as a candidate.
Earlier queries leave thousands of buffers open, so later queries sent
all of them to the client: 3,339 buffers for 51 real matches in one
case.
Open buffers are now checked against their in-memory text first, which
also stops ordinary non-SSH searches from reporting open buffers with no
matches.
- The host queued every candidate buffer's full contents without waiting
for the client, so data from cancelled queries piled up in front of the
new query's results.
A single worker shared by all searches now sends at most 64 buffers or
about 1 MiB before waiting for the client to acknowledge them, and skips
batches from cancelled searches.
- Cancelling a search could stop a buffer transfer after the buffer was
already marked as shared, so later searches waited forever for its
contents.
`BufferStore` now owns transfers, so dropping the caller no longer
cancels them.
Release Notes:
- Fixed hanging during remote project search
This has been the behavior since which-key was introduced.
When a key both completed a binding and started longer ones, the
which-key popup and the pending keystrokes indicator folded them all
into one `+N keybinds` row, so there was no way to see what pressing
that key alone would do. For example, with this keymap:
```json
[
{
"context": "Workspace",
"bindings": {
"space f": "file_finder::Toggle",
"space f g": "pane::DeploySearch",
"space f r": "projects::OpenRecent"
}
}
]
```
pressing `space` showed `f +3 keybinds`. It now shows `f file finder:
toggle` as its own row, and only the longer bindings are grouped (`f +2
keybinds`). A single longer binding is shown as a regular row.
Group counts also counted duplicate bindings for the same keys when they
weren't next to each other in the list (e.g. `+3` where the next level
only shows 2 rows). Duplicates are now removed before grouping, keeping
the binding key dispatch tries first.
Before:
<img width="200" alt="CleanShot 2026-09-29 at 10 16 01 PM@2x"
src="https://github.com/user-attachments/assets/fe46c218-da7c-431a-bb23-92b0799003ad"
/>
After:
<img width="200" alt="CleanShot 2026-09-29 at 10 15 49 PM@2x"
src="https://github.com/user-attachments/assets/2ce1280a-63bf-4dfc-b589-769dc84c307e"
/>
Release Notes:
- Fixed the which-key popup and pending keystrokes indicator hiding what
a key does when that key also starts longer keybindings.
# Objective
While selecting a font in appearance settings, every option in the
picker appeared in the selected UI Font with no visual difference. This
PR renders each option in its own font family, serving as a preview for
selecting.
## Solution
Each row in the font picker now wraps its label in a `div` with its own
font family, so the label inherits the typeface. One renderer serves all
`FontFamilyName` settings - so Buffer, UI, Agent Panel, and terminal
font pickers all get the new preview.
## Testing
`fmt`, `./script/clippy -p settings_ui,` and `cargo test -p settings_ui`
all pass. Manually verified on macOS in a debug build.
## 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
Before
<img width="3600" height="2338" alt="image"
src="https://github.com/user-attachments/assets/baed5f40-f997-4d68-87d8-ea86cb8889ca"
/>
After
<img width="3600" height="2338" alt="image"
src="https://github.com/user-attachments/assets/5dacb8af-160f-422c-be06-4b1ba5302e3e"
/>
---
Release Notes:
- Improved the font family pickers in the settings window to render each
option in its own font as a preview.