Skip to content

gpui: Make deactivate_window panic when the window is not active - #6

Closed
butvinm wants to merge 77 commits into
mainfrom
guard-vacuous-deactivation
Closed

gpui: Make deactivate_window panic when the window is not active#6
butvinm wants to merge 77 commits into
mainfrom
guard-vacuous-deactivation

Conversation

@butvinm

@butvinm butvinm commented Aug 3, 2026

Copy link
Copy Markdown
Owner

TestAppContext::deactivate_window silently does nothing when the window is not the active one:

if Some(self.window) == self.test_platform.active_window() {
    self.test_platform.set_active_window(None)
}

A test that deactivates an inactive window then asserts behaviour it never exercised, and passes. Nothing signals that the call was skipped.

Assert instead of skipping. A no-op deactivation is never what the caller wanted, so failing with an explanatory message turns a silently-vacuous test into an immediate, self-describing failure - including for tests written later, which per-test assertions would not cover.

Every existing caller already activates first, usually via Workspace::test_new (crates/workspace/src/workspace.rs:7911). Verified across every crate that calls deactivate_window:

Crate Tests
editor 637
workspace 149
agent_ui 177
project_panel 95

1058 tests, zero failures.

Release Notes:

  • N/A

@butvinm
butvinm force-pushed the guard-vacuous-deactivation branch from 48e0346 to 2a1fb35 Compare August 5, 2026 00:38
@butvinm
butvinm changed the base branch from fix-layout-switch-cancels-rename to main August 5, 2026 00:39
@butvinm
butvinm force-pushed the guard-vacuous-deactivation branch from 2a1fb35 to 27b3b55 Compare August 8, 2026 23:58
zaknesler and others added 27 commits August 9, 2026 11:31
…s#62367)

# Objective

The `gpui::img` element always overrides the `aspect_ratio` field, so if
you have an image element that applies its own `.aspect_ratio()` it just
gets wiped out.

## Solution

Only apply the aspect ratio default if one is not already set.

## Testing

It's a very minor change but I did add a small test to ensure it
actually gets overridden.

## 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

