1a6b37d367a36bbb837291762b5e6f74d7e6768a
31734
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
da7d444cab |
google_ai: Add Gemini 3.7 Flash (#62670)
Follow-up to #62010, which added Gemini 3.6 Flash. Google released Gemini 3.7 Flash on August 13, 2026. It keeps the 1 million token context window and the 64k output limit, and supports thinking. Unlike 3.5 and 3.6 Flash, it does not accept `thinking_level: MINIMAL` (the API returns a validation error). So it exposes Low, Medium and High, defaulting to Medium, and `disabled_thinking_level` in `completion.rs` returns Low for it instead of Minimal when the user turns thinking off. The provider builds its model list from `google_ai::Model::iter()`, so adding the enum variant is enough for it to show up in the model dropdown. Release Notes: - Added Gemini 3.7 Flash to the Google AI models |
||
|
|
3d5fb8133a |
anthropic: Preserve request context during explicit compaction (#62745)
Explicit compaction currently removes tool definitions before sending the request. That changes the prompt-cache prefix and can lower the effective input size below Anthropic's minimum compaction trigger, causing the request to complete without producing replacement context. Keep tool definitions in explicit compaction requests while setting `tool_choice` to `none`, preserving the input context without allowing tool calls. Also append a user turn when the conversation ends with an assistant message, since current Anthropic models reject that shape as unsupported assistant prefill. Testing: - `cargo test -p anthropic` - `cargo fmt --check` - `./script/clippy -p anthropic` Release Notes: - N/A |
||
|
|
74247e797e |
sidebar: Make project reordering key-bindable (#62695)
# Objective - The sidebar already supports moving project groups through its **Move Up** and **Move Down** context-menu entries, but those entries use callbacks that cannot be referenced from `keymap.json`. Moving a project several positions therefore requires reopening the menu for every step. - Follow-up to #57448. Related to #61647. ## Solution - Add `multi_workspace::MoveProjectUp` and `multi_workspace::MoveProjectDown` actions. The handlers resolve the active project group and delegate to the existing `MultiWorkspace` reordering methods, keeping ordering and persistence behavior unchanged. - Associate the actions with the existing context-menu entries so configured shortcuts are shown alongside the menu commands. The menu callbacks still operate on the project that was clicked. ## Testing - Added a GPUI test that dispatches both actions and verifies that the active project group moves in the expected direction and remains unchanged at list boundaries: - `cargo test -p workspace test_move_active_project_group_actions -- --nocapture` - Manually verified on macOS with an isolated Zed user-data directory and three project folders: - Assigned custom shortcuts to both actions in `keymap.json`. - Confirmed that the active project moves up and down in the sidebar. - Ran formatting, compilation, and lint checks: - `cargo fmt --all -- --check` - `cargo check -p sidebar` - `./script/clippy -p workspace -p sidebar -p gpui_platform --features gpui_platform/runtime_shaders` ## 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>Move projects with custom keybindings</summary> https://github.com/user-attachments/assets/09432817-318b-484e-b630-a6012e9599cd </details> --- Release Notes: - Sidebar: Added key-bindable actions for moving projects up and down. |
||
|
|
5b85565d93 |
gpui: Make inactive frame throttling configurable (#62628)
# Objective I am building an [app](https://github.com/nolight132/sonora) with GPUI, and the current animation throttling implementation does not quite meet its requirements. I needed the window to stay at a smooth framerate when unfocused to display lyrics, which was not possible at the time without modifying GPUI’s frame scheduling behavior. I understand that this is not a problem for Zed, but I believe making this behavior a field in `WindowOptions` could be beneficial for other programs going forward. ## Solution Added a field to `WindowOptions` struct which controls the minimum interval between animation frames while the window is inactive (documented). Kept the default value GPUI currently uses. ## Testing - Ran `gpui/src/examples/animation.rs` with different presets - works as expected. Zed compiles. One thing worth noting: this setting does not guarantee the window refreshes at this exact interval, as frames are still paced by the compositor. For granular FPS control, a helper function is needed. I have decided to keep it simple and use the existing logic. - Tested on NixOS x86_64, Niri. ## 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 (the default didn't change, tests still pass) - [x] Performance impact has been considered and is acceptable (no performance impact unless explicitly set) ## Showcase Before (unfocused): <img width="1280" height="802" alt="image" src="https://github.com/user-attachments/assets/e3302c1d-4f4a-4503-96a2-0bf24e28096c" /> After (unfocused with `inactive_frame_interval` set to 16ms): <img width="1450" height="972" alt="image" src="https://github.com/user-attachments/assets/1183adf1-2da1-42d5-8e97-f4ad7a31b783" /> --- Release Notes: - Added `WindowOptions::inactive_frame_interval` for configuring animation frame throttling on inactive GPUI windows. |
||
|
|
c772f94985 |
sidebar: Wrap import onboarding title when the panel is narrow (#62737)
Narrowing the agent sidebar clips the import-threads banner title mid-word. The title now wraps instead of overflowing the close button. <img width="212" height="279" alt="Screenshot 2026-08-16 at 11 25 26 PM" src="https://github.com/user-attachments/assets/03e20b9d-ea29-4872-a4c1-f364509ddacb" /> Release Notes: - Fixed the agent sidebar import-threads banner clipping its title when the panel is narrow |
||
|
|
c984c41b54 |
project_panel: Make the window deactivation test actually deactivate (#62724)
Follow-up to #61852. The regression test I added there passes with or without the fix. The test creates the panel with `ProjectPanel::new` but never calls `workspace.add_panel(...)`, so the panel is never rendered and its filename editor never holds window focus. Deactivating the window then blurs nothing, the project panel's `Blurred` handler never runs, and the assertion holds trivially. Add the panel to the workspace so it renders and its filename editor takes focus, and assert that the editor is focused before deactivating, so the test fails at an explanatory precondition rather than silently going vacuous again. Verified by running the new precondition without `add_panel`: it fails, because the workspace's `on_focus_lost` fallback (`crates/workspace/src/workspace.rs:1667`) reclaims focus from an editor that was never rendered into the dispatch tree. ## Suggested .rules additions > A GPUI test that depends on focus must put the view somewhere it can actually be focused. Constructing a panel with `ProjectPanel::new` and friends does not render it, so its editors never hold window focus and every focus or blur assertion passes vacuously. Add it with `workspace.add_panel(...)`, and assert the intended editor `is_focused` before exercising blur. Release Notes: - N/A |
||
|
|
a3bf217dba |
Improve explicit compaction for Anthropic models (#62139)
Explicit compaction (`LanguageModel::compact`) was previously implemented only for OpenAI-routed cloud models, which use a dedicated compact operation proxied through `/completions/compact`. Anthropic models only compacted automatically when a request's `compact_at_tokens` trigger was crossed, leaving consumers without a provider-backed way to request compaction immediately. Anthropic has no compact-on-demand operation, but the `compact_20260112` context-management edit provides the necessary pieces: the lowest trigger the API accepts, 50,000 input tokens, combined with `pause_after_compaction`, which stops the response after the compaction block. Explicit compaction requests remove tools so the internal summarizer must produce replacement context while retaining Anthropic's default summarization prompt. The resulting readable summary, optional opaque provider state, and usage are collected consistently. This implements explicit compaction for both direct and hosted Anthropic models. Hosted requests use the normal `/completions` endpoint; gateway support for forwarding the compaction fields landed in zed-industries/cloud#3216. Models expose the 50,000-token minimum so callers can disable explicit compaction below the provider's floor. Calls made below that floor still fail if the stream produces no finalized compaction context. The existing OpenAI compact operation is moved into a provider-specific helper without changing its request, endpoint, response handling, or provider-state ownership. Testing: - `cargo nextest run -p anthropic -p language_models_cloud -p language_models` - `./script/clippy -p anthropic -p language_model -p language_models_cloud -p language_models` - `cargo fmt --all --check` - `git diff --check` Release Notes: - N/A --------- Co-authored-by: Anant Goel <anant@zed.dev> |
||
|
|
75c80abb31 |
git: Decode non-UTF-8 blobs for project diffs (#60821)
## Summary Fixes #56449. Related to #16965. Zed’s Git panel and Project Diff build UI diffs from `language::Buffer` diff bases loaded through the Git backend. Git blob loading previously converted bytes with `String::from_utf8(...).ok()`, so legacy-encoded blobs were treated as missing and the whole worktree file appeared newly added. This follows the same encoding path used for worktree buffers: - move shared byte decoding and encoding into `language` - keep Git blob, revision, and index APIs byte-oriented with `Vec<u8>` - decode diff bases and index contents in `GitStore`, where `language::Buffer`s are created - encode index writes using the open buffer’s encoding and BOM so partial staging does not rewrite the file as UTF-8 - keep worktree loading and saving on the same shared implementation Regression coverage includes Windows-1251 decoding/encoding, UTF-8/UTF-16 BOM preservation, raw Windows-1251 Git blob loading, and a `BufferDiffSnapshot` assertion that a one-line CP1251 edit produces one modified-line hunk instead of a full-file rewrite. This does not run Git `textconv` commands. It fixes the reported legacy-encoding case without executing repository-configured commands or modifying working files on disk. ## Testing - `cargo test -p language file_content::tests --locked` - `cargo test -p git repository::tests::test_load_revisions --locked` - `CARGO_INCREMENTAL=0 cargo test -p project git_store::tests::test_decode_git_text_windows_1251_one_line_change --locked` - `CARGO_INCREMENTAL=0 cargo test -p project --test integration test_restaging_hunk_after_optimistic_unstage --locked` - `CARGO_INCREMENTAL=0 cargo check -p project --tests --locked` - `CARGO_INCREMENTAL=0 cargo check -p git_ui --tests --locked` - `cargo fmt --all --check` - `git diff --check` ## Suggested .rules additions - N/A Release Notes: - Fixed Git panel and Project Diff rendering for legacy-encoded text files whose Git blobs are not valid UTF-8. --------- Co-authored-by: Cole Miller <cole@zed.dev> |
||
|
|
8ecd20779c |
openai_subscribed: Request ungated account model catalog (#62729)
The ChatGPT Codex models endpoint interprets `client_version` as a Codex CLI compatibility version and filters models whose `minimal_client_version` is newer. Zed was passing its unrelated application version, so catalog contents depended accidentally on how Zed's release number compared with Codex's version sequence. A read-only sweep against the authenticated endpoint showed that omitting the parameter returns HTTP 400, ordinary versions receive the expected compatibility-filtered subsets, and `0.0.0` is a special ungated sentinel. The `0.0.0` response had the same model set, ETag, and canonical body hash as current and higher Codex versions, while `0.0.1` returned no models. This moves ownership of that behavior into `openai_subscribed::State`. The normal constructor now always requests the ungated account catalog, and the public constructor that accepted arbitrary host versions is removed so applications cannot accidentally couple model visibility to their own version scheme. The existing initial-load test pins the resulting `client_version=0.0.0` request. Testing performed: - `cargo nextest run -p openai_subscribed` - `cargo nextest run -p language_models openai_subscribed` - `./script/clippy -p openai_subscribed -p language_models` - `cargo fmt --all -- --check` - `git diff --check` Release Notes: - Fixed ChatGPT subscription model discovery to avoid filtering models by Zed's application version. |
||
|
|
9093ccd5d5 |
Recognize .brushrc files as shell scripts (#62720)
Add `.brushrc` to the Shell Script language configuration so [Brush](https://github.com/reubeno/brush) shell configuration files receive shell syntax highlighting. Release Notes: - Added Shell Script language detection for `.brushrc` files. |
||
|
|
d2bbf4a835 |
agent: Add ask_user tool using elicitation forms (#61497)
## Summary Adds a first-party `ask_user` tool to Zed's native agent (`crates/agent`) that lets the agent ask the user a question and get an answer back through a proper **elicitation form** rather than free-form chat text. This is a step towards the interactive-question experience requested in [discussion #48784](https://github.com/zed-industries/zed/discussions/48784) (implement the ACP elicitation spec for agent questions). Zed already renders elicitation forms client-side; this wires the native agent up to that existing rail so the agent can drive single-select and/or free-text prompts. ## What it does The tool takes: - `question` — the prompt shown to the user - `options` — optional list of selectable choices (single-select) - `allow_free_text` — whether the user may type a custom answer instead of picking an option The agent decides the shape of each question: | `options` | `allow_free_text` | Result | | --- | --- | --- | | 2+ | `false` | Single-select only | | 2+ | `true` | Single-select with a free-text "other" field | | empty | `true` | Free-text only | A typed answer takes precedence over a selected option, and the tool always resolves (a cancelled or failed elicitation is reported back to the agent rather than hanging). ## Demo https://github.com/user-attachments/assets/9d438d87-af65-4fa2-b500-b1232007d0a0 ## Implementation - `thread.rs` — new `ThreadEvent::Elicitation(ElicitationRequest)` variant plus `ToolCallEventStream::request_elicitation`, mirroring the existing `prompt_for_decision` permission rail. - `agent.rs` — handles the elicitation event by building a session-scoped `acp::CreateElicitationRequest` and routing it through `AcpThread::request_elicitation`, piping the response back to the tool. - `tools/ask_user_tool.rs` — the tool itself, including schema construction and response extraction. - Registered in the `write` and `ask` profiles and excluded from the tool-permissions setup UI. No client-side UI changes were needed — the existing elicitation form rendering handles it. ## Tests `cargo test -p agent ask_user` — 5 unit tests covering schema construction, validation, and accept/decline/cancel handling. Release Notes: - Added an `ask_user` tool that lets the agent ask the user a question with selectable options and/or free-text input, rendered as an elicitation form |
||
|
|
8fd8efd105 |
git_ui: Fix Trash Untracked Files with many files (#61602)
Release Notes: - Fixed Trash Untracked Files bailing out early with many selected files when trashing one file failed. --------- Co-authored-by: Cole Miller <cole@zed.dev> |
||
|
|
468837a78d |
Merge array settings from extension contributions instead of overwriting (#62686)
Closes https://github.com/zed-industries/zed/issues/62572 Reworks https://github.com/zed-industries/zed/pull/54950 — instead of unconditionally replacing the array with a different one, now does the replacement only when the user settings are set. The rest now merges into the array. Release Notes: - Fixed array merging for extensions case |
||
|
|
3a21e04379 |
Fixed the zoomed agent panel closing unexpectedly on rewind (#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 |
||
|
|
aab84dab21 |
editor: Match invisible character ranges directly (#62708)
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 |
||
|
|
895f438c1a |
editor: Fix buffer header context menu line height in multibuffers (#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 #24504, which #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> |
||
|
|
b99ce02038 |
repl: Save notebooks through the project instead of the local filesystem (#62602)
Closes #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> |
||
|
|
20a95914df |
Remove the problematic data field from the snapshot (#62685)
Follow-up to https://github.com/zed-industries/zed/pull/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 |
||
|
|
bd1a4abe26 |
title_bar: Fix test-support feature mismatch (#62284)
Follow-up to #46337, same fix as #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 |
||
|
|
437fe0f797 |
git_ui: prevent branch name overflow in git details pane (#62665)
# Objective - prevent branch name overflow in git details pane - Fixes #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 ... |
||
|
|
abacaae1cd |
Make search much faster (#62658)
# 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 #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` |
||
|
|
4155155572 |
acp: Poll the client connection future on a dedicated thread (#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](https://github.com/zed-industries/zed/issues/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 #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/2ade98f6a9320b9c7d6e65398fc4c364c367c1bd/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/2ade98f6a9320b9c7d6e65398fc4c364c367c1bd/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/2ade98f6a9320b9c7d6e65398fc4c364c367c1bd/crates/zed/build.rs#L88) (see [TODO comment](https://github.com/zed-industries/zed/blob/2ade98f6a9320b9c7d6e65398fc4c364c367c1bd/crates/zed/build.rs#L87)). --- Release Notes: - N/A |
||
|
|
bb1adf9781 |
agent: Share compatible Chat Completions infrastructure (#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> |
||
|
|
9b05e122be |
openai_subscribed: Discover account-specific models (#62651)
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. |
||
|
|
c1dab7a0d3 |
Support blaming parent revisions (#62614)
Closes https://github.com/zed-industries/zed/discussions/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 |
||
|
|
232eaba704 |
Extract shared Apple renderer from gpui_macos (#62649)
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 |
||
|
|
a55d40ac62 |
gpui: Unify performance tracking under the profiler feature (#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> |
||
|
|
f65b8464f6 |
csv_preview: Evolve into tabular data preview (#60768)
# 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 ... |
||
|
|
a5234566b4 |
editor: Treat blank rename as no-op (#62630)
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 |
||
|
|
6206d48ac5 |
deepseek: Support low reasoning effort for V4 models (#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 |
||
|
|
10190eed88 |
Properly measure invisible character replacement (#62478)
Another discovery during search-on-type work. Follow-up to https://github.com/zed-industries/zed/pull/19298 and https://github.com/zed-industries/zed/pull/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 |
||
|
|
af8d81593a |
anthropic: Filter models with null token limits (#62618)
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 |
||
|
|
dda3143f2c |
editor: Align selections by display position instead of byte column (#61997)
# Objective Fixes #60192 Closes https://github.com/zed-industries/zed/issues/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 #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> |
||
|
|
051140ea11 |
csv_preview: Allow copying cell and column header content (#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
|
||
|
|
03453dae3e |
gpui: Settle benchmark app state between task iterations (#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 |
||
|
|
0d42a77853 |
csv_preview: Make filter unavailability order-independent (#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 |
||
|
|
851bf3d499 |
Make file scanner less eager in non-git-tracked directory trees (#62583)
Fixes https://github.com/zed-industries/zed/issues/35780 Collab schema migration PR: https://github.com/zed-industries/cloud/pull/3422 The corresponding database schema migration has been created in the Cloud repo and applied to the production database. Before, Zed scanned each and every entry in the tree down from the directory it was opened in, except gitignored files and scan exclusions. The approach is unchanged, if Zed detects it was open inside a git repository: e.g. the directory open in Zed contains `.git` directory. For the rest of the projects, 2 optimizations are made: * Limit the depth of file scan traversal. Now, `file_scan_depth` (default `5`) restricts Zed from traversing any directory that has same number or more segments in its file path. Such directories behave similar to gitignored directories: their contents is not available in file finder, project search and project panel, but can be lazily traversed when the directory is expanded (e.g. project panel expands it or a nested file is open by path via terminal, etc.) To indicate that to the users, a status entry is shown firs time the limitation is hit in the project: <img width="858" height="133" alt="image" src="https://github.com/user-attachments/assets/7da6cfbb-98b4-4cc3-bf2a-8902a9597a15" /> * During the scan, any git repositories that are not direct children of the directory open in Zed (depth >= 2), are traversed and indexed normally, but their git metadata is never fetched eagerly. Only when Zed opens a buffer from that repo the git metadata is fetched and applied. All that combined now uses a way more moderate amount of CPU and RAM when opening `~`: <img width="1717" height="368" alt="Screenshot 2026-08-13 at 17 43 53" src="https://github.com/user-attachments/assets/ec83e2a9-f7cc-452b-8eb7-af158284ca4e" /> File scan inclusions and exclusions are considered still for such projects. Set `file_scan_depth` to `0` to enable old behavior. The setting is supported in the project settings, so custom values can be set based on the project's structure. --- Release Notes: - Fixed Zed using a lot of memory and CPU in large, non-git-tracked, directory trees |
||
|
|
fc58ad2226 |
Unify non-Unicode file detection code (#62581)
Closes https://github.com/zed-industries/zed/issues/62464 Closes https://github.com/zed-industries/zed/issues/62212 As a bonus, fixes the project search not working in BOM'd UTF-16 files. Release Notes: - Fixed project search not working in some non-Unicode files |
||
|
|
5178548fb6 |
Make terminal hyperlinks display correctly with changing content (#54884)
- Closes #31866 Currently, `Terminal::alacritty::make_content()` always carries over any existing hovered word. With this PR we now: - *Are more selective*: Only carry forward the hovered word if the terminal grid shape and visible lines have not changed - *Correctly handle a shifting viewport*: If the grid shape and visible lines have not changed, but new lines were added to the terminal we carry the hovered word forward, and adjust the lines of the `word_match` so that the original text remains hyperlinked. Also, this PR relaxes the test for displaying a hyperlink in `TerminalElement::prepaint`. We now display hyperlinks as long as the `hovered_word.id`s from terminal and terminal_view match. Previously we required all fields to be equal, which resulted in the hyperlink flickering when scrolled back with new lines being added. Release Notes: - Terminal: Made hyperlinks display correctly with changing content --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com> |
||
|
|
4476f5c7f6 |
gpui: Allow setting max FPS for Animation (#62579)
title --- Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
9c61384e88 |
helix: Add vim::HelixGotoLine action and bind it to G (#61581)
# Objective Make `G` keybinding in Helix mode work like in Helix and not like in Vim. Fixes https://github.com/zed-industries/zed/issues/61580 ## Solution Helix has two ways to jump to a line by line number. One is the `goto_file_start` command (bound to `gg`) that optionally takes a count to go to that line instead of the start of the file. Zed already supports it as `vim::StartOfDocument`. The other is the dedicated `goto_line` command (bound to `G`) that only does that and nothing else. Zed did not have it. What's worse, the default `"shift-g": "vim::EndOfDocument"` binding leaked from Vim keymap into Helix keymap, which previously made `<count>G` accidentally work in Helix mode for the wrong reason, until https://github.com/zed-industries/zed/pull/59449 fixed the behavior of `vim::StartOfDocument` and `vim::EndOfDocument` actions to match Helix exactly. This broke `<count>G` and exposed that `G` was bound to the wrong action in Helix mode, and the correct one didn't exist. This PR fixes that in the following way: - adds new`vim::HelixGotoLine` action - binds it to `shift-g` in `helix_normal` and `helix_select` modes in the default Vim keymap ## Testing - Unit tests - Manual testing ## 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 behavior of `G` binding in Helix mode and added new `vim::HelixGotoLine` action Signed-off-by: Oleksii Orlenko <alex@aqrln.net> |
||
|
|
3ae0ba85b5 |
Pass routing headers to ChatGPT subscription API (#62556)
## Objective Improve cache hit rate of LLM requests sent to ChatGPT subscription API. ## Solution Set headers that help route request to the correct servers. This is ChatGPT specific; plain OpenAI API doesn't require it. ## Testing I run a benchmark which imitates a thread that makes 20 sequential tool calls. I tried different cache route strategies. Results are below: | Configuration | Hit rate | |-------------------------------------------------|---------:| | No identity headers, no cache key | 22.2% | | `thread-id` only, no cache key | 44.4% | | `thread-id` + matching cache key | 42.1% | | Cache key only | 53.6% | | Turn state + cache key | 47.4% | | `session-id` + matching cache key | 100.0% | | `session-id` + `thread-id` + matching cache key | 97.4% | --- Release Notes: - Improved ChatGPT subscription caching |
||
|
|
333f4773b5 |
Fix ChatGPT subscription compaction (#62547)
ChatGPT Subscription compaction currently uses the legacy `POST /responses/compact` endpoint. The Codex backend now returns `404 Not Found` from that route, which causes manual and threshold-triggered compaction to fail even though ordinary model requests continue to work. Use the current Codex compaction contracts over the normal streamed `POST /responses` endpoint instead. Automatic compaction now advertises server-side support and sends `context_management`, while manual compaction appends the transient `compaction_trigger` input item used by Codex's remote compaction v2 flow. Both paths consume the standard encrypted `compaction` output item, preserving backend-owned state for subsequent requests. The manual action remains available through `supports_explicit_compaction`; only its transport changes. The shared Responses input type gains the `compaction_trigger` wire item and an append operation for provider-specific request construction. Testing performed: - `cargo nextest run -p open_ai -p openai_subscribed --lib` - `./script/clippy -p open_ai -p openai_subscribed` - `cargo fmt -p open_ai -p openai_subscribed -- --check` - Verified with ChatGPT OAuth against `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `gpt-5.4`, and `gpt-5.4-mini`: `compaction_trigger` returned HTTP 200 with a streamed `compaction` item for every model; forced `context_management` compaction also returned HTTP 200 for every model. The legacy `/responses/compact` route returned HTTP 404 for every model. Release Notes: - Fixed ChatGPT Subscription context compaction failing with an API endpoint error. |
||
|
|
efc1a47014 |
openai_subscribed: Log compaction response errors (#62540)
ChatGPT subscription compaction failures currently flow through the generic HTTP status conversion before callers can inspect the provider response. A 404 therefore becomes `ApiEndpointNotFound`, which drops the response body and leaves logs with only the inferred endpoint-not-found message. Log the original `RequestError` at the subscription compaction call site before returning it unchanged. The log identifies the compact endpoint and preserves the HTTP status and response body for diagnosis, without logging credentials, request contents, or response headers. Error classification, retry behavior, and user-facing presentation remain unchanged. Testing: - `cargo fmt --all --check` - `cargo nextest run -p openai_subscribed --lib` Release Notes: - N/A --------- Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
8a52ec4b66 |
gpui: Add binary data support to Svg element (#52319)
## Context Add support for binary SVG data in the `Svg` component in the `gpui` crate. The component now accepts raw SVG bytes via a new `.data()` method, in addition to the existing `.path()` and `.external_path()` methods. **Example usage:** ```rust svg().data(svg_bytes).color(colors::WHITE) ``` This solves the problem of unnecessary asset bundling and enables Rust's dead code elimination to optimize binary size. **Related issue:** Closes #52315 ## How to Review - Review `crates/gpui/src/elements/svg.rs` - the changes are localized to this file - Focus on: API design, caching strategy (hash-based virtual path), priority ordering in paint() - Verify the implementation properly integrates with existing `SvgRenderer` and `Window::paint_svg` ## Self-Review Checklist - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (none in this change) - [x] The content is consistent with the UI/UX checklist (trivial UI change) - [x] Tests cover the new/changed behavior (manual testing may be needed for SVG rendering) - [x] Performance impact has been considered (hash calculation is minimal; caching prevents redundant work) ## Technical Details The implementation: - Adds `data: Option<Arc<[u8]>>` and `data_path: Option<SharedString>` fields to `Svg` - Adds `pub fn data(mut self, data: &[u8]>) -> Self` builder method - Generates deterministic virtual path from SHA256-like hash: `__binary_svg__{hash}` - `paint()` checks sources in priority order: binary data > external_path > path - Uses existing `Window::paint_svg(..., data: Some(&bytes))` path This is a minimal, non-breaking change that leverages existing infrastructure. Release Notes: - Added `.data()` method to `Svg` element to accept raw SVG bytes Co-authored-by: Lukas Wirth <lukas@zed.dev> Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
23fbee3427 |
gpui: Add track_caller to gpui_util::log_err (#62538)
# Objective Tiny annoyance, the standalone `gpui_util::log_err` was never annotated with `#[track_caller]` so whenever it was called, the source location would be `gpui_util::lib` instead of the appropriate location. I checked and this is actually used in Zed in exactly one place: `crates/extension_host/src/extension_host.rs:1095`. So *technically* this can be considered a bug. I use it quite frequently in my code, so this is more of a self-serving pr. ## Solution I added `#[track_caller]` to `gpui_util::log_err`. ## Testing I ran the tests just in case and they all passed. ## 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 track_caller to gpui_util::log_err |
||
|
|
3130309c92 |
languages: Avoid probing unresolved macOS Python shim (#62534)
# Objective Fixes #62529. Prevent Python toolchain discovery from executing Apple's `/usr/bin/python3` Command Line Tools shim when no active developer Python exists. Executing that unresolved shim causes macOS to repeatedly prompt users to install the Command Line Tools, even when Python is managed through Nix, uv, or pyenv. ## Solution Update Python Environment Tools (PET) to `bb8e046`, which includes microsoft/python-environment-tools#506. That upstream change resolves active Xcode and Command Line Tools Python executables from filesystem state and skips unresolved macOS system Python shims before generic process probing. Adapt Zed to the updated PET API by: - displaying the newly supported Hatch environment kind - passing no refresh identifier when running in-process environment discovery ## Testing - `cargo check -p languages --locked` - PET unit tests covering unresolved macOS system Python shims - The Zed compilation check was run on Linux; the original dialog reproduction was not 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 --- Release Notes: - Fixed Python toolchain discovery prompting installation of Apple Command Line Tools when using a separately managed Python installation. |
||
|
|
ed4e541a6c |
Send correct line endings to language servers (#59941)
# Objective Zed normalizes all buffer text to `LF` internally, but was sending that `LF`-normalized text to language servers even for `CRLF` files. This caused servers such as ESLint (with a `linebreak-style` rule) to report a false error on every line. Fixes #38453 ## Solution Send the buffer's actual line endings to the language server instead: - `didOpen` and full-document `didChange` now send `text_with_line_endings()`, and incremental changes apply the buffer's line ending to each edit. - Normalize the line endings returning from the LSP before computing changed regions - This effectively incorporates the fix from #59151, which happens to be the reason this change was [originally reverted](https://github.com/zed-industries/zed/commit/b595846ba7cf15b9c0f6130b1d5130a6f28f52d0). As such, that PR should likely be integrated first. - Detect when a buffer's line ending differs from what a server was last sent and force a full-document resync, without this the server would keep stale line endings, as the incremental change tracking does not consider line ending differences. - Route the `UpdateLineEnding` operation to `on_buffer_edited` so toggling line endings via the status bar notifies the server immediately rather than waiting for the file to be edited or reopened. ## Testing - Did you test these changes? If so, how? Yes, in addition to new unit test coverage, I used a test project with ESLint configured with the `linebreak-style` rule set to enforce CRLF line endings to verify that the LSP integration worked as expected. - Are there any parts that need more testing? The original reversion seems to have been due to a regression in which LSP formatting would cause the editor to scroll to the bottom. I'm not seeing this in my reproduction, and I believe this was due to a failure to normalize line endings coming back from the LSP, but I don't know the exact circumstances that led to the original reversion, so there might be some additional things to test there. - How can other people (reviewers) test your changes? Is there anything specific they need to know? Not really! As mentioned above, configuring ESLint with the `linebreak-style` rule is probably the easiest way to test. - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? I tested on Linux, but I don't believe it's relevant. ## 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/881c5758-a5de-433c-8fd6-3cad7478aa90 --- Release Notes: - Fixed an issue where language servers received incorrect line endings for `CRLF` files, causing linters and formatters to report false errors. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
3e19851f8f |
editor: Keep the cursor before text inserted by on-type formatting (#61823)
## Why `textDocument/onTypeFormatting` edits that insert or replace text at an empty cursor use its right bias and move it past the new text. In paired tags, pressing Enter can therefore leave the cursor on the closing tag instead of between the tags. ## What - Capture a left-biased pin for each empty cursor before requesting on-type formatting. - Skip cursor tracking unless a matching language server advertises the trigger. - Restore only unchanged empty cursors whose displacement is fully covered by formatting transaction ranges, so intervening user edits are preserved. - Reset vertical movement state when restoring a cursor. ## Testing - `cargo test -p editor test_on_type_formatting` (5 passed) - `./script/clippy -p editor` ## References - Fixes https://github.com/zed-industries/zed/issues/61574 Release Notes: - Fixed the cursor being moved past text inserted or replaced at its position during on-type formatting. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
22a5bab822 |
Respect the filterText of LSP completion items during completion filtering (#62433)
# Objective Closes #61646. For code completions, Zed currently fuzzy-matches against `CodeLabel::filter_text()`: https://github.com/zed-industries/zed/blob/ddd9b3a3f09fe67258b81e017414df37266809d0/crates/editor/src/code_context_menus.rs#L337-L343 `CodeLabel::filter_text()` is a substring of `CodeLabel.text`, which is essentially the text itself. `CodeLabel.text` is constructed by Zed's per-language adapters from the `label` and `detail` fields of the completion items returned by the language server — the exact construction differs from adapter to adapter, but the source data is the same. In effect, `CodeLabel.text` ≈ `label` + `detail`. Zed therefore filters on the server-returned `label` and `detail`, while the server-returned `filterText` field is silently ignored.Per the LSP spec: ``` /** * A string that should be used when filtering a set of * completion items. When omitted, the label is used as the * filter text for this item. */ filterText?: string; ``` we should use `filterText` when it is provided. Normally, language servers populate `filterText` as a substring of `label`, so the current behavior works fine. But for certain language servers or functions, `filterText` can be entirely unrelated to `label` and `detail`. For example, for `std::path::Path::parent()` in Rust, rust-analyzer returns: ```json { "label": "parent()", "labelDetails": { "detail": "(alias dirname)", "description": "fn(&self) -> Option<&Path>" }, "kind": 2, "preselect": true, "sortText": "7ffffff6", "filterText": "parentdirname", ... } ``` Typing `dirname` therefore never surfaces this completion. The root design issue behind this bug is that `CodeLabel` is not well-suited to filtering LSP completions. ## Solution `CodeLabel` and its related methods are kept untouched: the struct is reused across the repo and is only unsuitable for filtering LSP completions. Instead, the changes are made in `CompletionSource` and `Completion`, each gaining a `filter_text()` method: - `CompletionSource::filter_text()` handles LSP completions, returning the server-provided `filterText` and falling back to the `label` when `filterText` is absent. - `Completion::filter_text()` is the general entry point used for fuzzy matching; for non-LSP completions it falls back to the existing `label.filter_text()`. The fuzzy match target is switched from `CodeLabel::filter_text()` to `Completion::filter_text()` — that is the core change. Since the fuzzy match target is no longer guaranteed to be a substring of the displayed `CodeLabel.text`, the matched characters no longer have a direct position in the displayed text to highlight. Bold highlights are therefore only rendered when `CodeLabel::filter_text()` equals `Completion::filter_text()`. This is a safe choice, though not an ideal one. ## Testing Added a new GPUI test covering the new behavior; also built and tested with a before/after comparison, 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) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase | Before | After | |:--:|:--:| | <img width="708" height="308" alt="Before" src="https://github.com/user-attachments/assets/ca2e3820-7ea1-4dcc-a91f-28aab71aecc5" /> | <img width="696" height="248" alt="After" src="https://github.com/user-attachments/assets/334e240b-64d5-495b-aef6-772456b993ba" /> | --- Release Notes: - Improved completion filtering for lsp completions. |