# Objective
Video overview of this PR, maybe it helps with the review:
https://youtu.be/-JhKcZttXp8Fixes: #63828
Building Zed from source and opening a project in a dev container fails
with `Remote server exited with status 1`.
Zed compiles `remote_server` and uploads it into the container. The
binary loads Zed's default settings from the Zed source directory, which
doesn't exist there, and panics in `settings::init`:
```
thread 'main' panicked at crates/util/src/util.rs:729:10:
dev asset loading requires running from within the checkout
```
The build passes `--features debug-embed` to embed those assets instead,
but `remote_server/debug-embed` only enabled its own (unused)
`rust-embed` dependency. It never reached `util/debug-embed`, which is
what `fs_embed!` gates on. Regression from #63396.
SSH and WSL remotes are affected the same way. Release builds are not:
assets are embedded whenever `debug_assertions` is off.
## Solution
Forward the feature.
```diff
-debug-embed = ["dep:rust-embed"]
+debug-embed = ["dep:rust-embed", "util/debug-embed"]
```
The same one-line change is already included as a secondary fix in
#63613, whose subject is unrelated; its author offered to split it out.
## Testing
- `cargo tree --package remote_server --features debug-embed` now
resolves `util` with `debug-embed`. Before:
`rand,test-support,util_macros`.
- `cargo check -p remote_server --features debug-embed --target
x86_64-unknown-linux-musl` passes clean.
- Manually: built Zed from source on Linux x86_64, opened a project in a
dev container (`mcr.microsoft.com/devcontainers/base:ubuntu`). Before:
panic at startup. After: connects.
Not tested on macOS or Windows hosts.
No test added: this is feature wiring, and #63577 notes that nothing in
Zed's graph enables `util/debug-embed`, so CI can't exercise it.
## 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
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- N/A
# Objective
Fixes#63869 — "Copy Value" in the debugger panel copied the trimmed
display preview instead of the full value.
## Solution
Evaluate the variable's `evaluateName` via the DAP `evaluate` request
using the `clipboard` context (falling back to `variables`), and copy
the returned result. Falls back to the display value if evaluation
fails.
## Testing
- `cargo test -p debugger_ui --lib` passes.
---
Release Notes:
- Fixed debugger "Copy Value" copying the truncated preview instead of
the full value.
Before, `GlobalWatcher` held a native backend and a polling backend, and
its methods dispatched to one or the other.
After this PR, we have `OsWatcher` which wraps a single watch backend,
and `RealFs` and `FakeFs` hold a native `OsWatcher` and a polling
`OsWatcher`.
This moves the split closer to the place where we decide which backend
should be used, and lets us clean up some indirection. A nice bonus is
that the "is this backend recursive" data exists in exactly one place.
Release Notes:
- N/A
This is a pure refactoring PR to make our FS watching code more
testable. It does two things:
1. Make the `GlobalWatcher` be owned by `RealFs` or `FakeFs` instead of
being a process-wide global.
2. Delete `FakeWatcher` and its `Watcher` implementation, and instead
mock the notify crate itself in `FakeFs` tests via the existing
`WatchBackend` trait. Now all our FS watching code down to the notify
boundary runs the same in tests and production.
Release Notes:
- N/A
# Objective
This removes an extra filesystem metadata lookup from
`RealFs::metadata`.
On Unix, `is_executable` performs a full extra stat(2)
(std::fs::metadata) just to read `mode() & 0o111`, even though the mode
bits are already present in the `symlink_metadata` result. On Windows
its impl also starts with `self.exists()`, another stat. This costs one
extra syscall plus one extra executor spawn per entry during the
worktree background scan - I experienced millions of avoidable syscalls
on a large monorepo.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Improved worktree scan performance by removing redundant executable
checks.
---------
Co-authored-by: Hamish <hamishc@users.noreply.github.com>
Closes#63620
Count Agent Skill descriptions by Unicode characters rather than UTF-8
bytes across validation, load-time warnings, the skill creator counter,
and imported-description truncation. This aligns Zed with the Agent
Skills specification and reference validator.
Testing:
- `cargo test -p agent_skills --lib`
- `cargo test -p settings_ui --lib`
- `cargo build -p zed`
- Manually verified that a 342-character CJK description containing
1,026 UTF-8 bytes can be saved successfully
- `./script/clippy -p agent_skills -p settings_ui --tests` is blocked by
an unrelated existing `clippy::drain_collect` diagnostic in
`crates/rpc/src/proto_client.rs`
<img width="667" height="210" alt="Successfully created Unicode test
skill"
src="https://github.com/user-attachments/assets/2427fce2-9f0f-462d-959f-e08ad160b3d1"
/>
Confirmed that the Codex agent panel discovers the skill and exposes it
in command completion without a length warning.
<img width="953" height="367" alt="image"
src="https://github.com/user-attachments/assets/8c100197-2e6e-4627-b3f8-862bdfaac918"
/>
Release Notes:
- Fixed valid multibyte Agent Skill descriptions being rejected for
exceeding a byte-based length limit.
---------
Co-authored-by: Chara <249489759+cmdr-chara@users.noreply.github.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
I think this is the final attempt of mine to do anything about the
binary size, as those fixes become relatively intricate and I like them
less and less.
Each commit has its own improvement stats and mainly reduce generic-code
duplication through shared non-generic helpers and `#[inline(never)]`
boundaries.
Total reduction stats:
With sccache disabled, `cargo clean` and `cargo build --release -p zed`:
Before: zed binary 396716472 bytes
After: zed binary 359416504 bytes (-9.40%, -37.29MB)
Release Notes:
- N/A
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Previously, on macOS, we set the [WatchRoot
flag](https://developer.apple.com/documentation/coreservices/kfseventstreamcreateflagwatchroot)
to `FsEventStreamCreate` (via our notify fork). This causes the
resulting stream to produce an event when any segment of the watched
path changes due to a rename (e.g. `/Users/cole/zed/crates/gpui` ->
`/Users/cole/zed2/crates/gpui`).
The cost of this is that for each path we watch on macOS, we hold open
file descriptors for that path and all its parents (and these are not
deduplicated across watched paths).
This especially blows up our file descriptor usage with non-visible
worktrees from GTD jumps:
```
zed 25415 cole 721r REG 1,14 99826 168007500 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/option.rs
zed 25415 cole 722r DIR 1,14 2432 168008864 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src
zed 25415 cole 723r DIR 1,14 128 168008863 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib/rustlib/src/rust/library/core
zed 25415 cole 724r DIR 1,14 928 168008723 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib/rustlib/src/rust/library
zed 25415 cole 725r DIR 1,14 128 168008722 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib/rustlib/src/rust
zed 25415 cole 726r DIR 1,14 96 168008721 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib/rustlib/src
zed 25415 cole 727r DIR 1,14 704 168004176 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib/rustlib
zed 25415 cole 728r DIR 1,14 256 168004175 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin/lib
zed 25415 cole 729r DIR 1,14 224 168004164 /Users/cole/.rustup/toolchains/1.97.1-aarch64-apple-darwin
zed 25415 cole 730r DIR 1,14 576 292591 /Users/cole/.rustup/toolchains
zed 25415 cole 731r DIR 1,14 224 292480 /Users/cole/.rustup
zed 25415 cole 732r DIR 1,14 8576 43880 /Users/cole
zed 25415 cole 733r DIR 1,14 160 18221 /Users
```
This PR bumps our notify dependency so that we no longer set that flag,
and instead just wake the background scanner loop every 5s to check
whether the worktree root path has changed. Note that both before and
after this change, the process_events arm of that loop checks the
worktree root path in the same way before doing anything else, so there
is no risk of descending further into the background scanner code with
an incorrect root path.
Release Notes:
- Made Zed use fewer file descriptors on macOS.
> **AI disclosure:** I used Claude (Anthropic) to write this change, its
test, and draft this PR description, after my own app shipped a
rendering bug that only reproduces on 1x displays — every test built on
gpui's test platform renders at a fixed 2.0 scale factor, so the bug was
invisible to an otherwise thorough offscreen test suite. I reviewed the
diff, ran the tests myself, and understand and take responsibility for
the change, per Zed's [AI
Policy](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#ai-policy).
# Objective
- `TestWindow::scale_factor()` has returned a hardcoded `2.0` since the
test platform's inception (`75f0670dd`, 2024-01-03), with no way for a
test to change it. Rendering behavior that only appears on 1x displays —
device-grid rounding, pixel snapping — can't be exercised: an error of
one device pixel is the full width of a hairline at 1x and half a
logical pixel at 2x, so this class of bug passes every test and ships.
- `Window::set_scale_factor` (`24058c865`, #61348, 2025-08) exists but
doesn't cover this: it overrides only the `Window`'s cached copy, so the
next `bounds_changed` re-reads the platform window and silently reverts
the override to 2.0.
## Solution
- Back the value with `TestWindowState`, still defaulting to `2.0`, so
existing tests are unchanged.
- Add `TestWindow::simulate_scale_factor_change`, which stores the new
factor and reports it through the resize callback — the same channel a
real DPI change reaches the window on — plus the matching wrappers on
`TestAppContext`, `VisualTestContext`, and `TestAppWindow`, mirroring
the `simulate_resize` family.
- Because the platform window owns the value, it survives later bounds
changes (unlike `set_scale_factor`); the test pins that.
## Testing
- Added `test_simulate_scale_factor_change` in
`crates/gpui/src/window.rs`: asserts the unchanged 2.0 default, that a
simulated change propagates to `Window::scale_factor()` through the
resize callback, and that it persists across a subsequent
`simulate_resize`.
- Reverting `scale_factor()` to the hardcoded `2.0` while keeping the
test reproduces the failure (see Showcase), so the test pins the
behaviour rather than passing vacuously.
- `cargo test -p gpui --lib` — 299 passed, 0 failed:
```
running 299 tests
...
test window::tests::test_simulate_scale_factor_change ... ok
...
test result: ok. 299 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.23s
```
- Tested on macOS. The change is confined to test-support code
(`platform/test/`, test contexts), which is platform independent, but I
have not built the Linux or Windows platform crates.
## 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)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
Before — the new test against the hardcoded `2.0`:
```
thread 'window::tests::test_simulate_scale_factor_change' panicked at crates/gpui/src/window.rs:7230:9:
assertion `left == right` failed
left: 2.0
right: 1.0
test result: FAILED. 0 passed; 1 failed
```
After — see the full run above.
Release Notes:
- N/A
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Closes#63725
Honor `preview_tabs.enable_preview_from_project_panel` when opening
files with `project_panel::Open` (Space), matching the setting-aware
single-click behavior. Add a regression test covering previews disabled.
Testing:
- `cargo test -p project_panel --lib`
- `cargo build -p zed`
- Manually verified with the setting disabled that Space opens two
permanent tabs
- Manually verified with the setting enabled that Space replaces the
previous preview tab
- `./script/clippy -p project_panel --tests` is blocked by an unrelated
existing `clippy::drain_collect` diagnostic in
`crates/rpc/src/proto_client.rs`
Manual verification:
Preview disabled — Space opens both files as permanent tabs:
<img width="1920" height="1032" alt="Preview disabled: Space opens both
files as permanent tabs"
src="https://github.com/user-attachments/assets/4b772aad-031e-401d-ac85-5a7f82a74bc1"
/>
Preview enabled — Space replaces the previous preview tab:
<img width="1920" height="1032" alt="Preview enabled: Space replaces the
previous preview tab"
src="https://github.com/user-attachments/assets/cfef36af-0cd5-4522-99b5-99d3bb2c3f9d"
/>
Release Notes:
- Fixed the project panel preview-tab setting being ignored when opening
files with the keyboard.
---------
Co-authored-by: Chara <249489759+cmdr-chara@users.noreply.github.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
# Objective
Fixes#63774
## Solution
On Wayland, the IME remained enabled when the focused control did not
register a text input handler. This allowed IME to intercept ABC...Z
character shortcuts in non-text UI, including the Project Panel outside
filename editing. However Windows 11 doesn't have this problem.
Fixed it by treating a missing input handler as not accepting text
input.
## Testing
I've tested on both Vim/Helix mode and normal mode with Vim/Helix
keybinds. All clear now.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
[after.webm](https://github.com/user-attachments/assets/91743d71-05c5-49d2-b032-4aebc8e91496)
ABC...Z character shortcuts are not going to be intercepted by IME
unexpectedly in project panel now.
---
Release Notes:
- Fixed IME remains enabled in project panel without a focused text
input in Wayland #63774
Follow up on #63775: disabling WebKit touch callouts did not fully
prevent iOS Safari from selecting the entire GPUI canvas alongside the
app's text selection.
Remote Web Inspector captured a viewport-sized DOM range containing the
canvas while its computed `-webkit-touch-callout` was `none` but
`-webkit-user-select` was `text`. Set both standard and WebKit-prefixed
`user-select` to `none` directly when GPUI creates the canvas, without
relying on the embedding application's stylesheet. This leaves
touch-event handling and the hidden IME textarea unchanged.
Closes DEL-2016
## Validation
- On an iPhone, injecting ordinary inline `-webkit-user-select: none`
prevented the issue; switching it back to `text` reproduced it. No
`!important` was necessary. This tested the equivalent runtime style,
not a rebuilt app containing this commit.
- `cargo fmt -p gpui_web -- --check` passed.
- `RUSTC_BOOTSTRAP=1 cargo check -p gpui_web --target
wasm32-unknown-unknown` passed. The bootstrap flag is required by the
existing `wasm_thread` dependency.
Release Notes:
- Fixed unintended whole-canvas selection when long-pressing in GPUI web
applications on iOS.
# Objective
Fixes#52884
On macOS, with **"Double-click a window's title bar"** set to **Fill**
and **"Tiled windows have margins"** enabled (System Settings > Desktop
& Dock), double-clicking Zed's title bar fills the whole visible frame
with no margins, while native apps leave the margin in place.
The `"Fill"` arm of `titlebar_double_click` currently falls back to
`zoom:`, with a comment stating that there is no documented API for the
Fill action. `zoom:` is the classic maximize: it targets the screen's
visible frame and never goes through the system tiling path, so the
margin preference cannot apply.
## Solution
AppKit does implement the action: `_zoomFill:` is the selector behind
**Window > Move & Resize > Fill**, and it goes through the system tiling
path. Prefer it for the `"Fill"` case, keeping `zoom:` as a fallback
when the window does not respond to it.
This means the margin geometry stays owned by the OS: neither
`EnableTiledWindowMargins` nor `TiledWindowSpacing` has to be read or
reimplemented in gpui, and the behavior follows the setting when the
user toggles it.
The selector is underscore-prefixed, hence the `respondsToSelector:`
guard and the `zoom:` fallback.
## Testing
Measured on macOS 26.6.2 (25G76), aarch64, on a 2560x1440 display with
the Dock on the left, so `visibleFrame` is `(80, 0, 2480, 1410)`. Probe:
a plain `NSWindow` (`titled`, `resizable`) in a standalone AppKit
binary, with `EnableTiledWindowMargins = 1` and `TiledWindowSpacing`
unset (default 8).
| action | resulting frame | insets vs `visibleFrame` |
| --- | --- | --- |
| `zoom:` | `(80, 0, 2480, 1410)` | 0 on all four sides |
| `_zoomFill:` | `(88, 8, 2464, 1394)` | 8 pt on all four sides |
`respondsToSelector: _zoomFill:` returns `YES` on that build. `cargo
check -p gpui_macos` and `cargo fmt -p gpui_macos -- --check` both pass.
To reproduce as a reviewer: enable both settings above, then
double-click the title bar. Before this change the window touches the
screen edges, after it the margin matches Finder or Safari. With "Tiled
windows have margins" off, both behave the same.
One behavior difference worth flagging: `zoom:` toggles, so a second
double-click used to restore the previous frame, while `_zoomFill:`
stays filled. AppKit exposes `_zoomUntile:` for the reverse direction,
which restores the pre-fill frame in my testing. I left it out to keep
the diff minimal, but I am happy to add the toggle if you would prefer
that a second double-click untiles.
I could not find a way to cover this with an automated test, since the
assertion would be about AppKit's own tiling geometry.
## 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 double-clicking the title bar ignoring the macOS "Tiled windows
have margins" setting when "Double-click a window's title bar" is set to
"Fill".
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Um4zWW8chJ5rwbGXhW8APh
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
# Objective
- Improve Go's syntax highlighting by distinguishing control-flow
keywords from other keywords, in the same way it was done for other
languages.
## Solution
- Split keywords in `highlights.scm` into two groups: `keyword.control`
and `keyword`. This change affects tree-sitter highlighting, enabling
`Semantic Tokens` can override it.
## Testing
- Tested locally on Windows using a development build, with `Semantic
Tokens` disabled. Opened a Go file with a theme that assigns different
colors to `keyword` and `keyword.control`
## 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
- Screenshot showing a build without this change and one with it side by
side
<img width="930" height="154" alt="after"
src="https://github.com/user-attachments/assets/bf3f612f-0ffc-40e4-b4c3-7002fff49fb7"
/>
Release Notes:
- Improved Go syntax highlighting by separating control-flow keywords
from regular keywords
---------
Co-authored-by: Finn Evers <finn.evers@outlook.de>
Before this change, two different guests requesting the same kind of
request would cancel each other's requests and only the latest one would
have arrived to the latest to query that.
Release Notes:
- Fixed collab LSP requests cancelling each other sometimes
OpenAI's Codex endpoint reports an exhausted ChatGPT subscription with
HTTP 429 and `error.type = "usage_limit_reached"`, but no `error.code`.
The Responses parser discarded the type and classified the response from
its status alone, making it appear to be transient request throttling.
This preserves `error.type` in both Responses and Chat Completions
parsing, considers both OpenAI discriminator fields during
classification, and falls back from the more-specific `error.code` to
`error.type` when populating the existing provider rejection code.
Usage-limit errors retain OpenAI's message and are not retried as
transient 429s.
The regression coverage exercises initial HTTP failures, Responses
stream errors, Chat Completions stream errors, unknown OpenAI-compatible
provider types, and precedence when both code and type are present.
Release Notes:
- Fixed ChatGPT subscription usage limits being shown as temporary
OpenAI request throttling.
When working with multiple windows, one agent worked in the external
hard drive's directory.
After finishing working on that external dir, I've closed the entire
window (the other one, unrelated, remained) only to discover I cannot
unmount the external hard drive.
Investigated, and seems that that manual `ref_count` is buggy — replaced
that with `WeakEntry` for both agent and ACP parts.
Also added leaked project logging into reliability.
Release Notes:
- Fixed projects leaking via agents panel
On iOS, WebKit presents a native touch callout when a user long-presses
a canvas. For GPUI Web this selected the full application canvas while
GPUI independently selected the intended word, producing two pairs of
selection handles, a native edit menu, and haptic feedback.
Set `-webkit-touch-callout: none` on the canvas created by `gpui_web`.
GPUI already owns touch gesture recognition on this surface, so WebKit
should not provide a competing canvas interaction.
Tested with:
- `cargo fmt --check --package gpui_web`
- `RUSTC_BOOTSTRAP=1 cargo check -p gpui_web --target
wasm32-unknown-unknown`
- A Delta Web WASM build using the local Zed checkout
- Manual verification on an iPhone that long-press word selection no
longer selects the full canvas
Release Notes:
- N/A
# Objective
- Removes Agent Panel menu item when AI disabled toggle is on.
- Fixes#63497
## Solution
- Use the global DisableAiSettings - disable_ai check in `app_menus.rs`.
To keep the order the same I
1. Check the disable AI setting
2. If true push to the `view_items` vec![]
3. Extend the vec![] with the remaining Menu Items and Separators.
## Testing
This can be tested visually:
1. Open Zed with AI settings enabled
2. Click View when Zed is focused
3. Noting where Agent Panel is on the list and to make sure clicking it
opens up the Agent Panel.
4. Open settings
5. Navigate to AI settings
6. Toggle disable AI on
7. Click View
Expected: Agent Panel is gone from the menu. The opposite is also
expected.
- This was tested on macOS 26.6.2 (25G83).
## 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
To keep this PR simple, I did not add any testing to this, as there were
no tests in this file already.
- [x] Performance impact has been considered and is acceptable
## Showcase
<details>
<summary>Click to view showcase</summary>
https://github.com/user-attachments/assets/50db44ac-6c11-4101-a064-fd4e3b285620
</details>
---
Release Notes:
- Fixed Agent Panel appearing in the "View" menu when disable AI
settings is on.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
# Objective
Add Gemini 3.8 Flash to Zed's built-in Google AI provider so it can be
selected from the model dropdown.
## Solution
Register `gemini-3.8-flash` with its 1 million token context window, 64k
output limit, and Low, Medium, and High thinking levels. Medium is the
default, and Low is used when thinking is disabled because the model
rejects Minimal.
Add tests covering the model metadata, serialization, token limits,
thinking levels, and disabled-thinking behavior.
## Testing
Tested on Windows using Rust 1.98 GNU:
- `cargo test -p google_ai` — 23 passed
- `cargo fmt --all --check`
- `cargo +stable-x86_64-pc-windows-gnu clippy -p google_ai --release
--all-targets --all-features -- --deny warnings`
Reviewers can run `cargo test -p google_ai`. The pinned MSVC toolchain
was not tested locally because `link.exe` was unavailable.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Added Gemini 3.8 Flash to the Google AI models
`KeyBinding::set_default_visibility` lets applications suppress
keybinding labels, but the current visibility value is private to
`KeyBinding::render`. Applications that compose related modifier hints
from lower-level UI elements cannot follow the same presentation policy.
Expose the existing visibility query without changing its behavior. This
lets those callers omit their complete hint, including accompanying text
and spacing, while sharing the same application-wide source of truth.
Release Notes:
- N/A
`replace_value_in_json_text` spelled a newly inserted key with
hand-written quotes, so a key carrying a `"` or a `\` produced invalid
JSON. The removal and rename paths then could not find such a key again:
both walked backwards to the nearest raw `"`, which lands inside an
escape, and ate the neighbouring entry while leaving JSON that still
parses.
The parser already hands back the key's byte range, so the three sites
use it, and serde for the spelling, the way key lookup and the
nested-construction path always did.
Worth knowing beyond the escaping: `update_value_in_json_text` pushes
every map key into the key path verbatim, so any settings map whose keys
are not authored by hand reaches this. Most are typed by the user, but
`favorite_config_option_values` is keyed by a `SessionConfigId` that an
ACP agent supplies over the protocol.
Tests cover insertion into a single-line and a multi-line object,
removal and rename, all with a key carrying a quote and a backslash.
Release Notes:
- Fixed a settings key containing a quote or a backslash corrupting
`settings.json`.
## Summary
- Add `window_title_format` and `window_title_separator` settings for
customizing the window title
- Expose `${projectName}`, `${fileName}`, `${filePath}`,
`${relativePath}`, `${fileStem}`, `${remoteName}`, `${remoteHost}`,
`${appName}`, and `${separator}` as the native Zed window-title
variables
- Keep the collab `↗/↙` indicator hard-appended
- Translate VS Code `window.title` / `window.titleSeparator` aliases
into Zed's canonical variables during settings import, including
`${appName}` passthrough support and mapping VS Code's
`${activeEditorMedium}` onto Zed's `${relativePath}`
- Gate path-, remote-, and release-channel-derived lookups on whether
the active template references the corresponding variable, so the
default template avoids the extra work and still uses the existing
`last_window_title` cache to skip redundant platform updates
An alternative approach is at #49638. I went with `${variable}` names
over `$ZED_*`, canonical Zed variable names with VS Code aliases handled
at import time, kept `${separator}` as the only structural token, and
left `${dirty}` out of scope.
## Implementation reasoning and notes
### Variables considered but not included
- **collab/shared indicator variable**: kept hard-appended instead.
Folding it into the template would need whitespace/separator logic the
other variables don't need, and I'd rather not bake those semantics in
without a concrete need for it.
- **dirty variable**: The glyph choice and interaction with OS-level
edited indicators (like macOS's titlebar dot via `set_window_edited`)
felt like a separate design call I wasn't confident making here.
A separator-style config for each of collab/shared/dirty would solve the
above, but I didn't want to add too many additional settings initially.
### Performance
`update_window_title` is on a hot path, so two short-circuits apply:
- Path-, remote-, and release-channel-derived lookups (`absolute_path`,
relative-path string, `file_stem`, `remote_connection_options`,
`ReleaseChannel::try_global`) are gated on `template.contains(...)` via
`WindowTitleNeeds::from_template`, so the default template avoids the
extra work.
- The existing `last_window_title` cache still skips the platform call
when the rendered title is unchanged.
## Screenshots
Settings Editor entries for `window_title_format` and
`window_title_separator`:
<img width="774" height="324" alt="Settings Editor screenshot"
src="https://github.com/user-attachments/assets/b3378ec7-5649-4de3-9de6-164a42bce3fd"
/>
Customized Zed window titles in AltTab app switcher (remote, local,
empty):
<img width="774" height="324" alt="AltTab app switcher screenshot"
src="https://github.com/user-attachments/assets/a189945e-fc68-41b9-aab9-6dc04d5ef4ab"
/>
## 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#14534
Release Notes:
- Added configurable window title formatting with `window_title_format`
/ `window_title_separator`, including `${appName}` / `${remoteName}` /
`${remoteHost}` variables and VS Code `window.title` import support
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
The particular edge case that is covered here is closing a community PR,
then labeling it with an `area:`, and _then_ reopening it.
Release Notes:
- N/A
It's been fun for a while to have the same function calling GitHub API
in every single script, but we're going to have fun in different ways
now.
This one's for you, @MrSubidubi! 🥂
## Testing
I've ran the things that had `--dry-run` locally and nothing blew up,
but the ultimate smoke test will be carried out in production.
---
Release Notes:
- N/A
# Objective
In Vim mode, pressing `o` to open a line inside a documentation-style
block comment preserves indentation but drops the `* ` prefix.
The behavior for pressing Return is already correct as it continues this
prefix in the next line.
This change makes both actions behave consistently.
Fixes#55049
## Solution
Make Vim’s `o` and `O` commands copy documentation-comment prefixes such
as `* ` onto the new line. This happens only when the current line is
parsed as a comment.
Also added regression coverage for this and folded it into the existing
`test_o_comment` test.
## Testing
- `CC=clang CXX=clang++ cargo test -p vim test_o_comment -- --nocapture`
- `CC=clang CXX=clang++ cargo test -p vim`
- `CC=clang CXX=clang++ cargo test -p multi_buffer`
- `cargo fmt --all -- --check`
- `CC=clang CXX=clang++ ./script/clippy -p vim -p multi_buffer`
- Tested on Linux aarch64.
## Self-Review Checklist:
- [x] I reviewed the diff for quality, security, and reliability
- [x] Unsafe blocks, if any, have justifying comments
- [x] The content adheres to the Zed UI standards
- [x] Tests cover the changed behavior
- [x] Performance impact is acceptable
---
Release Notes:
- Fixed Vim `o` comment continuation in C-style multiline comments.
# Objective
The project panel doesn't show a file or folder's actual location on
disk anywhere in the UI — you have to rely on the tab title or context
menu ("Copy Path") to find out where a file actually lives, which is
especially unclear for files with the same name in different folders, or
when a project has multiple worktrees.
## Solution
- Adds a tooltip to each file/folder row in the project panel that shows
the entry's path on hover, with the home directory abbreviated to `~`
(via the existing `PathExt::compact()` utility, consistent with how
paths are already displayed elsewhere, e.g. the Recent Projects list).
## Testing
- Manually tested by hovering over files and folders at various nesting
depths in the project panel and confirming the tooltip shows the correct
path.
- Tested with a project both inside and outside the home directory to
confirm the `~` substitution only applies when appropriate.
- Confirmed existing row behavior (selection, click-to-open,
drag-and-drop, right-click context menu) is unaffected by the added
tooltip.
- Reviewers: hover over any row in the project panel and confirm the
tooltip appears after the normal hover delay and shows the expected
path.
- Tested on macOS only — haven't verified on Linux/Windows.
## Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
## Showcase
<img width="1512" height="871" alt="image"
src="https://github.com/user-attachments/assets/ec86f9ab-0a8e-40f7-b783-8a115203f11d"
/>
- Help others understand the result of this PR by showcasing your
awesome work!
- If this PR includes a visual change, consider adding a screenshot,
GIF, or video
- A before/after comparison is very useful for changes to existing
features!
While a showcase should aim to be brief and digestible, you can use a
toggleable section to save space on longer showcases:
<details>
<summary>Click to view showcase</summary>
My super cool demos here
</details>
---
Release Notes:
- Added a tooltip showing the file path when hovering over files and
folders in the project panel.
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
## Objective
Markdown preview appearance settings are split between root theme
settings and
`markdown_preview`, and Markdown files always open as source editors
even when a user primarily
wants the rendered preview.
## Solution
- Group the Markdown preview font settings under `markdown_preview`,
migrate their legacy keys
across supported settings scopes, and update defaults, Settings UI, and
documentation.
- Add `markdown_preview.open_markdown_files_in_preview`, defaulting to
false. When enabled, clean
Markdown opens are replaced by a rendered preview while preserving dirty
editors, temporary-tab
behavior, pane activation and focus, targeted navigation, workspace
restoration, and the escape
back to source.
## Testing
- Manually verified on macOS that enabling the setting opens Markdown
files as preview-only.
- `cargo test -p markdown_preview` (three consecutive runs)
- `cargo test -p migrator nest_markdown_preview`
- `cargo test -p settings_content`
- `cargo check -p markdown -p markdown_preview -p migrator -p settings
-p settings_content -p settings_ui -p theme_settings -p workspace`
- `./script/clippy -p gpui_apple -p markdown -p markdown_preview -p
migrator -p settings -p settings_content -p settings_ui -p
theme_settings -p workspace --features gpui_apple/runtime_shaders`
- `cargo fmt --all -- --check`
- `git diff --check`
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Recordings
https://github.com/user-attachments/assets/032ab36d-f934-4ef7-aa18-53f3955a7df8https://github.com/user-attachments/assets/dc872265-2fe0-45ac-95eb-ff820d3a8164
Release Notes:
- Added a setting to open Markdown files directly in preview mode and
grouped Markdown preview settings together.
## Summary
- Reuse the existing Zed clone activity indicator, which previously
showed only a static `Cloning <URL>` message.
- Add filesystem job updates so the existing indicator can change while
a job is running.
- Stream exact `git clone --progress` messages into that indicator
without maintaining a phase allowlist.
- Preserve the final Git stderr message when cloning fails.
https://github.com/user-attachments/assets/a9b8cbfd-b87f-4d83-a24b-992eb1c4de1f
## Testing
- `cargo test -p fs git_clone_progress::tests -- --nocapture`
- `CCACHE_DISABLE=1 ./script/clippy -p fs -p activity_indicator`
- Manually cloned a repository and verified live Git progress in the
activity indicator.
Release Notes:
- Improved repository cloning by showing live Git progress in the
activity indicator.
# Objective
- Fixes#63433
- Currently, when there is no logged in user, the Organization menu item
shows up even though it should not.
## Solution
- This PR simply does an early return when there is no logged in user,
which skips the logic to add the organization header into the menu drop
down.
## Testing
- Open a Zed window
- Sign out of Zed
- Click the menu bar chevron (top-right corner) and ensure that the
Organization Menu item (like in image below is not there anymore.
- Login to make sure it does display properly when a user is logged in.
- I tested this on a Windows Machine as I use that for development, but
I believe the reproduction steps should be the same across Operating
Systems. I don't have access to other operating systems, so that might
be something that I'd need the communities help with to make sure
everything is working properly.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments - Not Applicable
- [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 - Not Applicable.
- [ ] Performance impact has been considered and is acceptable - Not
applicable
## Showcase
Before: Image is from the Original issue
<img width="438" height="458" alt="image"
src="https://github.com/user-attachments/assets/c4852e86-1b68-42d8-ad79-68904214eed7"
/>
After:
https://github.com/user-attachments/assets/520f2564-36da-433b-9339-8c0210695ee0
---
Release Notes:
- Fixed issue where "Organization" section in dropdown menu was being
rendered empty when no user was logged in.
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
# Objective
Case conversion commands deleted the newline at the end of the
selection,
merging the selected line into the line below it.
To reproduce:
1. A buffer with two lines:
```
hello world
goodbye
```
2. Put the cursor on line 1 and run `editor: select line` — this selects
`hello world\n`, newline included.
3. Run `editor: convert to upper camel case`.
Before: `HelloWorldgoodbye`, one line. After: `HelloWorld` / `goodbye`.
## Testing
Added a regression test to `test_manipulate_text`.
Release Notes:
- Fixed the case conversion commands deleting the line break when the
selection
ended at the start of the next line.
# Objective
Add an optional smooth cursor movement animation to make cursor position
changes easier to follow, especially during larger jumps and
multi-cursor editing.
Related to #4991.
## Solution
- Add a new `cursor_animation.enabled` editor setting, disabled by
default.
- Animate local bar and block cursors using a damped spring while
preserving momentum during rapid cursor movement.
- Support multiple local cursors independently.
- Continue using the cursor color provided by the active theme.
- Snap immediately when scrolling, resizing, or other viewport changes
would make interpolation misleading.
- Respect the `reduce_motion` setting.
- Request animation frames only while an enabled cursor animation is
active.
Enabling the feature causes additional editor redraws while the cursor
is moving, so it is opt-in and the performance cost is mentioned in the
setting documentation.
### Attribution
The cursor spring physics and four-corner deformation algorithm are
adapted from
[vscode-neovide-cursor](https://github.com/LengineerC/vscode-neovide-cursor),
which is available under the MIT License and inspired by Neovide.
The implementation adapts the algorithm to Zed's editor and GPUI
architecture, including viewport handling, selection state
reconciliation, multi-cursor support, theme integration, and
reduced-motion behavior. The attribution and license information are
also retained in the source file.
## Testing
Automated checks run on Windows:
- `cargo fmt --all --check`
- `cargo test -p editor cursor_animation --lib`
- 15 cursor animation tests passed.
The tests cover:
- Spring convergence.
- Short and long cursor movements.
- Mid-animation retargeting and momentum preservation.
- Multiple independent cursors.
- Selection replacement and state cleanup.
- Viewport and scroll changes.
- Invalid or unusually large timing values.
- Supported cursor shapes.
To test manually:
1. Add the following to the settings file:
```json
"cursor_animation": {
"enabled": true
}
```
2. Move the cursor using typing, arrow keys, mouse clicks, and
multi-cursor actions.
3. Toggle the setting off and confirm that cursor rendering immediately
returns to its normal behavior.
Manual testing was performed on Windows and Linux using a release build
from this exact PR branch.
Verified that:
- Cursor animation is disabled by default.
- Enabling `cursor_animation.enabled` is hot-reloaded without restarting
Zed.
- Disabling the setting immediately restores the original cursor
behavior.
- Cursor movement remains responsive during typing, keyboard navigation,
and mouse navigation.
This exact PR branch has not yet been manually tested on macOS.
## 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
https://github.com/user-attachments/assets/17450529-491e-4982-b539-c46e3d5df467
---
Release Notes:
- Added an optional cursor movement animation setting.
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
# Objective
- Fixes#62923.
- When `gutter.git_gutter_width` is set to a small `Custom` value (e.g.
`{"custom": 6.0}`), the deleted-line marker becomes disproportionately
small. It is nearly invisible in the reporter's screenshots, while
added/modified markers scale acceptably.
## Solution
- The deleted marker's `Default` arm uses a `0.35 * line_height` base;
the strip's `Default` arm uses `0.275 * line_height`. That 27% larger
base is what keeps the pill-shaped deleted marker visible next to the
rectangular added/modified strips.
- The `Custom(N)` arm previously used `N` for both branches, dropping
the boost. This PR routes the deleted-empty case through a new
`deleted_marker_base_width(setting, line_height)` helper that applies a
single `DELETED_MARKER_WIDTH_RATIO = 0.35 / 0.275` constant to both
arms.
- Default-mode pixels are byte-identical because `floor(0.275 * lh *
0.35/0.275)` reduces to `floor(0.35 * lh)`. Custom-mode gains the same
1.273× multiplier the default has always had.
## Testing
- Added a pure `#[test] fn test_deleted_marker_base_width` covering
three invariants:
- `Default` at `line_height = 22.0` returns `7px`, identical to the
previous default arm.
- `Custom(6.0)` at `line_height = 22.0` returns a width greater than 6.0
(visibility preserved).
- `Custom(0.0)` returns `0.0`, so the width-0 render path is unchanged.
- Verified locally on Windows: `cargo fmt --all -- --check`, `cargo
check -p editor`, and `cargo clippy -p editor --all-targets -- -D
warnings` all exit 0.
- I have not visually verified the rendered marker on macOS or Linux. A
reviewer with the reporter's setup (`git_gutter_width: {"custom": 6.0}`
on macOS) can confirm the pill stays visible.
## 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 the deleted git-gutter marker becoming nearly invisible when
`git_gutter_width` is set to a small custom pixel value.
# Objective
Follow-up to #63118. That PR set the preview's headings to semibold and
gave h6 a muted color through `heading_level_styles`, and the PR body
says as much, but neither actually rendered. Headings in the preview
came out at the base weight and color, which you can see in the after
screenshot on that PR: every heading is regular while the bold body text
and the table header cells are heavy.
I found this while looking into @Arcitec's report on #63118 about bold
not rendering with SF Pro. That one turned out to be a different bug: SF
Pro is a variable font, and the Linux text system does not pass the
requested weight through to it. It is tracked in #60155 and #62832 has a
fix up for it, so this PR does not touch it.
## Solution
`apply_heading_style` wrote the per-level style onto the heading div
only. The div's text style reaches layout, which is why the font sizes
worked, but the text runs are shaped from `MarkdownElementBuilder`'s
style stack, and nothing ever pushed the level style onto that stack. So
weight and color were dropped on the floor.
The fix pulls the level lookup out into `heading_level_style` and has
`push_markdown_heading` refine the heading's run text style with it
before pushing, alongside the existing div refinement. No style values
change anywhere. The agent panel's level styles only set font size, so
its rendering is identical before and after; I checked.
## Testing
- `cargo test -p markdown` and `./script/clippy` are clean.
- Smoke tested the preview on Linux with a document covering h1 to h6,
headings containing bold, italic, code, and links, a wrapping heading,
lists, blockquotes, tables, and code blocks. Headings are now semibold,
h6 is muted, sizes and h1/h2 borders are unchanged.
- Checked the agent panel with a reply containing headings, bold, a
list, and a table: unchanged.
- No new test. The test platform's text system is a no-op that returns
the same `FontId` for every font, so an assertion on run weight could
not fail.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments (there are none)
- [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 (see Testing for why not)
- [x] Performance impact has been considered and is acceptable
## Showcase
Before is `main` at 6dc2206180, which already includes #63118, so the
only difference is the heading weight and the h6 color.
| Before | After |
|--------|-------|
| <img width="1933" height="2101" alt="zed_before"
src="https://github.com/user-attachments/assets/b84d536a-235d-45bf-9b38-34027accc091"
/> | <img width="1933" height="2101" alt="zed_after"
src="https://github.com/user-attachments/assets/27d90afd-93c9-4118-96c8-f849b1ad096d"
/> |
Release Notes:
- Fixed Markdown preview headings not rendering at their configured
weight.
# Objective
Fixes#63569
`run_docker_command` Debug-formatted the whole `docker exec` command, so
every `-e NAME=VALUE` pair forwarded into a dev container was written to
`Zed.log` in plaintext: once at DEBUG, and again in the error message
that `remote_client.rs` logs at ERROR on a failed reconnect.
## Solution
Render the command with `redact_arguments`, which replaces the value of
every `-e NAME=VALUE` argument with `<redacted>` before the arguments
are flattened, and pass the remaining arguments and stderr through
`util::redact::redact_command`.
Validate `containerEnv` and `remoteEnv` keys in `spawn_dev_container`
before any container is reused or built, because an empty key produced
`-e =VALUE`, which the Docker CLI rejects while echoing the value
verbatim to stderr.
Skip invalid names in `remote` as well, since `remote_env` is also
rehydrated from the workspace database.
The shared predicate lives in `util::redact::is_valid_environment_name`.
The DEBUG line now logs the redacted command and exit status only; the
previous stdout and stderr byte dumps are gone.
## Testing
`cargo test -p remote -p dev_container --lib`.
Unit tests cover redaction of forwarded env, argument boundaries,
assignments inside program arguments and stderr, invalid-name skipping
and rejection, and the podman CLI.
Release Notes:
- Fixed dev container environment variables being logged in full
---------
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Fixes https://github.com/zed-industries/zed/issues/63672
OpenCode Go now requires the `x-opencode-session` header on every model
request. Zed previously sent the header only when a request already had
a thread ID, so inline assistance, terminal assistance, and other
standalone requests could omit it and risk rejection.
This change makes the OpenCode provider add the header to every request.
Existing thread and assist session IDs are reused when available.
Standalone requests receive a generated non-empty ID. Thread title and
summary requests now carry the thread ID so related requests keep the
same session scope.
The change also adds tests for missing, empty, and invalid IDs, plus a
wire-level test that verifies the header reaches the HTTP client. The
provider test file stays separate so the implementation remains under
1,000 lines.
Testing:
- `cargo fmt --all -- --check`
- Focused OpenCode, thread summary, and thread title tests
- `cargo check -p agent_ui -p sidebar`
- `GITHUB_ACTIONS=1 ./script/clippy -p language_models`
- `git diff --check`
Release Notes:
- Fixed OpenCode Go requests that could fail when Zed omitted the
session header.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
OpenAI can return HTTP 404 during temporary service disruptions, but
language model errors currently classify that status as permanently
missing. Treat OpenAI 404 responses as transient while leaving other
providers unchanged, and expose the shared transient classification so
retry executors can consume it directly instead of inferring it from a
first-attempt delay.
Release Notes:
- Improved recovery when OpenAI temporarily returns HTTP 404 errors.
# Objective
Fixes#62169
Accounts which are marked "too young" have layout issues within the LLM
settings. Example provided in the linked issue.
## Solution
Allow the provider controls to shrink to the available width instead of
retaining their content width. Also make the young-account configuration
fill that width so the warning wraps correctly without collapsing the
provider description.
I think the "Upgrade to Pro" looks a little stretched now, but I don't
know how to fix it without allocating even more space for the already
large setting section. Could we possibly shorten the 30-day requirement
explanation? Regardless, it's much better than what it was before :D
## Testing
- I added a debug selector to be able to write a regression test for
layout issues. Since the UI may change, the tests only enforce the rough
layout.
- Compiled with `too_young_account` being `true` and `false`, checking
that the UI looks okay.
## 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>Click to view showcase</summary>
Before:
<img width="639" height="678" alt="image"
src="https://github.com/user-attachments/assets/45ed32b0-8987-49d1-8bbd-a12f7917570a"
/>
After:
<img width="640" height="225" alt="image"
src="https://github.com/user-attachments/assets/bb39a847-7d36-4597-b16d-6a6ccb872817"
/>
</details>
---
Release Notes:
- Fixed layout issues in settings when using recently created GitHub
accounts
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
Allow Cloud to send notification invalidations. Add
`NotificationsUpdated` to the `cloud_api_types` protocol and handle it
explicitly as a no-op in the existing user and LLM token listeners.
Release Notes:
- N/A
We already had the PR's upvotes (all the positive reactions,
deduplicated by user); this commit adds the issue-closed-by-the-PR's
upvotes (deduplicated against the PR's upvoters too). The code got even
uglier because I'm trying to avoid extra API calls.
Release Notes:
- N/A