This came from an issue where vertical images inside an element (square
in this case, as you'd see in an image gallery) do not behave correctly
with `object_fit` values of `ObjectFit::Contain` or
`ObjectFit::ScaleDown`.

This was simply because despite the image element having a fixed square
size (`img().size(px(200.))`), the aspect ratio would be forced to the
ratio of the image itself, so vertical images weren't being properly
fitted into their containers.

Minimal repro for that issue:
https://github.com/zaknesler/gpui-object-fit

So with this change, you can set `.aspect_square()` and the object fit
will behave as you'd expect:

<img width="1237" height="986" alt="image"
src="https://github.com/user-attachments/assets/5b1045a8-bd71-4b77-8bbd-c3b12112bcb0"
/>

---

Release Notes:

- gpui: Fix image element's aspect ratio overriding existing value
…ck (zed-industries#61187)

Follow-up to zed-industries#59838, implementing what was discussed at the end of
zed-industries#59829: cmd-click navigation now respects `lsp_results_location` when
go-to-definition falls back to find-all-references (invited in
zed-industries#59829 (comment):
"It would! Feel free to hook that up if you'd like to!").

## Problem

Cmd-clicking a symbol's definition falls back to find-all-references,
but the results always open in a multibuffer even with
`"lsp_results_location": "picker"`. The hover-link click path calls the
editor navigation methods directly, so the action handlers registered by
`lsp_locations` never get a chance to intercept.

## Solution

- `handle_click_hovered_link`'s fallback now dispatches the
`FindAllReferences` action (with `open_results_in: None`, deferring to
the global setting) instead of calling the method, so the
`lsp_locations` handler can intercept it, or propagate to the editor's
built-in handler when the setting is `multi_buffer`, preserving today's
behavior exactly.
- The plain cmd-click arm of `cmd_click_reveal_task` now runs the
definition query via `go_to_definition_of_kind` (no internal references
fallback) instead of `go_to_definition`, so the click path has a single
fallback decision point: the dispatching one. Without this, the method's
baked-in fallback opened a multibuffer before the dispatch could run.
- `go_to_definition_of_kind` visibility widened to `pub(crate)` for the
call from `hover_links.rs`.

Shift/alt click variants (type definition, splits) are untouched.
Keyboard invocations were already intercepted and are unchanged.

## Testing

- New test `test_cmd_click_fallback_honors_lsp_results_location` in
`lsp_locations`, following the module's existing test patterns: fake LSP
returning no definition and two references, `lsp_results_location:
picker`, simulated cmd-click at the cursor's pixel position, asserts the
picker opens. The test fails without this change.
- `cargo nextest run -p lsp_locations`: 6/6.
- `cargo nextest run -p editor -E 'test(hover) or test(fallback) or
test(go_to_definition) or test(references)'`: 54/54.
- `cargo fmt` and `./script/clippy` clean.
- Verified manually in a release build: with the setting on,
cmd-clicking a definition opens the picker; with it off, behavior is
unchanged.

Per the contributing guidelines' note on AI assistance: this change was
developed with heavy AI assistance (Claude Code). I have reviewed and
understand the full diff and the reasoning behind each hunk, and I'm the
one answering review feedback.

Release Notes:

- Fixed cmd-click go-to-definition falling back to a references
multibuffer even when `lsp_results_location` is set to `picker`.
We added one more custom repository role that a Guild member can hold,
therefore we need the labeler to accept it.

Release Notes:

- N/A
…closed (zed-industries#61467)" (zed-industries#62399)

This reverts commit 6297c88.

---

fixes zed-industries#62286
fixes zed-industries#62095

zed-industries#61467 fixed its intended bug,
but at the same time introduced an issue where running tasks that would
cause new tasks to be terminated immediately.
zed-industries#62322 tried to fix that
forward, but was unsuccessful. In the mean-time I am going to revert the
original PR.

We can try to re-land the original bugfix in a future PR.

Release Notes:

- N/A
Recommends GPT-5.6 Sol for both OpenAI BYOK and OpenAI subscription.
Also unifies the naming so that we use the same OpenAI model names for
the Zed/OpenAI BYOK and OpenAI subscription providers.

Release Notes:

- N/A
Now, this is one of these beautiful cases where GitHubs API ist just so
pleasant to work with: Because PRs are treated as issues, assigning an
assignee to a PR suddenly requires issue write permissions, despite the
issue in question being a PR. Not having that permission resulted in
some missing assignees on zed zippy bumps and failures of the workflows
as seen in
https://github.com/zed-industries/zed/actions/runs/31339736929/job/93311493258.

In comparison, labelling PRs requires PR write permissions as seen in
zed-industries#61525 🤡

Beautiful API and a pleasure to work with, 10/10 would recommend. 

Release Notes:

- N/A
…stries#62294)

# Objective

Ensure that, when users undo project panel operations, we don't trash
files with unsaved edits as that could lead to data loss, as outlined
[here](zed-industries#62243 (comment)).

Closes zed-industries#62243

## Solution

Update `UndoManager::trash` to require confirmation before moving files
to the trash. For files with unsaved edits, users can save, discard, or
cancel the operation while clean files receive a standard trash
confirmation, same as shown when trashing a file through the Project
Panel.

This helps avoid the issue where, if an user undoes a file creation for
a file that has unsaved edits and then quits Zed, the edits that were
saved in memory, as well as the Project Panel history, will now be gone
and there's no way to recover the data.

Batch operations have also been updated to now show a single
confirmation before making filesystem changes, preventing partial
execution when cancelled and warning about unsaved edits.

Lastly, the trash/delete prompt building has been refactored in order
for the Project Panel and Undo Manager to share the same wording,
file-list truncation, and unsaved-change warnings.

## Testing

Tested both manually as well as added the following tests:

*  `project_panel::tests::undo::undo_create_cancel_trash`
*  `project_panel::tests::undo::undo_create_dirty_file`
*  `project_panel::tests::undo::cancel_partial_trash_batch`
*  `project_panel::tests::undo::batch_trash_warns_about_unsaved_changes`

## 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

The screen recording below shows the trash confirmation dialog on both a
clean and dirty files, on both undo and redo flows.


https://github.com/user-attachments/assets/0f9b96f5-0357-4e3f-8ec2-141486942c89

---

Release Notes:

- Fixed issue with undoing or redoing project panel operations that
could lead to a file with unsaved edits being trashed without
confirmation.
# Objective

Zed's Markdown parser accepts tilde-fenced code blocks, but Mermaid
extraction only strips backtick fences. As a result, a block like this
is parsed as Mermaid while the fence itself is still passed to the
renderer:

```markdown
~~~mermaid
graph TD;
~~~
```

## Solution

Teach the Markdown code-block helpers to recognize triple-tilde fences
alongside triple-backtick fences.

The change stays in the existing parsing path, so Mermaid rendering does
not need a separate special case. A regression test covers extraction
from a tilde-fenced Mermaid block.

## Testing

- `cargo fmt --all -- --check`
- `cargo test -p markdown` (138 tests)
- `./script/clippy -p markdown`
- `cargo build -p zed`
- Opened a `~~~mermaid` block in the built Zed Dev app on macOS and
verified that Markdown Preview renders the diagram

## 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 Mermaid diagrams in Markdown previews when they use triple-tilde
fences.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Closes zed-industries#61208

Before, Zed showed no toasts on startup when tasks.json contained
malformed entries, also if there were two top-level arrays, the last one
was silently discarded without any toasts too.

The PR fixes both.

Release Notes:

- Fixed error toast not showing for malformed tasks.json
> “Smart quotes” are the ideal form of quotation marks and apostrophes,
and are commonly curly or sloped. "Dumb quotes," or straight quotes, are
a vestigial constraint from typewriters when using one key for two
different marks helped save space on a keyboard.

Also helps us be consistent. I’m going to make a PR to our marketing
site to fix these issues as well, to bring further consistency to our
copy (docs / marketing / otherwise). Starting with v0.5.0 and up,
[`smart-punctuation`](https://github.com/rust-lang/mdBook/blob/6bf7fadc295a862f1f4b2f2d4a9c4c0b1e998dff/CHANGELOG.md#config-changes)
is enabled by default, so we just need this temporarily.

Good read: https://smartquotesforsmartpeople.com/

---

Release Notes:

- N/A
While working on the project search on type PR and testing it, uncovered
this bug and split off into a separate commit

Release Notes:

- N/A
…ed-industries#61871)

GPUI's input-latency histograms only sample frames that were preceded by
input, so a window that janks while animating or while streaming content
(agent panel output, terminal scrollback) never shows up in the fleet's
latency reports. Hang detection catches outright stalls, but frames that
are merely late — stutters in the 30–100ms range during animation —
currently aren't visible anywhere.

This adds a `frame-duration-histogram` feature to GPUI with a per-window
tracker recording two histograms: the duration of every `Window::draw`,
and the interval between consecutively presented frames while the window
is animating (a next-frame callback was already scheduled at the
previous present, so frames are being produced back-to-back and a
stretched interval means frames were missed). Intervals are only
recorded for active windows, since inactive windows are deliberately
throttled to a lower frame rate, and re-presents of unchanged frames
(e.g. sustaining the display's refresh rate during high-rate input) are
excluded. Zed enables the feature and reports both histograms every five
minutes as a "Frame Duration Report" telemetry event alongside the
existing "Latency Report", bucketed at roughly the 120Hz/60Hz/30Hz frame
budgets so dropped-frame rates can be aggregated across the fleet.


Release Notes:

- Added frame rendering performance to the diagnostics Zed collects when
telemetry is enabled, to help find and fix stutters and dropped frames.
The hosted-model reference now includes Claude Opus 5. This closes the
gap between the public documentation and the models that `cloud`
currently offers to Zed Pro and Zed Business customers.

The pricing table lists the provider price and Zed price for input,
output, cache-write, and cache-read tokens. The context-window table
lists the current 1M-token hosted limit. This change does not alter
model access or billing behavior.

Testing performed:

- `cd docs && npx prettier --check src/account/zed-hosted-models.md`
- `cd docs && mdbook build`

Release Notes:

- N/A
…62352)

# Objective

When developing remotely, when I close the uncommitted changes tab, I
need some time to load before I can copy the path. Or have to switch to
the project panel to find the specific file. All of this is annoying, so
I added a copy path action to the git panel's context menu and key
bindings consistent with the project panel.

## Solution

Already described in the Objective section.

## Testing

I wrote a unit test and tested it manually.

## 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

<img width="411" height="535" alt="showcase"
src="https://github.com/user-attachments/assets/a17e7633-eb92-4737-aa30-958fe58bb99f"
/>
<img width="717" height="427" alt="showcase"
src="https://github.com/user-attachments/assets/d067e892-17de-4527-ac20-16cad6f38015"
/>


---

Release Notes:

- Added "Copy Path" and "Copy Relative Path" actions to the Git Panel's
context menu
# Objective

- Make Git Panel grouping sections collapsible so users can hide
sections they are not currently interested in.
- Support collapsible sections when grouping changes by tracking and by
staging.
- Provide a clear visual indicator showing whether each section is
expanded or collapsed.

## Solution

- Added per-section collapsed state to the Git Panel.
- Made grouping headers clickable to toggle their section between
expanded and collapsed.
- Added chevron indicators that point down when expanded and right when
collapsed.
- Applied the behavior to both flat and tree views.
- Kept the stage/unstage checkbox independent from the header collapse
interaction.
- Ensured a previously collapsed Tracked section does not hide files
after switching to Group by None.

## Testing

- Ran `rustfmt --edition 2024 crates/git_ui/src/git_panel.rs --check`.
- Ran `cargo check -p git_ui`.
- Ran `cargo test -p git_ui`:
  - 129 tests passed
  - 0 tests failed
- Ran `git diff --check`.
- Attempted `./script/clippy -p git_ui` twice. It produced no lint
diagnostics but did not finish compiling the release, all-targets,
all-features dependency graph within the available timeout.
- Manually verify by selecting both grouping modes in the Git Panel and
clicking each section header in flat and tree views. Confirm that:
  - The section contents are hidden and restored.
  - The chevron updates to reflect the current state.
  - Clicking the stage/unstage checkbox does not collapse the section.
  - Switching to Group by None does not leave tracked files hidden.

## 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



https://github.com/user-attachments/assets/77ec4c88-4a6d-4e49-ac9f-ddbf80e724ca


---

Release Notes:

- Improved Git Panel organization by allowing grouped change sections to
be collapsed
Show a modal when invoking the stash action to allow users to provide an
optional custom message for the stash entry.

Closes zed-industries#62430 


# Image

<img width="1622" height="1106" alt="Screenshot 2026-08-10 at 9 14
00 PM"
src="https://github.com/user-attachments/assets/0d26dac2-919d-4bb1-b6a7-433ceff18955"
/>

<img width="1622" height="1106" alt="Screenshot 2026-08-10 at 9 14
11 PM"
src="https://github.com/user-attachments/assets/896b68ff-999f-4ec9-a6a4-e0e7a6867286"
/>



# Objective

Zed's stash action runs `git stash push --quiet --include-untracked --`
with no `-m`, so every stash is labelled with git's auto-generated `WIP
on <branch>: <sha> <subject>`. That text describes the commit you were
sitting on, not what you stashed — so two stashes taken from the same
commit are indistinguishable.

This undercuts the stash picker (`git::ViewStash`), which lists entries
as `#<index>: <message>` and fuzzy-searches over exactly that string.
The search box already exists; there is just nothing meaningful to
search, because every candidate is a variation of the same
auto-generated line.

## Solution

`git::StashAll` now opens a single-line modal ("Optionally provide a
stash message") before stashing.

- Confirming with text passes `--message <text>` to `git stash push`.
- Confirming with the field empty omits the flag entirely, keeping git's
default description — so the prompt is a one-keystroke pass-through and
existing muscle memory still works.
- Cancelling aborts the stash, so the prompt doubles as a confirmation
step.

Implementation:

- `StashMessageModal` (`Editor::single_line`) in `git_panel.rs`, toggled
from `GitPanel::stash_all`. `menu::Confirm` trims the input and maps
empty to `None`.
- `message: Option<String>` threaded through `Repository::stash_all` →
`stash_entries` → `GitRepository::stash_paths`. The flag is appended
before the `--` separator so a message is never parsed as a pathspec.
- New `message` field on the `Stash` proto message, so remote and collab
projects behave identically.

One non-obvious detail: the modal is opened via `cx.defer_in` rather
than inline. `git::StashAll` is registered on the workspace
(`git_ui.rs`) as well as on the panel element, and
`Workspace::register_action` dispatches while `Workspace` is leased — so
opening the modal inline re-enters that update and hits GPUI's
`double_lease_panic`. This only reproduces when focus is *outside* the
Git Panel, which makes it easy to miss.

`Option<String>` rather than `String` is deliberate: `--message ""`
produces a blank stash description, which is strictly worse than git's
default.

## Testing

Manually verified the modal in a local build on macOS: the prompt
appears on `git::StashAll`, accepts a message, and the named entry shows
up in the stash picker.

Also verified at the git level by replaying the exact argument vector
`stash_paths` builds against a scratch repo with mixed staged / unstaged
/ untracked changes:

| Case | Result |
|---|---|
| `stash push --quiet --include-untracked --message "my named stash" --
<paths>` | `stash@{0}: my named stash`; worktree clean, untracked file
included |
| same, without `--message` | `stash@{0}: <sha> <subject>` — git's
default text |
| `--message "x" --` with no paths (clean repo) | exit 0, no stash
created — the empty pathspec does **not** stash everything |

`cargo fmt --check` clean, `./script/clippy -p git -p fs -p project -p
git_ui` passes with `--deny warnings`, and the existing suites pass
(`cargo test -p project -p git_ui`, 436 tests).

Worth a reviewer's attention: trigger `git::StashAll` with focus in the
**editor** rather than the Git Panel. That routes through the workspace
action registration and is the case the `cx.defer_in` deferral exists to
keep from panicking.

No new automated tests — the behavior is testable with the existing
`git_panel.rs` harness (`init_test`, `GitPanel::new`) if reviewers would
prefer coverage over a manual check.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments — n/a, no unsafe
added
- [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 — no new tests; see Testing
- [x] Performance impact has been considered and is acceptable — one
extra process argument; no new work on any hot path


---

Release Notes:

- Added an optional stash message prompt when stashing changes
`

---------

Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
…es#62356)

# Objective

Helix uses tab/shift-tab to navigate code action menus. Currently, this
will indent the code instead of navigating within the menu.

## Solution

Add keymaps.

## Testing

I tested it manually.

## 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 support for using `tab` and `shift-tab` to navigate the code
actions menu in Helix mode
…ies#62466)

OpenAI reasoning summaries are streamed as multiple indexed parts, and
each new reasoning output item starts its indexes at zero. The Responses
event mapper previously treated those indexes as global, so adjacent
reasoning items could be concatenated without whitespace, producing text
such as `**First item****Second item**`.

Track the current summary part by both its item ID and summary index,
and emit a separator whenever that pair changes. Text delta events now
retain their summary index as a fallback when a separate part-added
event is absent, while sharing the same boundary handling to avoid
duplicate separators.

Testing performed:

- `cargo check -p open_ai`
- `cargo nextest run -p open_ai`
- `cargo fmt -p open_ai -- --check`
- `./script/clippy -p open_ai`

Release Notes:

- Fixed missing separators between OpenAI reasoning summaries.
# Objective

I noticed that in workspace symbol search, the function's symbol kind
has become `Trait`.


## Solution

Add `to_proto` and a macro to define the mapping instead of `as i32`.

## Testing

Updated the test.

## 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 `SymbolKind` mapping to LSP protocol values
Spotted
```
The package `block v0.1.6` currently triggers the following future incompatibility lints:
> warning: static of uninhabited type
>   --> .../block-0.1.6/src/lib.rs:64:5
>    |
> 64 |     static _NSConcreteStackBlock: Class;
>    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>    |
>    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
>    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
>    = note: for more information, see issue #74840 <rust-lang/rust#74840>

The package `proc-macro-error2 v2.0.1` currently triggers the following future incompatibility lints:
> warning[E0365]: extern crate `proc_macro` is private and cannot be re-exported
>    --> .../proc-macro-error2-2.0.1/src/lib.rs:494:13
>     |
> 494 |     pub use proc_macro;
>     |             ^^^^^^^^^^
>     |
>     = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
>     = note: for more information, see issue #127909 <rust-lang/rust#127909>
> help: consider making the `extern crate` item publicly accessible
>     |
> 277 | pub extern crate proc_macro;
>     | +++
```
warnings recently.

The former is impossible to fix quickly as needs a migration to `objc2`,
but the latter is easily fixed by a version bump, ergo this PR.

Release Notes:

- N/A
# Objective

- Stop language-server update checks from waiting forever.
**Note:** I tried to find any existing issue but no luck.

## Solution

- Set one time limit for the full response body. If the GitHub, for
example, release request stops responding, return an error. Do not let
it block language-server update checks without limit.

## Testing

- Did you test these changes? If so, how?

   1. This is a flaky issue, reproducing it is not that trivial.
2. The easiest way I found is just restarting Zed until you get the
notification in the status bar `Checking for updates
<language_server_naem>`

- Are there any parts that need more testing?

   No

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

   See above.

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

   - macOS
   - Linux

## 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

<img width="2624" height="2260" alt="CleanShot 2026-08-03 at 20 29
11@2x"
src="https://github.com/user-attachments/assets/83e2781c-15bc-4924-be33-88c26f20387d"
/>

---

Release Notes:

- Fixed language servers update checks
…ndustries#62325)

Since zed-industries#60772, a worktree's ignore rules are also applied to the
directories above its root. Because of this, an `info/exclude` pattern
naming one of those parent directories marks it as ignored, and with it
the whole worktree below.

Stop the walk at the repository containing the worktree root.

Also skip exclude rules for paths outside the work directory they are
anchored at, as `.gitignore` and global gitignore rules already do.

Release Notes:

- Fixed a worktree being reported as entirely ignored when its
repository's `info/exclude` named one of the worktree's parent
directories
…industries#62477)

Release Notes:

- Make GPT-5.6 Sol default for OpenAI subscribed

Signed-off-by: Neel <neel@zed.dev>
## What

`docs/.conventions/brand-voice/SKILL.md` declares:

```yaml
name: brand-writer
```

while sitting in a directory called `brand-voice`.

The Agent Skills specification requires the two to be identical:

> The required `name` field: … **Must match the parent directory name**
> — <https://agentskills.io/specification#name-field>

So this skill fails `skills-ref validate` today.

## Which side is wrong

The directory — and this repository settles it three separate ways, with
no outside context needed.

**1. The sibling copy already uses the matching name.**
`.factory/skills/brand-writer/` holds the same four files (`SKILL.md`,
`rubric.md`, `taboo-phrases.md`, `voice-examples.md`) under
`brand-writer`.

**2. `crates/agent_skills/README.md` documents the skill system using
this exact skill, and the name it documents is `brand-writer`:**

```
line 107:  <name>brand-writer</name>
line 149:  the model … calls `skill { name: "brand-writer" }`
line 151:  when the user types `/brand-writer`
line 158:  <skill_content name="brand-writer">
```

That name is load-bearing — it is what the skill tool invokes and what
the slash command types. The directory name is referenced twice, both
inside `docs/.conventions/CONVENTIONS.md`.

**3. Six of the repository's seven skills already match their
directory:**

| skill | matches? |
| --- | --- |
| `.agents/skills/gpui-test` | ✅ |
| `.agents/skills/lint-creator` | ✅ |
| `.agents/skills/zed-cherry-pick` | ✅ |
| `.factory/skills/brand-writer` | ✅ |
| `.factory/skills/humanizer` | ✅ |
| `crates/agent_skills/builtin/create-skill` | ✅ |
| **`docs/.conventions/brand-voice`** | ❌ the only one |

## The change

The frontmatter is untouched. Only the directory moves, plus the two
references to it:

- `docs/.conventions/brand-voice/` → `docs/.conventions/brand-writer/`
(4 files, pure rename)
- `CONVENTIONS.md:5` — `[brand-voice/](./brand-voice/)` →
`[brand-writer/](./brand-writer/)`
- `CONVENTIONS.md:368` — `` `brand-voice/rubric.md` `` → ``
`brand-writer/rubric.md` ``

`git grep brand-voice` returns nothing afterwards.

If you would rather keep the directory name and rename the field to
`brand-voice`, that is a one-line change instead and I am happy to
switch it — but it would give the two copies of one skill two different
names, and it would diverge from the name
`crates/agent_skills/README.md` documents.

## One thing I noticed but did not touch

The two copies have drifted. `.factory/skills/brand-writer/SKILL.md` is
279 lines and includes a *"Phase 4: Humanizer Pass"* section;
`docs/.conventions/`'s copy is 265 lines, lacks that section, and
renumbers Validation from Phase 5 to Phase 4. That is a separate
question about which copy is canonical, so it is left alone here.

---

Found with [AgentCompass](https://github.com/YoavLax/agent-compass), an
offline static analyzer for AI-agent repo readiness. Verified by hand
against the spec before opening.

Release Notes:

- N/A
# Objective

- Fixes zed-industries#62238
- Properly escapes paths in the sftp PUT line

## Solution

- 10-line wrapper function that escapes paths as sftp expects. Namely:
paths in quotes with `\\` and `"` escaped.

## Testing

- Did you test these changes? If so, how? `cargo check`
- Are there any parts that need more testing? Up to you, this is a
simple change and I dont think sftp with default install paths ever
worked on MacOS
- How can other people (reviewers) test your changes? Is there anything
specific they need to know? Just connect to a remote on OSX and see if
the logs had an sftp upload failure in there
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fix remote uploads over sftp where the paths contain spaces

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
…ed-industries#62502)

ChatGPT subscription models currently report the short-context billing
thresholds (272k or 372k tokens) as their maximum context windows. Those
thresholds matter when Zed is paying metered API costs, but subscription
requests are billed directly by OpenAI.

This updates the subscribed models to report the full context windows
supported by the corresponding public API models: 1.05M tokens for
GPT-5.4, GPT-5.5, and GPT-5.6, and 400k tokens for GPT-5.4 Mini. It also
reports the 128k output limit so context accounting reserves capacity
for the response. Request serialization is unchanged; the unsupported
`max_output_tokens` parameter is still omitted from requests to the
Codex backend.

Release Notes:

- Improved context window usage for GPT models accessed through a
ChatGPT subscription.
HalavicH and others added 26 commits August 13, 2026 18:13
…ries#61796)

# Objective

A column's filter popover grays out values that would leave zero rows
given other active filters.
That check only looked at columns filtered _before_ the one being
viewed, so reopening a filter on a column filtered earlier than another
still-active one showed a value as available with count `0` —
selectable, but guaranteed to empty the table.

Separately, values already checked when they became blocked lost their
checkmark and couldn't be unchecked from the popover (matches IntelliJ's
reference behavior of always keeping values checkable with an honest
count, never fully disabled).

## Solution

- Availability now reuses the same `rows_passing_other_filters` set
already used for counts (every other active column's filter, own filter
excluded) instead of the old order-dependent cascade over
`activation_order`. Removed `activation_order` entirely — now dead code.
- `Unavailable` carries `is_applied`, same as `Available`.
Hidden-and-applied rows stay checked and toggleable (to uncheck); only
hidden-and-unapplied rows stay disabled.
- Filter popover footer no longer disappears when a filter's count drops
to `0` (`has_active_filters` instead of `selected_rows == 0`).

## Testing

Fixture:

```csv
A,C
1,red
2,red
1,blue
1,blue
```

Rendered as:
<img width="381" height="165" alt="image"
src="https://github.com/user-attachments/assets/fc12d1d3-26e6-4f8e-97f0-5522f67e70ea"
/>


Manual:
apply filters:
- C=red,blue
- A=2
reopening C's popover shows the blocked `blue` value grayed with count
`0`, stays checked and uncheckable.

## Demo

| Before (counds not updated) | After (counts reflect reality) |
| --- | --- |
| <img width="631" height="190" alt="image"
src="https://github.com/user-attachments/assets/df433449-826d-4f7e-8c35-d3779911b7fa"
/> | <img width="615" height="217" alt="image"
src="https://github.com/user-attachments/assets/ce067fb9-3fd5-4d2a-9689-8defc587f617"
/> |


Release Notes:

- Fixed CSV preview column filters showing incorrect availability/counts
depending on which filter was applied first
…ies#62587)

Dropped entities are released only inside an update's effect flush, and
releases cascade: one flush drops the entities whose handles are gone,
their drops release further handles and can queue foreground work, and a
later flush collects those. `BenchAppContext` callers that only pump the
executor between iterations therefore saw torn-down state linger in the
entity map until some woken task happened to run an update — in a
downstream benchmark this looked like a per-iteration leak of the whole
app graph (~35 MB per iteration), releasing on an apparently timer-bound
schedule.

This adds `BenchAppContext::settle`, which alternates draining queued
work with GPUI update cycles until the dispatcher reports idle,
mirroring the update cadence production gets for free from frames and
input events. `bench_batched_task` now settles before each iteration's
setup (outside the timed interval), so the previous iteration's state is
fully released and cannot accumulate across a measurement. A new
`ThreadedDispatcher::is_idle` predicate backs the loop's termination and
is covered by a unit test.

Release Notes:

- N/A
While our extension ecosystem grows more and more, we simultaneously are
also enforcing more and more policies to have a better experience for
our users and ensure extensions meet a minimum standard. However, at the
same time, it has become increasingly difficult for extension authors to
keep track of what we enforce onto extensions and what specific rules
apply to their extension.

Thus, this PR splits out the publishing guidelines out of the
`Developing Extensions` page in an effort to make it easier to go
through our requirements and make it harder to miss those. This also
paves the way for more detailed publishing prerequisites, so that both
authors can more quickly see what applies to their extension as well as
reviewers having easier ways to point authors to what they are missing.

Release Notes:

- N/A

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
…ries#61769)

# Objective

- There was no way to copy a cell's or a column header's text out of the
CSV preview table (at all).

## Solution

- Right-clicking a table cell now copies its full content to the
clipboard; the cell tooltip shows the content plus a "Right click to
copy content" hint.
- Right-clicking a column header name copies the column name to the
clipboard, with the same tooltip pattern ("Right click to copy column
name").

## Testing

- Right-click a cell: content is copied, tooltip shows the hint.
- Right-click a column header: column name is copied, tooltip shows the
hint.

## Demo

<img width="994" height="241" alt="image"
src="https://github.com/user-attachments/assets/827a0356-e152-4bfd-84ea-5745e638f13c"
/>


## 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

Release Notes:

- Added copy-to-clipboard on right-click for CSV preview cells and
column headers
…ed-industries#61997)

# Objective

Fixes zed-industries#60192
Closes zed-industries#62308

`editor: align selection` lines cursors up by their buffer column, and
that column counts bytes. If a multi-byte character sits before the
cursor, the byte column is larger than the position the cursor is
actually drawn at, so the row gets padded with the wrong number of
spaces.

The issue reports it with `←` (3 bytes) and `π` (2 bytes):

```
a ← 1  # one
bc ← π  # two
```

Put a cursor on each `#`, run the action, and the result is still
misaligned:

```
a ← 1    # one
bc ← π  # two
```

This is not the columnar selection bug fixed in zed-industries#57097. That one was
`select_columns` in `selection.rs`, where the output is a selection
range. This one is `align_selections` in `editor.rs`, where the output
is inserted spaces, so the same byte-column assumption was left behind
in a second place, and fixing it here needs a rounding step that the
first fix did not.

## Solution

Measure each cursor by its x offset in the laid-out display row
(`DisplaySnapshot::x_for_display_point`), take the target for a column
as the furthest x across the rows, then turn the difference into whole
spaces by dividing by the advance width of `' '`. The offset that
carries into later columns becomes an x offset instead of a column
count.

The display map has already expanded tabs by the time the row is laid
out, so a leading tab now counts as its expanded width instead of as a
single byte.

Two things I would look at first in review:

- The division rounds instead of truncating. The x offsets are built by
repeated float addition, so a gap that should be exactly three spaces
can arrive as 2.9999998, and truncating inserts two.
- The function returns early if the space advance is missing or zero.
Dividing by zero gives `inf`, which saturates to a huge `u32` and then
tries to allocate that many spaces.

I did not add any public items and did not touch `selection.rs`.

## Testing

`cargo test -p editor align` on Windows: 6 passed, 0 failed. That is the
new test plus the two existing `align_selections` tests, which I did not
change and which still pass.

`test_align_selections_with_multibyte_chars` covers the repro from the
issue, a second column whose offset has to carry past a multi-byte
character in the first, a leading tab, a non-BMP character, and a case
where multi-byte characters sit after the cursors and nothing should
move.

I also checked that the test catches the bug rather than just passing:
reverting the change in `editor.rs` and keeping the test makes it fail
on the repro, inserting four spaces where three are right. Putting the
change back makes it pass. The two older align tests pass either way,
since they are pure ASCII.

What I have not covered:

- Wide CJK characters, combining marks, and ZWJ clusters. These should
be right by construction, since the code measures advances rather than
counting characters, but I have no tests for them. The headless text
system behind `gpui::test` gives every BMP character the same advance,
so a test there would assert the test double's behavior rather than the
real renderer's.
- Proportional fonts. Aligning with inserted spaces cannot be exact when
glyph widths vary. The code rounds to the nearest whole space.
- Soft-wrapped rows. I measure x from the start of the wrapped row but
still group cursors by buffer row, so two cursors on one buffer row that
sit either side of a wrap boundary get measured from different origins,
and the carried offset crosses that boundary as if they shared one. The
old byte-column code did not have that particular failure. I left it
alone because fixing it is a different change, but I would rather flag
it than have you find it.
- I work on Windows and have no macOS machine. The arithmetic is
platform independent, so I do not expect a difference, but I have not
checked.

To try it: paste the two lines from the issue, put a cursor on each `#`
with `editor: select next`, then run `editor: align selection`. The two
`#` should line up.

## Self-Review Checklist:

- [ ] 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 `editor: align selections` misaligning rows and Vim `ctrl-d` /
`ctrl-u` / `ctrl-f` leaving the cursor behind on lines with multi-byte
characters or tabs.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
According to the docs these fields can be null:

https://platform.claude.com/docs/en/api/models/list#model_info.max_input_tokens

https://platform.claude.com/docs/en/api/models/list#model_info.max_tokens

Instead of failing the whole request, we filter those models out since
we can't handle models without knowing their context window size. Seems
like ClaudeCode follows the same approach.

Release Notes:

- N/A
Another discovery during search-on-type work.

Follow-up to zed-industries#19298 and
zed-industries#19846

With the `"soft_wrap": "editor_width"`, I should have no text contents
overflowing the editor width.

Before (scrollbar shown incorrectly):
<img width="2032" height="1162" alt="before"
src="https://github.com/user-attachments/assets/8b89ba6d-f98b-4ea0-89f2-8a22e968c438"
/>

After:
<img width="2032" height="1162" alt="after"
src="https://github.com/user-attachments/assets/93f62c2b-4981-48ae-aebd-8b0021348787"
/>


Release Notes:

- Fixed invisible symbol replacement width calculation
…62577)

# Objective

DeepSeek has released the GA version of its V4 Pro model, and added a
new low reasoning effort level for both V4 Flash and V4 Pro. We need to
update Zed's DeepSeek provider to sync with this update.

Reference: https://api-docs.deepseek.com/updates/

## Solution

Added a new Low reasoning effort level for DeepSeek models.

## Testing

Built and ran locally. Screenshots with this change are attached in the
Showcase section.

## 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
After this change:

<img width="639" height="169" alt="flash"
src="https://github.com/user-attachments/assets/5521f6fe-ced9-4842-8783-24c532bf66f6"
/>

<img width="640" height="181" alt="pro"
src="https://github.com/user-attachments/assets/0293d4a2-03f8-41e1-8a3e-31efce9dea17"
/>

---

Release Notes:

- Added support for low reasoning effort for DeepSeek V4 Flash and V4
Pro
)

Closes zed-industries#21054

## Summary
• make the JetBrains base keymap use subword motions for
`Alt+Left/Right` and `Shift+Alt+Left/Right` in editors
• keep Zed's default keymaps and the underlying `word`/`subword`
primitives unchanged
 • document word vs. subword navigation in the key bindings docs
• document the JetBrains default in the IntelliJ, WebStorm, PyCharm, and
RustRover migration guides

## Testing
 • `./script/check-keymaps`
 • `cargo fmt --all -- --check`
 • `./script/clippy -p editor`
• `cd docs && pnpm dlx prettier@3.5.0 src/key-bindings.md
src/migrate/intellij.md src/migrate/webstorm.md src/migrate/pycharm.md
src/migrate/rustrover.md --check`

Related to zed-industries#12816 and zed-industries#34090, but does not actually address the
configurable word separators or broader subword semantics. Intentionally
scoped to JetBrains keymap defaults & docs.

Release Notes:

- Improved JetBrains keymap behavior by adding CamelHump-style subword
navigation in editors.

---------

Co-authored-by: Tom Houlé <tom@tomhoule.com>
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Confirming an inline rename after deleting the entire symbol name or
entering only whitespace currently submits an invalid rename request to
the language server. This can remove the symbol text instead of leaving
the source unchanged.

Treat empty and whitespace-only replacements as successful no-ops after
dismissing the inline rename UI. Returning a completed task also
consumes the confirmation action, preventing Enter from propagating back
into the editor. Non-blank rename behavior remains unchanged.

The regression test covers both empty and whitespace-only rename fields,
verifying that no LSP rename request is sent and the original buffer
remains intact.

Release Notes:

- editor: Fixed confirming a blank symbol LSP-rename modifying the
source code
# Objective

The MVP version of CSV preview is ready. However it's trivial to extend
it to TSV & other formats.

## Solution

This PR does exactly that - switching from CSV only to any tabular data
(TSV/CSV/PSV/SSV).
1. added `tsv`/`psv`/`ssv` support
2. renamed action/eye button & crate
3. added `.psv`/`.ssv` types to use database icon (similar to
`csv`/`tsv`)
2. Added `Table` svg icon (was previously missing) so preview is not
longer using book icon (from markdown preview).

> NOTE: Crate renaming will be done separately (as it's mechanical work
& I don't want to mix it with logic changes)

## Testing

Opened csv/tsv/psv/ssv files in peview

## 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

PSV/SSV file formats icon

| Before | After |
| --- | --- |
| <img width="141" height="136" alt="image"
src="https://github.com/user-attachments/assets/ff5ec1a2-10e3-4363-a467-d535c7f621c0"
/> | <img width="143" height="135" alt="image"
src="https://github.com/user-attachments/assets/f4a85276-beee-4d3e-bc59-319c4fc8812c"
/> |

Change namespace for actions (`csv` -> `tabular data`)

| Before | After |
| --- | --- |
| <img width="551" height="150" alt="image"
src="https://github.com/user-attachments/assets/f7b79a7f-b300-4d14-8565-b42b3bcb11c4"
/> | <img width="558" height="152" alt="image"
src="https://github.com/user-attachments/assets/be9dcc54-51a4-4736-9539-172fecabdf6d"
/> |


Update parser & detection logic to support preview for TSV/PSV/SSV

| Before | After |
| --- | --- |
| <img width="470" height="287" alt="image"
src="https://github.com/user-attachments/assets/d0222bd1-91a7-46e0-b4da-76be0642bf51"
/> | <img width="541" height="275" alt="image"
src="https://github.com/user-attachments/assets/3c4d237a-4956-46ad-b7d6-3a8782b41888"
/> |


Introduce table svg icon

| Before | After |
| --- | --- |
| <img width="349" height="66" alt="image"
src="https://github.com/user-attachments/assets/bd7999ef-516f-43d1-a0e6-50055c1c3bed"
/> | <img width="331" height="50" alt="image"
src="https://github.com/user-attachments/assets/fc534921-0c15-421c-b046-8c5967178d24"
/> |


---

Release Notes:

- N/A or Added/Fixed/Improved ...
…stries#62496)

GPUI currently splits performance instrumentation across several Cargo
features and runtime controls. Task profiling, frame-duration
histograms, input-latency histograms, and benchmark frame timing
therefore follow separate code paths despite measuring related parts of
the same UI work.

This PR consolidates those systems under the `profiler` Cargo feature.
The `bench` feature now enables `profiler`, aggregate frame and
input-latency histograms remain active whenever profiling is compiled
in, and `set_trace_enabled` controls whether individual task timings and
per-frame draw and presentation records are retained.

The change also introduces a single per-window profiler that owns the
begin and end state for input dispatch, drawing, and presentation, and
routes window action-handler timing through the existing aggregate
action tracker. Draw and presentation records reuse the same timestamps
and computed intervals as the aggregate histograms, avoiding duplicate
clock reads. Benchmark trace scopes are reference-counted so overlapping
measurements cannot disable tracing while another measurement still
needs it.

This does not change hang detection directly. It establishes the common
profiling foundation needed to correlate slow or delayed frames with
actions and foreground or background tasks. Better attribution should
make it easier to find and prevent responsiveness regressions.

Release Notes:

- N/A

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Extract parts of `platform_macos` to `gpui_apple` to be used as a shared
crate between `gpui_macos` and a future `gpui_ios` for iOS/iPadOS apps.

Release Notes:

- N/A
Closes zed-industries#42583

Adds more tooltip entries and `editor::BlameRevision`,
`editor::BlamePreviousRevision` actions to use.
Started to highlight gutter blame entries that belong to currently
annotated commit.


https://github.com/user-attachments/assets/ba754e0b-6431-407c-8d79-2f8b0324fde1


Release Notes:

- Supported blaming parent revisions
…2651)

ChatGPT subscription model availability is determined by the
authenticated Codex backend and can vary by account. The provider
currently exposes a bundled static list and defaults to GPT-5.6 Sol, so
users can be offered a model that their ChatGPT account subsequently
rejects.

This change fetches the account-scoped Codex model catalog after loading
stored credentials and after sign-in. Requests use the existing OAuth
token, ChatGPT account ID, Zed originator, and the Zed client version.
Picker-visible models are ordered by the server's priority, and the
returned metadata drives model names, context windows, image support,
reasoning levels, and Fast Mode support.

The bundled list remains available before discovery and when discovery
fails. A failed refresh preserves the last usable catalog and surfaces
the failure in provider settings, while generation checks prevent a
response for an older account or request from replacing newer state.
Model discovery uses the same five-second timeout as Codex so a stalled
catalog endpoint cannot indefinitely delay authentication. Zed's
language model provider now derives its provided, default, recommended,
and fast models from that resolved catalog.

Testing performed:

- `cargo nextest run -p openai_subscribed`
- `cargo nextest run -p language_models`
- `./script/clippy -p openai_subscribed -p language_models --lib`
- `cargo fmt --all -- --check`
- `git diff --check`

Release Notes:

- Fixed ChatGPT subscription accounts offering models that are not
available to them.
…es#62652)

OpenAI-compatible providers currently cannot reuse Zed's OpenAI Chat
Completions transport unless they also adopt the exact OpenAI request
and response types. OpenRouter therefore maintained its own copy of
request construction, authentication, status handling, response reading,
and server-sent event framing.

This change extracts that mechanical transport into two provider-neutral
functions in `open_ai`: one for streaming requests and one for
non-streaming requests. They accept any serializable request envelope,
preserve custom headers and provider names, return untyped JSON for
provider-specific decoding, and retain typed failures for serialization,
request construction, HTTP transport, response reading, and
deserialization. The existing OpenAI entry points remain as
compatibility wrappers, so existing callers keep the same API and
behavior.

The abstraction deliberately stops at the wire boundary. OpenRouter
continues to own its request and response schemas, attribution headers,
routing controls, cache placement, and API-specific error
interpretation. It now adapts the shared framed stream into those
OpenRouter types instead of implementing a second HTTP and server-sent
event stack.

Moving OpenRouter onto the shared path also requires the ordinary Chat
Completions schema and event mapper to preserve compatible metadata that
OpenRouter already emits. This includes structured reasoning details
needed for replay, fragmented reasoning accumulation, prompt-cache read
and write usage, and thought signatures attached to tool calls. The
stream exposes `[DONE]` explicitly rather than treating it as
indistinguishable from an unexpected end of the response body.
OpenRouter's routing session identifier is hashed before transmission so
Zed's internal thread identifier is not exposed.

The diff is larger than the extracted transport alone because the shared
API is additive, the compatibility metadata must be represented in the
common wire types and event mapper, and the provider-specific adapter
remains intentionally independent. Roughly four hundred added lines are
focused transport, metadata, error-classification, attribution, caching,
and privacy tests. The provider-level OpenRouter implementation becomes
smaller while preserving its existing behavior.

Testing performed:

- `cargo test -p open_ai`
- `cargo test -p open_router`
- `cargo nextest run -p language_models open_router`
- `cargo check -p edit_prediction -p edit_prediction_cli`
- `cargo fmt --all -- --check`
- `./script/clippy -p open_ai -p open_router -p language_models -p
edit_prediction_cli`
- `cargo machete`

Release Notes:

- Improved OpenRouter reasoning continuity and request privacy.

---------

Co-authored-by: Eric Holk <eric@zed.dev>
…ustries#62259)

Some context behind this change: I’ve been meaning to look into this
because I kept running into this crash when working on
[other](zed-industries#61040) fixes.
Everything worked fine in dev builds, right up until you tried to create
a new Agent Thread using an ACP adapter. The crash reports in this
instance were throwing me off: I was seeing different things each time.

So, I had Fable look into this. It did so by binary-searching the
minimum thread stack on which a probe replicating Zed’s exact handler
chain can dispatch one message. Full methodology, probe source, and raw
numbers can be found in [this
gist](https://gist.github.com/yeskunall/2ac2b00f51389d9388d607974f6f8a04).
The results of the probe are as follows:

| SDK | Minimum stack (dev profile) | vs. 512 KiB GCD budget |
|---|---|---|
| 1.3.0 | 409,600–413,696 B | fit, ~100 KiB headroom |
| 2.0.0 | 507,904–512,000 B | entire budget before runtime overhead |

The oversized frames are monomorphized into `agent_servers`, not the SDK
crate -- a `[profile.dev.package]` opt-level override on
`agent-client-protocol` does **not** fix this (see gist), and optimized
builds collapse the frames entirely, which is why only dev builds
crashed. It found that the real signature is `fault_address ==
stack_pointer` on a `com.apple.root.default-qos` thread inside the ACP
dispatch specialization, which I then had it verify across six local
`.ips` reports. It seems in zed-industries#61570, we pushed the dispatch chain past
the GCD budget, explained further below:

`AcpConnection::stdio` polled the ACP client connection future via
`background_spawn`, which on macOS executes runnables on
[GCD’s](https://developer.apple.com/documentation/DISPATCH) global-queue
workers. Those threads have kernel-fixed, unconfigurable [512 KiB
stacks](https://github.com/apple-oss-distributions/libpthread/blob/42d026df5b07825070f60134b980a1ec2552dfee/kern/kern_internal.h#L154).
In unoptimized builds, the SDK’s chained-handler dispatch needs **~0.5
MiB of stack per inbound message** (again, see linked gist), so the
first message overflows the guard page and takes the process down.

Therefore, this 512 KiB constraint is **macOS-only**. Linux doesn’t use
GCD -- GPUI [spawns its own `std::thread`
workers](https://github.com/zed-industries/zed/blob/82878540b5410b288a2c92cb9ee5675533e4d807/crates/gpui_linux/src/linux/dispatcher.rs#L39)
([2 MiB Rust
default](https://github.com/rust-lang/rust/blob/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/thread/unix.rs#L26)).
Windows uses [the OS thread
pool](https://github.com/zed-industries/zed/blob/82878540b5410b288a2c92cb9ee5675533e4d807/crates/gpui_windows/src/dispatcher.rs#L68),
which [inherits the executable’s stack
reserve](https://github.com/MicrosoftDocs/sdk-api/blob/4502fff176b3b56beddb6a63c9f980377b11ba9b/sdk-api-src/content/threadpoolapiset/nf-threadpoolapiset-setthreadpoolstackinformation.md?plain=1#L58)
-- [1 MB linker
default](https://github.com/MicrosoftDocs/win32/blob/2eb6588c6703d31599285bbb06563c3d41b57590/desktop-src/ProcThread/thread-stack-size.md?plain=1#L17),
but Zed already bumps it to 8 MiB in
[crates/zed/build.rs:88](https://github.com/zed-industries/zed/blob/82878540b5410b288a2c92cb9ee5675533e4d807/crates/zed/build.rs#L88)
(see [TODO
comment](https://github.com/zed-industries/zed/blob/82878540b5410b288a2c92cb9ee5675533e4d807/crates/zed/build.rs#L87)).

---

Release Notes:

- N/A
# Objective

Project search sends one candidate per file to its worker pool, and each
one
carried an owned `Snapshot`. Every field of `Snapshot` is cheap to clone
except
`always_included_entries`, a `Vec<Arc<RelPath>>` holding one entry per
always-included file.

With a broad file_scan_inclusions such as **/*, that vector holds an
entry per file in the project, so cloning it once per file made search
O(files²).

Partially addresses zed-industries#38799 (still needs to fix the huge memory usage and
the occasional stutters) .

## Solution

Share the snapshot behind an `Arc` instead, the consumer only reads
`id()`, `abs_path()`
and `root_name()`, so nothing needs an owned copy.

## Testing
Using the [linux kernel repo](https://github.com/torvalds/linux), i
searched for `vmx_l1d_should_flush
` and `netif_rx` and its at least 60x faster on 5950x. 
with `file_scan_inclusions: ["**/*"]`


Release Notes:

- Fixed project search being very slow on projects that set a broad
`file_scan_inclusions`
…ies#62665)

# Objective

- prevent branch name overflow in git details pane
- Fixes zed-industries#62526 

## Solution

- set min width
- add tooltip for readability

## Testing

- manual testing

## Self-Review Checklist:

- [X] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [X] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable

## Showcase
### before
- 
<img width="670" height="205" alt="image"
src="https://github.com/user-attachments/assets/26716b50-6f09-40c1-bec5-d78bd913d4ec"
/>

- No tooltip

### After
- 
<img width="499" height="203" alt="image"
src="https://github.com/user-attachments/assets/3eee21e8-f9e8-4c30-a21d-0c23bf25c9de"
/>

- Tooltip: 

<img width="609" height="364" alt="image"
src="https://github.com/user-attachments/assets/822d784d-889e-4d26-b8e6-de46f8206569"
/>

---

Release Notes:

- N/A or Added/Fixed/Improved ...
Follow-up to zed-industries#46337, same fix as zed-industries#48280.

`title_bar` tests enable `remote/test-support`, which adds
`RemoteConnectionOptions::Mock`. But without
`recent_projects/test-support`, the match arms for that variant aren't
compiled, causing a non-exhaustive match error when testing the crate in
isolation:

```
error[E0004]: non-exhaustive patterns: `&RemoteConnectionOptions::Mock(_)` not covered
    --> crates/remote_connection/src/remote_connection.rs:233:76
```

CI doesn't catch this because `collab` and `sidebar` enable
`recent_projects/test-support` during workspace-wide tests.

Adding `remote_connection/test-support` instead isn't enough — that just
moves the same error into `recent_projects`.
`recent_projects/test-support` covers both.

Release Notes:

- N/A
…2685)

Follow-up to zed-industries#62658

The problematic field is not needed at all in the snapshot, as can be
constructed before starting the scanner — moreover, the field had
accumulated more and more paths between rescans, leaking memory.

Now, we spend more time traversing the entire tree between rescans, but
that happens for rescans only which should be relatively rare?

Release Notes:

- N/A
…tem (zed-industries#62602)

Closes zed-industries#59001

Saving a notebook wrote the file with
`project.fs().atomic_write(abs_path, ...)`. `Project::fs()` is always
the client's own filesystem, so for a remote project the remote path was
resolved against the local machine: on Windows the drive letter got
prepended and the atomic-write temp file used a backslash, producing
`C:/data/project/src_example\.tmpPuzw3d3` and `os error 3`. The same
thing fails on macOS/Linux clients with `os error 2`.

Both `save` and `save_as` now go through the project's buffer machinery
instead: open the buffer for the notebook's `ProjectPath`, set its text
to the serialized notebook, then `save_buffer` / `save_buffer_as`.
Writes are routed over the remote connection for remote projects, and
the open buffer stays in sync locally.

`save_as` also updates the item's project path and entry id, since
`save_buffer_as` moves the buffer to the new path and otherwise the next
save would write back to the old file.

Added a test that edits a cell, saves, and checks that the notebook
buffer held by the project reflects the saved file. It fails against the
old implementation.

Release Notes:

- N/A

---------

Co-authored-by: Finn Evers <finn.evers@outlook.de>
…ed-industries#61923)

## Objective

Right-clicking a buffer header in a multibuffer showed a context menu
whose item spacing did not match other context menus. The menu is drawn
via a deferred draw, which inherits the editor's text style stack, so
its line height followed `buffer_line_height` instead of the default UI
line height.

This is the same root cause as zed-industries#24504, which zed-industries#25172 fixed for the
editor's mouse context menu and completion popovers. The buffer header
menu was a remaining call site.

## Solution

`ContextMenu` now applies the default (`comfortable`) line height itself
in `render`, next to its existing rem size and font family
normalization, so menus render the same regardless of where they are
opened from. This fixes the all workarounds and the need for them too:
the workaround in `layout_mouse_context_menu` is removed, and the buffer
header ends up needing no changes at all.

The completions and code actions popovers keep their override in
`element.rs`: they are not `ui::ContextMenu`s and compute their sizes
with eager `window.line_height()` reads while being built, so styling on
the elements they return cannot cover them. Migrating them could be a
follow-up.

## Testing

- `cargo check --workspace` passes, `./script/clippy` on the touched
crates passes.
- Manual: set `"buffer_line_height": "standard"` (or any extreme custom
value to see it better), open a multibuffer (e.g. project search),
right-click a buffer header, and compare the menu with another context
menu (e.g. a tab's) — spacing matches. The editor's mouse context menu,
which lost its own override, renders as before, and with default
settings there is no visual change anywhere.
- Tested on macOS, change is platform-independent styling.

## 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 (visual styling fix; menu
text styles have no existing test coverage)
- [x] Performance impact has been considered and is acceptable

## Showcase

Regular context menu:
<img width="425" height="164" alt="A context menu elsewhere in the app,
showing normal item spacing"
src="https://github.com/user-attachments/assets/1fc13981-b394-444f-883a-ce3ef462c386"
/>

Before:
<img width="425" height="164" alt="Buffer header context menu before the
fix, with tighter item spacing following the custom buffer_line_height"
src="https://github.com/user-attachments/assets/9774076c-7e0c-41dd-b54f-53de58b24336"
/>

After:
<img width="425" height="164" alt="Buffer header context menu after the
fix, with item spacing matching other context menus"
src="https://github.com/user-attachments/assets/ae76e37c-8e39-474c-8a5e-e229e69173fb"
/>

---

Release Notes:

- Fixed the file header context menu in multibuffers not matching other
context menus' spacing when a custom `buffer_line_height` is set.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Local benchmark shows this speeds it up by at least 30% and is
definitely more reasonable to have like this than compared to iterating
over a list for every given char.

Release Notes:

- N/A
…stries#62711)

`ThreadView::regenerate` does `thread.rewind()` which de-focused the
message editor mid-flight causing the zoomed panel to disappear.

* workspace: Keep zoomed panels open when window focus is lost

Commit adds a test + tweaks a default, generic, fallback to be more
lenient: instead of focusing the workspace (and hiding all panels right
away), try to fall back to whatever panel open

* gpui: Restore focus to nearest surviving ancestor when focus is lost

Commit tries to push it down to a library level and add a way to fall
back to closest ancestor that's still visible with the focus instead.


Release Notes:

- Fixed the zoomed agent panel closing unexpectedly on rewind
The early return made the call a silent no-op, so a test could deactivate a
window that was never active and then assert behaviour it had not exercised.
Every existing caller already activates first.
@butvinm
butvinm force-pushed the guard-vacuous-deactivation branch from 27b3b55 to 73ecb97 Compare August 16, 2026 20:42
@butvinm

butvinm commented Aug 16, 2026

Copy link
Copy Markdown
Owner Author

Closing: purely preventive. With the assert live, all 1662 tests across editor, workspace, agent_ui and project_panel pass, so no current test deactivates an inactive window - every caller activates first, usually via Workspace::test_new. And of the two ways a deactivation test can be vacuous, this guards the one that has never occurred; the one that actually bit zed-industries#61852 was 'nothing focused', which this does not catch. Branch kept locally as backup/guard-vacuous-deactivation-2026-08-16 if it is ever worth revisiting.

@butvinm butvinm closed this Aug 16, 2026
@butvinm
butvinm deleted the guard-vacuous-deactivation branch August 22, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.