c032dcc3bcd56c8e2e80de4b65e2b864564aa003
39761
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c032dcc3bc |
Enable share-generics in release bundle builds (#63432)
Cargo joins `build.rustflags` across config sources, so the base `symbol-mangling-version=v0` and `tokio_unstable` flags still apply after the newly added config. With sccache disabled, `cargo build --release -p zed` on macOS: Before: zed binary 420677880 bytes After: zed binary 375109048 bytes (-10.8%, -45.6MB) After `strip -x` of both (https://github.com/zed-industries/zed/pull/63429): 313879024 -> 307727432 bytes (-2.0%, -6.2MB) The rest of the delta is the smaller symbol table. `drop_glue` instantiations: 101778 -> 65041. Release Notes: - N/A |
||
|
|
6dc2206180 |
Reduce LLVM IR bloat in closure funnels (#63426)
Follow-up to https://github.com/zed-industries/zed/pull/63232 Cuts closure monomorphization in settings and editor: settings file updates now share one boxed write-pipeline instantiation instead of inlining the `SettingsContent` clone, both `serde_json::to_value` calls, and the JSON diff at every call site; `Editor::register_action` and the settings enum dropdown get the same treatment. Behavior and public signatures are unchanged; thin generic shims remain. Symbol table of the release binary: Before: `update_settings_file_inner` 229 instantiations, inlined `serde_json` `SerializeMap` machinery 6547 copies After: 3 instantiations, 673 copies (-89.7%); `render_dropdown` is no longer instantiated at all With sccache disabled, `cargo clean` and `cargo build --release -p zed`: Before: zed binary 420677880 bytes After: zed binary 396999464 bytes (-5.6%, -23.7MB) Release Notes: - N/A |
||
|
|
fa839e548d |
context_server: Include requested scopes in OAuth DCR flow (#63370)
# Objective Fixes https://github.com/zed-industries/zed/issues/63363 The OAuth DCR flow would register an OAuth app with default (unset) `scope`. This was incompatible with some MCP servers, including GitLab's Orbit MCP server, which require OAuth scope(s) that are not part of the default assigned to DCR apps. ## Solution The OAuth DCR request now registers with the same set of `scope` selected for the entire flow, matching the authorization prompt used later. If the server advertises/requests no particular scopes for authentication, this field is elided to request a default set of scopes decided by the server. ## Testing - Successfully logged in via OAuth to the GitLab.com Orbit MCP server ([ref](https://docs.gitlab.com/orbit/remote/access/mcp/#connect-your-mcp-client)) and MCP server ([ref](https://docs.gitlab.com/user/model_context_protocol/mcp_server/#connect-a-client-to-the-gitlab-mcp-server)) on Linux - Unit tests confirm `scopes` are preserved in the DCR request body ## 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 OAuth authentication failure with MCP servers that require non-default scopes to access MCP endpoints Signed-off-by: Jonathon Anderson <anderson.jonathonm@gmail.com> |
||
|
|
7599be8e6b |
Stop prompting to migrate settings that contain no deprecations (#62818)
## Objective Zed can report that a settings file uses deprecated settings even when it contains no deprecations. A context server configured with only a `url` is enough to trigger the prompt, although the backup Zed offers to write is identical to the current file. Fixes #24967. ## Solution Two text-edit migrations cancel each other on `context_servers` entries: one adds a `source` key and a later one removes it. The round trip reindents the entry, and the migrator mistakes the leftover whitespace for a migration. Remove `m_2025_06_16` rather than comparing around that whitespace. It wrote `source` and `settings` into every entry, but `ContextServerSettingsContent` contains neither field today. `settings` is worse than inert: an empty entry such as `{ "settings": {} }` matches neither the `Stdio` nor `Http` variant of the untagged enum. Update `m_2025_06_27`, the only remaining consumer of the generated `"source": "custom"`, to detect legacy entries from the shape of `command` itself. This continues to flatten settings written before `source` existed. It also deliberately flattens an object `command` beside `"source": "extension"`, which the old migration skipped. The command shape is invalid regardless of the declared source, and a test pins the new behavior. `m_2025_11_25` remains unchanged because it still removes `source` from settings that genuinely carry it. This deletes one migration and edits another despite the warning at the top of `migrator.rs`. That warning protects later migrations that depend on earlier output, but this output has no remaining consumer. I left the policy unchanged rather than adding an exception in the same PR that relies on it, but I can document the exception if preferred. ## Testing - `cargo test -p migrator` passes, 86 tests. The suite loses the three tests that only exercised the deleted migration and gains `test_flatten_context_server_command_alongside_source`, covering a legacy entry that carries both `source` and an object `command`. - Restoring the `source` requirement on `m_2025_06_27` with the deletion in place turns `test_flatten_context_server_command` red. Its input is a pre-`source` entry, which is what makes the relaxation load-bearing rather than incidental. - To check by hand: add `"context_servers": { "grep": { "url": "https://mcp.grep.app" } }` to user settings and confirm no migration prompt appears. Add `"show_inline_completions": true` alongside it and confirm the prompt returns and leaves the context server block untouched. - I have not run those steps in a built editor. The tests call `migrate_settings`, which is all `should_migrate_settings` checks before raising the prompt, so that call is the whole untested gap. It’s all platform-independent text processing, so I did not test Linux or Windows. ## 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 migration prompt appearing for settings that contain no deprecations. Context servers configured with only a `url` no longer trigger it. --------- Co-authored-by: MrSubidubi <finn@zed.dev> |
||
|
|
2d6911db05 |
fs: Stop FakeFs deleting files it should leave alone (#63416)
# Objective `FakeFs::rename` deletes files in two cases where `RealFs` leaves them alone. Tests written against the fake see a file vanish where the real filesystem keeps it, so the behavior cannot be tested at all and anything relying on it drifts unnoticed. There is already a test for the first case for `RealFs`, `test_realfs_rename_ignore_if_exists_leaves_source_and_target_unchanged`, but the fake had no counterpart. ## Solution Return early in both cases instead of falling through to the removal. For `ignoreIfExists` onto an existing target, `RealFs` reports success and does not move anything. The fake kept the target but removed the source. The fix also stops recording a move that never happened, which would otherwise leave an open file handle pointing at the wrong path. For a rename onto itself with `overwrite`, POSIX requires success with no action. The fake assigned the entry onto itself and then removed it. I found this while fixing the first one, and included it. ## Testing I extended an existing test, and added two new ones. Each fails on `main` and passes here. I found this issue while working on #5369, where an LSP rename can send `ignoreIfExists` and the fake made the resulting bug impossible to write a test for. Ran the tests only on macOS as the area seems platform agnostic, but please let me know if I need to run them across all platforms. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - N/A |
||
|
|
3ba2bcfd68 |
theme: Show bundled Docker icon for .dockerignore files (#63398)
## Objective Fixes #63227 — `.dockerignore` files display a generic icon instead of the Docker icon. ## Solution Added `.dockerignore` to the list of filenames mapped to the Docker icon in `crates/theme/src/icon_theme.rs`. ## Testing - No automated tests added; the change is a static mapping. - Manually verified by opening a project with a `.dockerignore` file in Zed. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments (none) - [x] The content adheres to Zed's UI standards (single icon mapping) - [ ] Tests cover the new/changed behavior (not required for static mapping) - [x] Performance impact has been considered and is acceptable ## Showcase > This section is optional. If this PR does not include a visual change or does not add a new user-facing feature, you can delete this section. - Help others understand the result of this PR by showcasing your awesome work! - If this PR includes a visual change, consider adding a screenshot, GIF, or video - A before/after comparison is very useful for changes to existing features! While a showcase should aim to be brief and digestible, you can use a toggleable section to save space on longer showcases: <details> <summary>Click to view showcase</summary> My super cool demos here </details> --- - `.dockerignore` now shows the Docker icon for the bundled icon theme. |
||
|
|
432c18bcb9 |
Fix searching for full SHA-256 commit hashes in Git graph (#63371)
# Objective Search in the Git graph does not support full commit hashes in SHA-256 formatted repos, while SHA-1 formatted repos work fine. ## Solution Use existing constants in the `git` crate instead of hardcoded values when checking for a commit hash query. ## Testing Added a regression test for valid SHA-1 and SHA-256 commit hash lengths, plus rejection of hashes longer than the max length. ## 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) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase <details> <summary>Click to view showcase</summary> The screenshots below show the commit that is being searched for open in the Git graph. Before: <img width="1153" height="536" alt="before" src="https://github.com/user-attachments/assets/e47c4523-a046-4c47-ac75-cd00845b968f" /> After: <img width="1153" height="536" alt="after" src="https://github.com/user-attachments/assets/72eeaa16-d0ec-48cb-8ca2-c2bb26f02a10" /> </details> --- Release Notes: - Fixed searching for full SHA-256 commit hashes in the Git graph. |
||
|
|
88483df921 |
Show last recently used commands on top of the picker's list (#63388)
Closes #8106 Closes #8107 https://github.com/user-attachments/assets/2aba378a-657d-4de9-a45a-6106325281e5 Release Notes: - Improved command palette ordering: commands are sorted by recency of use, and previously used commands rank above unused ones while filtering. |
||
|
|
036af28f9d |
Restore the rule (#63384)
Release Notes: - N/A |
||
|
|
81299967df |
lints: Add map_lookup_then_insert lint (#62681)
## Objective
Sometimes we can do a hash lookup twice, which is slow and unidiomatic.
We should use the Entry API instead.
## Solution
Add another `dylint` lint called `map_lookup_then_insert` that catches
those cases.
This works with HashMap, BTreeMap, HashSet, BTreeSet and
entry-compatible ADTs.
## What it catches
See the examples in the `tooling/lints/ui/map_lookup_then_insert.rs`.
It's mostly things of the form
```rust
if let Some(value) = map.get(&key) {
*value
} else {
map.insert(key, 1);
1
}
```
which should be
```rust
*map.entry(key).or_insert(1)
```
The two key expressions are matched up to borrows/derefs,
value-preserving
conversions (`clone`, `to_owned`, `to_string` on string types, `to_vec`
on
slices, `String::from` on `&str` — each resolved by definition, not by
name),
and immutable local aliases. So looking up `&key` and inserting
`key.clone()`
is caught too. When a conversion had to be peeled, the diagnostic
carries a
note that an entry-API rewrite would perform that copy on hits as well
as
misses.
## What it deliberately does not catch
Forms Clippy already catches.
## Findings
A `--workspace` run finds 31 warnings at 30 unique sites in `zed`:
the 16 the plain key matching finds, plus 15 more that require the
conversion/alias matching (e.g. `tiles_by_key.get(key)` followed by
`tiles_by_key.insert(key.clone(), tile)` in `metal_atlas.rs`).
Will post those fixes in a follow up PR.
## Testing
UI tests cover every `Entry` method positively and negatively, BTreeMap
mirrors, set cases, and the Clippy-deferral boundary. The
key-normalization logic is covered by nine positive cases (cloned keys,
UFCS forms, `to_owned`/`to_string`/`to_vec`/`String::from`, deref
layers, local aliases, sets) and six negative cases (inherent methods
merely named `clone`/`to_owned`, mutated aliases, a clone of a different
key, `to_string` on a non-string key, and side-effecting initializers).
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
|
||
|
|
47df871ecc |
debugger: Fix breakpoint list not showing breakpoints in single files (#63348)
# Objective - Currently there is a bug where breakpoints in single files (not in folder/worktree) are not shown in the debug panel breakpoint list. They visually make the breakpoint list empty - This is because we try to create a `RelPath` from `breakpoint.path`, which is an absolute path ## Solution - Create the fallback directory string in a valid way - Because breakpoint directories can now be absolute, the first part of the path isn't always the worktree root, so we can't blindly skip this in the UI code anymore - Instead, only prepend the worktree root if there multiple worktrees, matching behavior of other UI elements. This simplifies the code overall ## Testing - Manually tested ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase Before: <img width="978" height="645" alt="image" src="https://github.com/user-attachments/assets/334176fd-3ad3-4bc7-b7bc-bf1568be6d76" /> After: <img width="962" height="755" alt="image" src="https://github.com/user-attachments/assets/e4259c7f-679b-4ac9-807e-d8787d43d067" /> --- Release Notes: - Fixed breakpoint list not showing breakpoints in single files |
||
|
|
9cdbece495 |
Normalize ranges returned by language servers in more cases (#63372)
Previously, we'd panic when constructing multibuffer excerpts in response to "find all references" if a language server returned a reversed range. This PR makes it so we normalize those ranges using the existing `range_from_lsp` helper before passing them to `set_excerpts_for_path`. It also replaces several other places where we were calling `point_from_lsp` on each endpoint of a range separately with `range_from_lsp`. Closes ZED-79W Co-authored-by: Mikayla <mikayla@zed.dev> Release Notes: - Fixed a crash with some languages servers when handling `editor::FindAllReferences`. |
||
|
|
f64d69fec6 |
Ensure that multibuffer anchor ordering is stable over time and consistent with resolution (#62636)
Digging into ZED-7G6 ("buffer snapshot not found for excerpt boundary",
171 events) revealed some bugs in the implementation of multibuffer
anchors that landed in #52364. Specifically:
- In the presence of multibuffer excerpt changes, it was possible for
two anchors to satisfy `a1 < a2` but `a1.to_offset() > a2.to_offset()`.
This happened in particular when a `PathKey` was reused for two
different buffers at different times, and could cause crashes in code
that sorted anchors by `cmp` and expected the resulting offsets to be
sorted.
- Changes of diff base and normal buffer edits could cause two anchors
to sort `a1 < a2` against one snapshot and `a2 < a1` against a later
snapshot. This could also cause crashes in downstream code that
(reasonably) expected anchors to have a stable ordering.
This PR adds a property test asserting that multibuffer anchor ordering
is stable over time and consistent at every moment in time with the
ordering obtained from resolving the anchors, and fixes the bugs in
anchor resolution and comparison that are revealed by that test. It also
includes tests downstream for specific cases that previously crashed.
Closes ZED-7G6
Release Notes:
- Fixed a crash that could occur when inlay hints were present while a
multibuffer replaced the contents of a file, such as a diff view whose
base changed.
- Fixed crashes that could occur when a file's contents were replaced in
a multibuffer (such as a diff view refreshing) while highlights, inlay
hints, or other positions still referenced the old contents.
---------
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
|
||
|
|
513ad12cef |
Avoid redundant string allocations (#63377)
Remove unnecessary intermediate `String` allocations when constructing `Arc<str>` and `SharedString` values. Use static `SharedString` storage for fixed worktree picker identifiers. Validation: - `cargo fmt --all -- --check` - `tooling/lints/single-lint owned_string_into_shared -p editor -p git_ui_core -p toolchain_selector` - `cargo test -p editor -p git_ui_core -p toolchain_selector` Release Notes: - N/A |
||
|
|
50b7479f17 |
gpui: Touch events (#63373)
Adds support to GPUI for touch events, important for mobile web browsers, and any potential native ios/android platforms --- Release Notes: - N/A or Added/Fixed/Improved ... --------- Co-authored-by: Jakub Konka <kubkon@jakubkonka.com> |
||
|
|
0134fcd23a |
markdown: Round inline code backgrounds across all markdown surfaces (#63272)
# Objective Inline code renders as a rounded chip in the Markdown preview (#63118) but as a square, full-line-height background everywhere else — the agent panel, editor hover popovers, notifications, and other markdown surfaces. ## Solution Inline code with a background color now always renders as a chip with a 4 px corner radius. The radius is fixed at the paint site rather than exposed through `MarkdownStyle`, so every markdown surface uses the same rendering without carrying configuration through the element builder and rendered lines. Chip backgrounds and text styling remain configurable. Only the corner radius is fixed, removing the alternative square rendering path and preventing surfaces from becoming inconsistent. ## Testing - Updated `test_inline_code_chips_cover_exactly_the_code_span_glyphs` to cover the fixed chip behavior. - `cargo test -p markdown test_inline_code_chips_cover_exactly_the_code_span_glyphs` - `./script/clippy -p markdown` ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments (there are none) - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Improved inline code to render with rounded backgrounds across all markdown surfaces, matching the Markdown preview. --------- Co-authored-by: MrSubidubi <finn@zed.dev> |
||
|
|
c67c5c150b |
Send complete tool JSON schemas to every provider (#63342)
Zed asked each language model which JSON Schema dialect it wanted, and
rewrote every tool's schema into that dialect before sending it.
`LanguageModelToolSchemaFormat` had grown three variants, and providers
picked between them by model name, so Grok and Gemini took a lossy path
while everything else did not.
The subset exists because Google's `FunctionDeclaration.parameters`
field accepts an OpenAPI-flavored schema rather than JSON Schema, and
`adapt_schema_to_format` tried to translate into it. The translation was
best-effort: constructs it could not represent were left in place and
the function still returned `Ok`. The shape schemars produces for a Rust
`String | Vec<String>` union survives as a nested `anyOf` whose outer
node carries no `type`, and Vertex rejects the entire request over it,
taking every other tool down with it. Where the translation did fail,
the caller logged the error and dropped the tool, so the model silently
lost a capability.
Google now offers `parametersJsonSchema` alongside `parameters`, which
takes plain JSON Schema, and every other provider we ship documents JSON
Schema for function parameters. So the first commit switches
`into_google` to `parametersJsonSchema`, and the second deletes the
dialect: `LanguageModelToolSchemaFormat`,
`LanguageModel::tool_input_format`, `adapt_schema_to_format`, and the
per-model branching in every provider go away, along with
`x_ai::Model::requires_json_schema_subset`.
What remains is `normalize_tool_schema`, which every tool now passes
through. It strips `$schema`, `title`, and `description` from the root,
which no provider reads and which cost tokens; gives an object schema an
explicit `"properties": {}`, which OpenAI requires; and inlines
same-document `$ref`s. That last part is carried over from the deleted
code and matters only for context servers: MCP's Python SDK derives
input schemas through pydantic, which emits `$defs` and `$ref` for any
nested model or enum, and `zod-to-json-schema` emits `definitions` for
reused shapes, while Google rejects references outright. Built-in tools
never contain one, because `root_schema_for` inlines subschemas during
generation. A schema whose references cannot all be resolved is passed
through untouched and the reason logged, so a provider explains what is
wrong instead of receiving something half-rewritten.
## Providers whose behavior changes
| Provider | Models affected | Before | After |
|---|---|---|---|
| Google | all | `JsonSchemaSubset` in `parameters` | full JSON Schema
in `parametersJsonSchema` |
| Zed Cloud | Google, xAI | `JsonSchemaSubset` | full JSON Schema |
| Copilot Chat | Google, xAI, unknown vendors | `JsonSchemaSubset` |
full JSON Schema |
| xAI | Grok 4.3, 4.5, 4.6, 4.20 Reasoning, 4.20 Non-Reasoning |
`JsonSchemaSubset` | full JSON Schema |
| OpenRouter | model ids containing `gemini` or `grok` |
`JsonSchemaSubset` | full JSON Schema |
| Vercel AI Gateway | all | `JsonSchemaSubset` | full JSON Schema |
| OpenAI-compatible | all | `JsonSchemaSubset` | full JSON Schema |
| Bedrock Mantle | all | `JsonSchemaSubset` | full JSON Schema |
| Everything else | — | `JsonSchema` | unchanged apart from
normalization |
One deliberate difference for the last row: the old `JsonSchema` path
also injected `additionalProperties: false` into object roots, and
normalization does not. Nothing depends on it. Serde ignores unknown
fields, so a model inventing an argument never broke deserialization,
and OpenAI's strict function calling — the one feature that requires the
flag — is never enabled: every `ToolDefinition::Function` in the tree
passes `strict: None`. It was also only ever applied on the `JsonSchema`
path, so Google, Grok, Vercel and Bedrock Mantle users never received
it. Dropping it makes behavior uniform rather than removing a guarantee.
## Verification
This was checked against live providers rather than by reasoning about
documentation. A harness in the Delta repository dumps all 24 built-in
tool schemas from this branch and submits them with `tool_choice: none`
to each provider, so the only thing under test is whether the provider
accepts the schemas. Anthropic, OpenAI (chat and responses), Gemini,
xAI, Baseten, OpenRouter (Gemini and Grok), Vercel AI Gateway (Gemini
and Grok), Copilot (Gemini and Grok), the ChatGPT subscription, Bedrock
Converse, Bedrock Mantle (GPT and Grok), and Zed Cloud (Anthropic,
OpenAI, and Google) all accepted them. DeepSeek, Mistral, and OpenCode
were not probed for lack of a key.
The failure this fixes is reproducible on the route that broke. Vertex,
not the Gemini Developer API, is what enforces the constraint: the
harness pins the `grep` declaration production generated, replays it to
Vertex through Zed Cloud in the legacy `parameters` field, and gets back
the exact `INVALID_ARGUMENT` naming `parameters.globs`, while the same
route accepts this branch's schemas through `parametersJsonSchema`. The
Gemini Developer API accepts the broken shape on every model tried, so a
direct API key would never have caught it.
Testing:
- `cargo nextest run -p language_model_core -p google_ai -p agent` for
the schema, `into_google`, MCP and built-in tool tests
- New tests cover reference inlining for the shapes pydantic and zod
produce, recursive references, and unresolvable references
- `built_in_tool_schemas_are_normalized` asserts every built-in tool is
present and normalized
- `crates/agent/examples/dump_tool_schemas.rs` prints the definitions
the harness consumes
- 21 live provider probes with the complete tool set
Release Notes:
- Fixed Gemini rejecting requests because Zed translated tool schemas
into a restricted dialect it could not represent
|
||
|
|
951357a916 |
editor: Add language detection for untitled buffers (#61412)
# Objective Closes #4868. Reintroduce automatic language detection for user-created untitled buffers without allowing it to override language choices made by users or owning surfaces. More details: + https://github.com/zed-industries/zed/pull/61201 + https://github.com/zed-industries/zed/pull/61351 ## Solution VS Code distinguishes between inferred and explicitly selected languages, and only continues automatic detection in the former state. This change introduces a buffer-local opt-in flag with the same purpose. It defaults to disabled and is enabled only for user-created untitled buffers and restored untitled buffers that did not persist a language. Choosing a language through the language picker disables detection, while automatically detected languages remain eligible for later redetection. Buffers whose language is assigned by their owning surface, such as Channel Notes, never opt in. Rather than adding persisted state or changing the database schema, restoration reuses the existing optional serialized language. An opted-in buffer that remains Plain Text is serialized without a language and resumes detection after restoration. Once automatic detection has selected a language, that language is serialized normally and restoration leaves detection disabled, effectively treating it as an explicit selection. This also matches VS Code's effective default after restoration. Candidate selection adopts VS Code's confidence-group filtering. Results below the minimum confidence are discarded, and candidate groups are accepted only after a clear confidence gap. The detector then selects the first available Zed language without eagerly loading every candidate. I then added a separate switching rule: Zed keeps the current language unless another candidate has a clear confidence advantage, reducing language changes as model scores fluctuate during editing. Model inference runs off-thread on a bounded sample, and stale results are discarded. I also evaluated penalizing YAML and using stricter global switching thresholds, but neither reliably resolves the ambiguity between Markdown and YAML. In the reproduction from #61351, Betlang assigns YAML more than 80% confidence during editing and peaks around 90%. This is reasonable from the content alone: `#` denotes a YAML comment, while `-` denotes a sequence item. Adding ordinary prose or a fenced code block shifts the model strongly toward Markdown. A fixed penalty would overfit this example and risk suppressing legitimate YAML detection. Since known-language buffers do not opt in and manual language selection takes precedence, I consider this level of ambiguity acceptable and prefer not to introduce language-specific score tuning. Model inference itself is fast. As noted in #61201: > In release builds on Linux with an Intel Core i5-13600KF, the `betlang::detect` call alone typically completes within 3 ms when processing the maximum sampled input. The main concern is the work surrounding inference. Without debouncing, rapid typing creates a snapshot and launches a background detection task on every keystroke, while the detected language may change before the user has finished typing. This change therefore adds a 200 ms debounce delay, allowing detection to run and update the language only after the user pauses. ## Testing Automated coverage verifies that short inputs remain Plain Text, sufficient Rust content is detected as Rust, replacing it with Go content triggers redetection, and manually selecting Plain Text prevents subsequent automatic changes. Restoration coverage verifies that a stored language keeps detection disabled, while an empty language-less untitled buffer resumes detection. Beyond the automated tests, I manually tested automatic language detection while editing untitled buffers. ## 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/103fc731-e12e-48d6-ae89-03978f1c9d74 --- Release Notes: - Added automatic language detection for untitled buffers. --------- Co-authored-by: Max Stevens <maxstevens2708@gmail.com> Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com> |
||
|
|
3122f37ff1 |
git_ui_core: Fix worktree creation for bare repositories (#63351)
Follow-up https://github.com/zed-industries/zed/pull/55153 Fixes https://github.com/zed-industries/zed/discussions/54553#discussioncomment-17091833 When a repository stores its Git data in `~/work/zed/.bare`, creating a linked worktree from Zed is broken in two visible ways: - Zed creates `random-code` at: ``` ~/work/worktrees/.bare/random-code/.bare ``` instead of: ``` ~/work/worktrees/zed/random-code/zed ``` - Because the checkout ends in `.bare`, Zed displays `.bare` as its worktree name in the title bar, worktree picker, and agent thread sidebar. Every worktree Zed creates from that repository gets the same `.bare` label instead of its generated name. This problem is specific to the path Zed creates. Worktrees using either of these layouts are not malformed: ``` ~/work/worktrees/zed/random-code/zed ~/work/zed/some-worktree ``` https://github.com/zed-industries/zed/pull/55153 introduced repository identities for bare repositories. This PR uses that identity in the remaining worktree naming and creation paths. There are three repository layouts to account for: - In a normal repository, the common Git directory is `~/work/zed/.git`, so Zed derives the main worktree at `~/work/zed`. Existing behavior remains unchanged. - With `~/work/zed/.bare`, Git has no main worktree. A checkout named main is still a linked worktree. Zed now treats `~/work/zed` as the repository identity, creates new worktrees under `~/work/worktrees/zed`, and displays their generated names. - With a bare repository named `~/work/foo.git`, `foo.git` is the repository identity. Its worktree path remains `~/work/worktrees/foo.git/random-code/foo.git`. Zed uses foo.git to derive the worktree name random-code, while displaying the repository itself as foo. Existing malformed worktrees such as `~/work/worktrees/.bare/random-code/.bare` are not moved and may continue to display `.bare`. Broken: <p> <img width="238" height="58" alt="image" src="https://github.com/user-attachments/assets/1504e4d0-c34a-471f-8e76-c5ec062b1d77" /> </p> <p> <img width="274" height="49" alt="image" src="https://github.com/user-attachments/assets/13266ca9-4e64-426c-b03c-e23c924a3597" /> </p> <p> <img width="574" height="85" alt="image" src="https://github.com/user-attachments/assets/0fca58c7-5be7-4d36-9067-066d0b80caf8" /> </p> Release Notes: - Fixed linked worktree names and creation paths for bare Git repositories. |
||
|
|
a0608b889d |
feat: Add reveal buffer if already open (#63306)
# Objective Fixes #12572 ## Solution - Adds an opt-in `reveal_if_open` setting which enables searching and revealing an already open buffer - Ensures this only happens if there is no pane target for the open intent ## Testing - Built for and tested on my Mac - Tests added covering the scope of the feature ## 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/cdcc78cd-85fd-4b56-b562-feba375ecd03 --- Release Notes: - Added configuration to reveal buffers already open in a different pane instead of the active pane, via `reveal_if_open` --------- Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com> |
||
|
|
ee83eeca60 |
docs: Update documentation for YARA (#63340)
## Description Fixed documentation bug in \docs/src/languages.md\: - **Issue**: \Yara\ was incorrectly linked to \./languages/yarn.md\ and there was a duplicate \Yarn\ entry - **Fix**: Changed \Yara\ link to \./languages/yara.md\ and removed the duplicate \Yarn\ entry ## Testing - Verified both \yara.md\ and \yarn.md\ files exist in \docs/src/languages/\ - Applied Prettier formatting to the file --- Release Notes: - N/A --------- Co-authored-by: Kunall Banerjee <hey@kimchiii.space> |
||
|
|
26d819a9cf |
git: Fix remote URL parsing for partial clones (#63331)
Git adds the clone filter after `(fetch)` in `git remote -v` for partial clones. Zed expected `(fetch)` at the end of the line, so it dropped these remotes. This fixes that. **Before:** Only regular fetch entries were recognized: ```text origin https://github.com/zed-industries/zed.git (fetch) ``` **After:** Fetch entries containing partial-clone filter metadata are also recognized: ```text origin https://github.com/zed-industries/zed.git (fetch) [blob:none] ``` Release Notes: - Fixed Zed failing to recognize Git remotes in partial clones. |
||
|
|
0403df17a4 |
which_key: Fix Windows keybinding display in Which Key (#63349)
On Windows, Zed shows some shortcuts using the keys a person presses. For example, it displays `ctrl-@` as `Ctrl-Shift-2`. Which Key was dropping that Windows-specific label and showing `Ctrl-@`, while the command palette and keymap editor showed `Ctrl-Shift-2`. This PR makes Which Key use the same shortcut labels as the rest of Zed. **Before:** Which Key (Shows `Ctrl-@`): <p> <img height="70" alt="image" src="https://github.com/user-attachments/assets/9272ba29-1ebc-4329-8bd3-ec42937766c8" /> </p> Keymap Editor (Shows `Ctrl-Shift-2` instead of `Ctrl-@`): <p> <img height="50" alt="image" src="https://github.com/user-attachments/assets/3c36d887-2cb8-45fc-9672-6a8ea2ba2f4d" /> </p> Command Palette (Shows `Ctrl-Shift-2` instead of `Ctrl-@`): <p> <img height="70" alt="image" src="https://github.com/user-attachments/assets/2619a84b-341d-4ee4-89fb-4db62c3569dc" /> </p> **After:** <p> <img height="70" alt="image" src="https://github.com/user-attachments/assets/212f4d6e-e07d-4857-a0e7-e526611f2fcb" /> <p> Release Notes: - Fixed inconsistent shortcut labels in Which Key on Windows. |
||
|
|
0b1f4f4020 |
Delay-load ETW profiling DLLs (#62647)
Since we're here, improve the UX by prompting for a path when you save rather than when recording begins. Fixes #62334 Release Notes: - N/A |
||
|
|
8a54abc4b9 |
Improve outline fonts and colors (#63325)
Closes https://github.com/zed-industries/zed/issues/58580 * Outline modal and panel now use buffer fonts for the contents: <img width="1728" height="1117" alt="modal" src="https://github.com/user-attachments/assets/5e0ef6e3-be39-4949-bc32-7087a51a02ec" /> <img width="1728" height="1092" alt="panel" src="https://github.com/user-attachments/assets/5cf9edbf-5ff3-402d-a2ca-bc915bd10e8e" /> * Gutter colors are now fall-backed to tree-sitter better, if no semantic tokens could be retrieved due to multi buffer shenanigans: <img width="1728" height="426" alt="gutter" src="https://github.com/user-attachments/assets/a175b2c8-843e-4632-b030-3edfbd350982" /> Release Notes: - Improved outline fonts and colors |
||
|
|
2ada348466 |
Improve Windows shell discovery (#63339)
- Simplify PowerShell discovery, and add support for .NET global tool installations. - Fix Git Bash discovery in the case where Zed was launched from within Git Bash. Git Bash prepends its internal `mingw64\bin` directory to `PATH`, so `which git` returns a different `bash` executable that causes the relative path lookup to fail. Release Notes: - N/A |
||
|
|
9e6bb59956 |
crashes: Abort after reporting Windows panics (#63157)
On Windows, the panic hook generated a minidump by calling `simulate_exception`, but that function only invokes the crash callback and then returns. Rust could therefore unwind a panicking background thread while leaving the rest of the application running. Abort unconditionally after minidump generation, matching the existing Linux and macOS behavior. The Windows-specific simulation still runs first so the crash sidecar can persist the exception context and panic metadata before the process terminates. Testing: - `cargo fmt -p crashes --check` - `cargo nextest run -p crashes` Release Notes: - Fixed Windows processes remaining alive after a background thread panic. |
||
|
|
bb3b7953fe |
editor: Auto-refresh Bookmarks tab when bookmarks change (#56363)
[## Context Fixes a bug where the Bookmarks tab, opened via `editor: view bookmarks`, showed a stale snapshot and had to be reopened to display bookmarks added or removed while it was open. Closes #56268 `view_bookmarks` built a one-time multibuffer and never subscribed to `BookmarkStore`. The store also calls `cx.notify()` while resolving serialized bookmarks into anchors, even though that bookkeeping does not represent a user-visible bookmark change. Observing all notifications would therefore feed resolution notifications back into the refresh mechanism and cause redundant cancellation and requeue work. The store now emits a dedicated `BookmarkStoreEvent::BookmarksChanged` from bookmark mutation paths, while `resolve_all` deliberately does not emit it. Refresh state lives on a `BookmarksView` entity that holds the tab's multibuffer. Split editors already share that multibuffer, so they share the view as well. Each store event drives one reconciliation regardless of how many split editors display it. The view remains alive as long as any split retains it, so closing the original tab does not stop the remaining split from refreshing. Each refresh reconciles excerpts per path instead of rebuilding the multibuffer: `set_excerpts_for_path` updates files that still contain bookmarks, while `remove_excerpts` removes files whose final bookmark was deleted. This follows the per-path reconciliation pattern used by project diff views. `view_bookmarks` creates the tab synchronously and populates it asynchronously, following the existing patterns in `ProjectDiagnosticsEditor::deploy` and `ProjectSearchView::existing_or_new_search`. Repeated invocations focus the existing Bookmarks tab instead of opening duplicates. Video of the manual test: [Screencast from 2026-05-11 02-03-38.webm](https://github.com/user-attachments/assets/8ac97245-09ff-4a79-9634-20cb8dfbb7eb) ## How to Review **`crates/project/src/bookmark_store.rs`** Adds `BookmarkStoreEvent::BookmarksChanged`, emitted from bookmark mutation paths such as toggle, label edit, file rename or deletion, clear, and deserialization, but not from anchor resolution. It also adds `BookmarkStore::is_empty`. **`crates/editor/src/bookmarks.rs`** Adds `BookmarksView`, which holds the multibuffer, store subscription, and in-flight refresh task. It reconciles excerpts and emits `BookmarksViewEvent::Populated(ranges)` for per-editor highlights and cursor placement. It also caches the latest populated ranges and replays them when an editor attaches, allowing a split created after population to display bookmark highlights immediately. **`crates/editor/src/editor.rs`** Adds the shared `bookmark_view`, a per-editor subscription to its population events, and `bookmark_initial_selection_pending` for initial cursor placement. `Editor::clone` attaches the split to the shared view instead of creating another store subscription and refresh task. **`crates/editor/src/editor_tests.rs`** Adds five tests covering automatic addition and removal across multiple files, removal of a file's path after its final bookmark is deleted, initial cursor placement, a bookmark change racing initial population, splitting while population is pending, cached highlights in a late-attaching split, and continued refreshing after the original tab releases its view handle. ## Self-Review Checklist - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the UI/UX checklist - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed Bookmarks tab not updating when bookmarks are added or removed while the tab is open](https://github.com/zed-industries/zed/pull/56363) --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
05154a14af |
helix: Add m i m/m a m and preserve the selection after those actions (#59201)
# Objective - Preserve Helix mode selections after surround-related commands such as adding, deleting, and replacing surrounds. - Add Helix-compatible closest-pair behavior for `m i m` / `m a m` and surround commands that target `m`. - Avoid long stalls in Helix text-object boundary scans by removing repeated syntax-scope classification during textual scans. - Keep workflows like selecting text with `m i w`, applying `m s`, and continuing with `i`, `a`, or another surround command aligned with Helix behavior. ## Solution - Add selection anchors that preserve each pre-edit selection range and direction through surround edits. - Update Helix surround add so the resulting selection includes the added delimiters, allowing surround commands to compose and insert/append actions to land outside the pair. - Apply preserved selections to Helix surround delete and replace so non-empty selections are not collapsed to the cursor after the edit. - Add Helix-specific text-object bindings so `m` selects the closest surrounding pair, `t` selects types/classes, `c` selects comments, and `x` selects XML/HTML elements in Helix mode. - Match the current closest pair through language bracket queries, so delimiters inside strings or comments do not count as surrounding pairs. - Resolve the textual boundary scanner's `CharClassifier` once per scan and pass it by reference instead of recomputing the same classifier for every scanned character. Word and subword boundaries still clone it only to apply the `ignore_punctuation` flag. ## Performance The textual boundary scanner previously called `char_classifier_at(from.0)` inside the per-character comparison closures for the four `ImmediateBoundary` scan methods and `FuzzyBoundary::to_boundary`. That lookup resolves the language scope through the syntax layers, and the value was loop-invariant because every iteration used the scan's starting offset. Local debug benchmark, using `] m` in a roughly 540 KB buffer with no pair characters so the scan runs to EOF across all pair boundaries: | | `] m` | | ------ | -----: | | Before | 36.3 s | | After | 210 ms | This speeds up the remaining textual scanner paths, including `m i (` / `m i "`-style pair objects, word/sentence/paragraph objects, `]` / `[` text-object navigation, and `] m` / `[ m`. The current-pair `m i m`, `m a m`, `m d m`, and `m r m` paths use the tree-sitter closest-pair path instead. ## Testing - Ran `cargo test -p vim test_helix_surround -- --nocapture`. - The focused Helix surround test filter passed: 10 passed, 0 failed. - Added coverage for closest-pair selection, Helix-specific text-object keys, and surround selection preservation. ## 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 Helix mode support for closest-pair text objects with `m i m` and `m a m`. - Fixed Helix mode surround commands to preserve selections after edits and avoid slow textual boundary scans. |
||
|
|
7472da6de7 |
Add folder_indicator setting to show chevron and folder icon together (#62393)
# Objective - Enable panels to show chevron and icon at the same time. - Closes #8661 ## Solution - Replaces `folder_icon` with a new `folder_indicator` which converts from a boolean to enum (`both`, `chevron`, `icon`) for the three display cases ## Testing - gpui and migration tests had been applied ## 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 ### project panel both | chevron | icon --- | --- | --- <img width="400" alt="both_project_panel" src="https://github.com/user-attachments/assets/4c21e1a1-a7a4-4471-b7de-fe867373ddbd" /> | <img width="400" alt="chevron_project_panel" src="https://github.com/user-attachments/assets/a626a82e-e5b7-470d-9d93-ed5787dc83d6" /> | <img width="400" alt="icon_project_panel" src="https://github.com/user-attachments/assets/20f9c55e-87c4-477a-b4c9-b070d6e5a1db" /> ### git panel both | chevron | icon --- | --- | --- <img width="400" alt="both_git_panel" src="https://github.com/user-attachments/assets/3dc166dd-9e63-4943-b803-df3f167876b6" /> | <img width="400" alt="chevron_git_panel" src="https://github.com/user-attachments/assets/8dfd2c10-3a68-439a-8019-4951b72e17d1" /> | <img width="400" alt="icon_git_panel" src="https://github.com/user-attachments/assets/d78a9938-91e7-4d39-a3c8-04647da67768" /> ### outline panel both | chevron | icon --- | --- | --- <img width="400" alt="both_outline_panel" src="https://github.com/user-attachments/assets/1b58c679-0bea-4600-a8ac-e800b0e8d24c" /> | <img width="400" alt="chevron_outline_panel" src="https://github.com/user-attachments/assets/0a9358e4-ec89-40d8-8d5e-a53b784ed30a" /> | <img width="400" alt="icon_outline_panel" src="https://github.com/user-attachments/assets/d8bf5199-5a8c-4de0-b516-00247e6531a5" /> --- Release Notes: - Added a `folder_indicator` setting that can show the disclosure chevron and folder icon at the same time in the project, outline, and git panels. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
b421755e5d |
Fix settings schema missing extension-provided LSP settings on remote (#62355)
## Objective Fixes an issue where language servers provided by extensions are not included in the settings schemas served by remote servers. When connecting to a remote server via the `open_remote_project_with_existing_connection` flow (dev servers, multi-workspace reopen, git worktree picker), setup-N servers never received any extension sync, so their schemas omitted extension-provided language servers, breaking language support for remote development. ## Solution Three changes ensure that language servers provided by extensions are included in the settings schemas served by remote servers: 1. **Register connections opened via `open_remote_project_with_existing_connection` with the extension store**: dev servers, multi-workspace reopen, and the git worktree picker now register their connections with the extension store so that extensions are synced to those servers. Previously only the `open_remote_project` flow did this, so setup-N servers never received any extension sync and their schemas omitted extension language servers. 2. **Emit `ExtensionsInstalledChanged` from `HeadlessExtensionStore` after sync and install complete**: this allows the remote process to invalidate its cached settings schemas. The local `ExtensionStore` already emitted this event; without it, the remote schema cache stayed stale for the lifetime of the server process. 3. **Include available LSP adapters in the project settings schema**: this matches the user settings schema (this was fixed for `settings` in #46766 but never applied to `project_settings`). ## Testing - Manually verified that after connecting to a remote server via the `open_remote_project_with_existing_connection` flow (including dev servers and the git worktree picker), extension language servers appear in the schema served by the remote server. - Verified that `ExtensionsInstalledChanged` is emitted after sync and install complete, and that the remote schema cache is correctly invalidated and rebuilt. - Verified that the `project_settings` schema includes the available LSP adapters, matching the behavior of the user settings schema. - Reviewers should focus on the multi-workspace reopen and git worktree picker flows (the two previously unregistered flows) to confirm that extension language servers are correctly synced and appear in the schema. ## 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 **Server / Project** — before the fix <img width="1061" height="749" alt="image" src="https://github.com/user-attachments/assets/d6c5459f-58fb-4769-a701-f6fb317adc37" /> **Local** <img width="1119" height="449" alt="image" src="https://github.com/user-attachments/assets/fb30a1e2-74f0-4439-a25f-1022ed164074" /> --- Release Notes: - Fixed an issue where language servers provided by extensions were missing from settings schemas served by remote servers. --------- Co-authored-by: vancez <vancez@users.noreply.github.com> Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
c684a6a537 |
Add LSP call hierarchy modal (#53239)
<img width="1128" height="953" alt="image" src="https://github.com/user-attachments/assets/b2017c0a-e25a-49d7-9342-d074014d085c" /> Closes #14203 Release Notes: - Initial Call Hierarchy support in Zed --------- Co-authored-by: Alexey Olshanskiy <gh@aohoy.dev> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
941bd6fa99 |
gpui: IME race condition bug (#63311)
When an IME makes a selection, but doesn't modify the text, there was a race condition, where the GPUI->mirror sync could overwrite the `selectionchanged` event, causing IME sessions to be discarded. --- Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
09440c85cb |
lsp: Add client support for LSP 3.18 markdown diagnostic messages (#61030)
LSP 3.18 allows servers to send [`MarkupContent` diagnostic messages](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#diagnostic), guarded by the client capability `textDocument.diagnostic.markupMessageSupport`. - Advertise `markup_message_support` only while pull diagnostics are enabled because `textDocument.diagnostic` is the pull-model capability. LSP 3.18 currently has no equivalent capability for push diagnostics: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#diagnosticClientCapabilities https://github.com/microsoft/language-server-protocol/issues/2246 - Handle `string | MarkupContent` messages in both push and pull diagnostic paths: markdown-kind messages populate the existing `Diagnostic::markdown` field (rendered in hover popovers and the diagnostics panel), plaintext-kind markup remains plain text, and plain string messages keep going through the adapter's `diagnostic_message_to_markdown`. - Preserve server-provided markup for code actions sent back to the originating server, avoid forwarding markup diagnostics to other servers, and render diagnostic metadata without altering the server-provided markdown. - Carry the markup kind over RPC via a new optional `LspDiagnostic.markup_message_kind` proto field so remote/collab projects round-trip `MarkupContent` messages. Depends on the lsp-types change that turns `Diagnostic.message` into a `DiagnosticMessage` enum (`string | MarkupContent`): https://github.com/zed-industries/lsp-types/pull/15 Once merged, Cargo.toml can point to the upstream commit. Note that Zed already rendered some plain-string diagnostics as Markdown through language-specific adapter hooks, including `rust-analyzer`. This adds protocol-level support for diagnostics explicitly sent as LSP 3.18 `MarkupContent`, while preserving the existing adapter fallbacks. As a result, this does not introduce a new diagnostics rendering pipeline. Server-provided Markdown is routed through the existing `Diagnostic::markdown` path, with small fixes to handle Markdown-only updates and block content correctly. ## Showcase Example from [JETLS.jl](github.com/aviatesk/JETLS.jl) (a Julia language server): > Before <img width="924" height="160" alt="Screenshot 2026-07-15 at 16 05 40" src="https://github.com/user-attachments/assets/b19fe9e3-50e3-44e4-9b4d-ac8bd438d3d6" /> > After <img width="924" height="160" alt="Screenshot 2026-07-15 at 14 13 05" src="https://github.com/user-attachments/assets/359c3382-118d-4fa6-aa91-6bd3661d3d28" /> --- Release Notes: - Added support for rendering LSP 3.18 Markdown diagnostic messages from language servers. --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Kirill Bulatov <mail4score@gmail.com> |
||
|
|
0854657a2b |
gpui: Add text_edit_editable_range API (#63294)
When syncing text to the browser IME mirror, we sometimes need to mark a particular range as "editable". Native clients have a pull-based model, so don't need this mechanism, but on the web we need to proactively push content to the IME mirror `textarea`. --- Release Notes: - N/A or Added/Fixed/Improved ... --------- Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
b24568132b |
Add support for Visual Line select in terminal vi mode (#63251)
# Objective Add support for Visual Line Select in terminal vi mode. ## Solution Add handling for "V" akin to Visual Line Select mode in vim. ## Testing manually tested these changes by running locally (`cargo run`) ## 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/a39636cd-a82e-444d-bdac-8f86d76f03f4 --- Release Notes: - Added support for Visual Line Select in terminal vi mode |
||
|
|
b90c4869f9 |
Require clear sections in lint UI fixtures (#62659)
Add `// --- SHOULD FIRE ---- ` and `// ---- SHOULD NOT FIRE ---- ` to the `/lint-creator` skill. Release Notes: - N/A |
||
|
|
22a582a86a |
Remove wasted clones of loop-invariant values (#62763)
# Objective Remove avoidable clones of loop-invariant values that pay a copy on every loop iteration. These were found by running a prototype `deep_clone_in_loop` dylint (modeled on the accidentally quadratic project-search fix in #62658) across the workspace. None of these sites are quadratic in practice — the loops are bounded — but each one does strictly wasted work that a one-line change removes. ## Solution - `collab/src/api/extensions.rs`: use `next_marker.take()` instead of `next_marker.clone()` for the S3 pagination marker. The marker is either overwritten via `clone_from` at the end of the iteration or the loop breaks, so it is never read after the `take`. - `project/src/manifest_tree/path_trie.rs`: build the trie key with `Arc::from(path_so_far.as_rel_path())` instead of `path_so_far.clone().into()`. The `From<RelPathBuf> for Arc<RelPath>` impl copies the bytes into the `Arc` anyway, so the intermediate `RelPathBuf` clone was a second, redundant copy. - `context_server/src/client.rs`: in `notify`, split off the last handler and move the `serde_json::Value` payload into it, cloning only for the preceding handlers. Previously every handler received a clone and the final one was always wasted. - `editor/src/rewrap.rs`: use `std::mem::replace` to move the comment-delimiter and rewrap-prefix accumulators into the pushed range instead of cloning them and immediately reassigning. ## Testing - `cargo check -p collab -p project -p context_server -p editor` — clean. - `cargo test -p editor rewrap` — 7/7 pass, including the boundary-sensitive `test_rewrap*` editor tests. - `cargo test -p context_server` — 97/97 pass. - `cargo test -p project path_trie` — 2/2 pass. - Re-ran the `deep_clone_in_loop` lint on the four crates: the `extensions.rs`, `path_trie.rs`, and `rewrap.rs` hits are gone; `client.rs` still (correctly) reports the remaining required per-handler clone. - Not tested platform-specifically; the changes are platform-independent. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - N/A |
||
|
|
1a42a2b714 |
Improve lint-creator skill (#60383)
Rewrote `.agents/skills/lint-creator/SKILL.md` to be more concrete and concrete. Release Notes: - N/A |
||
|
|
b16d08d473 |
gpui: Fix stale pending input when a window is blurred (#63271)
This prepares for the keybinding hints PR. To reproduce, press `ctrl-b` in a GPUI app with `ctrl-b h` and `ctrl-b j` bindings, then call `window.blur()`. The live pending state clears, but observers still report `ctrl-b`. `Window::blur` now clears pending input and notifies observers after the current effect cycle. I don't think we currently exercise this path in Zed, and I was only able to reproduce it with an example GPUI app. Release Notes: - N/A |
||
|
|
3ba893e4ac |
editor: Add file permalink support to tabs and the Project Panel (#62177)
# Objective - Add file-level hyperlink support for opening and copying hyperlinks for Git remote source control to project panel and tabs - Unify the language for Git remote hyperlinks across blame, project panels, and tabs to be similar to GitLens' definitions (which are commonly used in VS Code) ## Solution - Updated the Git crate to expose relevant metadata to surface new options within the editor - Added new options for `Open File on Remote` and `Copy Remote File URL` to project panel/file explorer and file tabs - Altered the blame UI options to be consistent with new labels / more clear ## Testing - Ran `cargo run` to boot app and manually smoke test (see proof below) - Added unit tests for this change ## 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/d600ca4f-47e7-438c-90e1-f40124a606b4 --- Release Notes: - Added options to open or copy whole-file permalinks from file tabs and the Project Panel. --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com> |
||
|
|
a3c4abf07c |
gpui: Text input configuration and web implementation (#63264)
Allows setting various attributes for the underlying mirror textarea on the web. Allows GPUI app authors to specify things like "this element should be auto-corrected" --- Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
f7fcd09512 |
agent: Release completed terminal PTY resources (#62978)
Closes #62972 Completed Agent terminal cards remain alive so conversation history can render their output. Each retained terminal also kept its Alacritty PTY sender alive, which retained a poller and one kqueue descriptor after the command exited. Terminal lifecycle state is now more strongly typed to prevent this class of regression. Task terminals are created through a sealed `TerminalMode` API that pairs their running state with the correct completion channel, while PTY resources use explicit active and released states. This makes invalid lifecycle combinations unrepresentable instead of relying on callers to coordinate independent `Option` values correctly. - Release the live PTY sender after final terminal output is captured. - Preserve PTY process metadata and working-directory behavior for historical terminal cards. - Represent PTY resources as explicit active or released lifecycle states. - Construct interactive and task terminals through typed modes so a task cannot omit its running state or use a mismatched completion channel. - Keep resource release idempotent for later ACP release and entity destruction. - Add a macOS regression test that retains the historical terminal entity while exercising the complete sandboxed terminal tool path. Release Notes: - Fixed Agent terminal tool calls leaking file descriptors on macOS. Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
2f3ceb37ce |
open_router: Support effort-based reasoning (#61308)
# Objective - This PR adds support for effort-based reasoning for OpenRouter models - This PR correctly configures whether OpenRouter models support reasoning or not - Fixes #58843 (already closed, was converted to #58848 ) ## Solution - The OpenRouter `/v1/models` endpoint includes data about supported effort levels (see [docs](https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#discovering-per-model-reasoning-options)) and model capabilities - This PR uses this data to populate the "effort" dropdown in the agent panel (compare #56411 which added a similar feature for OpenAI) and to provide better model metadata (`supports_thinking`, `supports_disabling_thinking`). - If a model supports `max_tokens`-based thinking, effort levels will still be shown. OpenRouter automatically converts effort levels into an appropriate `max_tokens` budget ([docs](https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#reasoning-effort-level)). This way users are not limited to a fixed `max_tokens` budget. - Some models return `"supported_parameters": ["reasoning"]` with `"reasoning": {"mandatory": false}`. From the docs I am not quite sure what that's supposed to mean. The PR interprets these models with a binary thinking on/off switch. The PR also fixes the inverted logic where `supports_parallel_tool_calls` would always return `false`, which would then result in `parallel_tool_calls: None` for the actual API call (which enables parallel tool calls by default). So the result of `supports_parallel_tool_calls` was interpreted opposite to what I would expect. The PR now returns `true` from `supports_parallel_tool_calls` and adapts the corresponding call. There is no change in behavior (`parallel_tool_calls` are always enabled in practice), it just fixes the code logic. ## Testing I tested the changes manually in an instance started via `cargo run`: - I tested using GLM 5.2 and GPT 5.5. The reasoning effort is being shown in the agent panel. Changing the effort level changes the amount of thinking that the model does (e.g. on "Extra High" I consistently see thinking blocks, on lower levels I sometimes do. I don't see thinking blocks when thinking is disabled). - Some models with `"reasoning": {"mandatory": false}` can be called with effort levels. I am not sure if it actually makes a difference, but the API doesn't reject it. Maybe there are configuration options that are not currently exposed by this PR. I think the approach in this PR is a safe default though. - To test this PR: 1. Build it via `cargo run` 2. Set an OpenRouter API Key 3. Open the Agent panel and select different models. Notice that the effort level selector and the thinking toggle is dynamically shown/hidden/populated based on the model. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable — Release Notes: - Added support for effort-based reasoning when using OpenRouter models --------- Co-authored-by: Bennet Bo Fenner <bennet@zed.dev> Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de> |
||
|
|
732d67cac8 |
Move language model stream mapping to background executors (#63241)
Language model event mappers run as part of lazy completion streams. Because these streams are polled on the main thread, repairing and parsing large streamed tool inputs can freeze the UI. This moves completion stream mapping to background executors. A bounded channel preserves event order and backpressure, while dropping the stream cancels its background task. The change covers all providers that perform this work. Release Notes: - Fixed UI hangs when language model providers stream large tool inputs. |
||
|
|
34c48d6579 |
Fix project search holding a reference to closed unsaved files (#61677)
# Objective Fixes #28398 ## Solution This issue was occurring because `ProjectSearch` stored `Entity<MultiBuffer>` with has reference counted pointers to underlying buffers The function `remove_deleted_buffers` is renamed to `remove_stale_buffers` and it now also checks for buffers which do not have a file associated with them and are closed. Then, it removes them from `Entity<MultiBuffer>` stored in ProjectSearch. This function is also called in again when workspace is upgraded. ## Testing Bug being fixed was manually verified. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed project search retaining results from closed untitled buffers. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
0a10d97e6a |
Bump Zed to v1.19.0 (#63253)
Release Notes: - N/A Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
918e494e61 |
Improve auto indentation in situations with multiline comments present (#61669)
## Objective Fix incorrect indentation after multiline comments and when pasting multiline code immediately after a comment. Fixes #61668 Fixes #55597 ## Solution - Calculate logical indentation from the opening line of block comments, documentation comments, and multiline strings. - Reuse the logical indentation for both newline handling and multiline paste auto-indent. - Preserve the relative indentation of pasted multiline content while using the logical indentation of the surrounding code as its basis. ## Testing - `cargo test -p editor --lib test_newline -- --nocapture` - `cargo test -p editor --lib test_paste -- --nocapture` - `cargo test -p language --lib test_autoindent -- --nocapture` - `./script/clippy -p language` - `./script/clippy -p editor` - Regression coverage includes Go, TypeScript, and Python comment/string indentation, plus Go multiline paste after a documentation comment. - No platform-specific behavior is involved; the fix is implemented in shared editor and language auto-indent logic. The demonstration video is as follows: https://github.com/user-attachments/assets/2a2ee494-d4ea-4b16-8644-f868b9f31272 https://github.com/user-attachments/assets/9487f893-e584-448d-a1c7-a94c76c03f5b ## 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 incorrect indentation after multiline comments and multiline paste. |
||
|
|
e9b18cd2d5 |
agent: Coalesce thread saves into a single worker (#63053)
# Objective - Reduce excessive RAM usage during long agent sessions. Previously every `Thread::notify` triggered a full serialization of the entire conversation (including any embedded base64 image) to JSON, so streaming bursts queued many large, redundant saves and ballooned memory into the multi-GB range. - Related to #57126. - Related to #62133. ## Solution - Replace the per-notification save task with a single coalescing save worker per session in `crates/agent/src/agent.rs`. - `save_thread` now writes the latest snapshot into an in-place buffer and wakes the worker via a `watch` channel, instead of spawning a fresh full-conversation save on every notification. - The worker drains the buffer in a loop, saving only the latest snapshot per burst (latest-wins coalescing), and preserves save-on-close by draining the final snapshot before exiting. ## Testing - `cargo check -p agent` - `cargo test -p agent test_close_session_saves_thread` - `cargo test -p agent test_save_load_thread` - `cargo test -p agent test_threads_flushed_to_database_on_app_quit` ## 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 (no UI change) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Improved memory usage during long agent sessions. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
5b8e551dc0 |
Reduce LLVM IR bloat (#63232)
Cuts serde monomorphization in settings_content: both parse entry points
now share one deserializer instantiation, and the flatten-heavy settings
structs deserialize through a small manual routing macro instead of
serde's Content buffering.
Parsed values seem to be unchanged; JSON schema and serialization
derives are untouched.
`cargo llvm-lines -p settings_content`:
Before (
|