The rate limiter's semaphore guard was being held for the entire
duration of a turn, including during tool execution. This caused
deadlocks when subagents tried to acquire permits while parent requests
were waiting for them to complete.
## The Problem
In `run_turn_internal`, the stream (which contains the `RateLimitGuard`
holding the semaphore permit) was kept alive throughout the entire loop
iteration - including during **tool execution**:
1. Parent request acquires permit
2. Parent starts streaming, consumes response
3. Parent starts executing tools (subagents)
4. **Stream/guard still held** while tools execute
5. Subagents try to acquire permits → blocked because parent still holds
permit
6. Deadlock if all permits are held by parents waiting for subagent
children
## The Fix
Two changes were made:
1. **Drop the stream early**: Added an explicit `drop(events)` after the
stream is fully consumed but before tool execution begins. This releases
the rate limit permit so subagents can acquire it.
2. **Removed the `bypass_rate_limit` workaround**: Since the root cause
is now fixed, the bypass mechanism is no longer needed.
Note: no release notes because subagents are still feature-flagged, and
this rate limiting change isn't actually observable without them.
Release Notes:
- N/A
Closes https://github.com/zed-industries/zed/issues/47330
This PR moves the queue logic out of the native Thread into the shared
UI layer (thread view) to enable it for external agents. There's a key
difference in behavior, though, between native and external agents:
queued messages in the former will be sent in the next turn boundary,
given we can easily tell this, whereas for the latter, queued messages
will be sent by the end of the generation. We'd need an ACP-level change
to provide exactly the same UX between both types of agents, and I
figured that's better to have _some_ version of the feature for external
agents as opposed to not having it all due to this difference.
Release Notes:
- Agent: Made the message queue feature available for external agents as
well.
Many editors such as vim and emacs support "modelines", a comment at the
beginning of the file that allows the file type to be explicitly
specified along with per-file specific settings
- The amount of configurations, style and settings mapping cannot be
handled in one go, so this opens up a lot of potential improvements.
- I left out the possiblity to have "zed" specific modelines for now,
but this could be potentially interesting.
- Mapping the mode or filetype to zed language names isn't obvious
either. We may want to make it configurable.
This is my first contribution to zed, be kind. I struggled a bit to find
the right place to add those settings. I use a similar approach as done
with editorconfig (merge_with_editorconfig). There might be better ways.
Closes#4762
Release Notes:
- Add basic emacs/vim modeline support.
Supersedes #41899, changes:
- limit reading to the first and last 1kb
- add documentation
- more variables handled
- add Arc around ModelineSettings to avoid extra cloning
- changed the way mode -> language mapping is done, thanks to
`modeline_aliases` language config
- drop vim ex: support
- made "Local Variables:" handling a separate commit, so we can drop it
easily
- various code style improvements
---------
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This PR adds a thinking toggle for controlling whether to use thinking
for a model in the Zed provider:
<img width="645" height="142" alt="Screenshot 2026-01-22 at 12 34 01 PM"
src="https://github.com/user-attachments/assets/9aa543fe-e708-4840-8b38-1a6fbcb78388"
/>
Previously we would create separate "Thinking" variants of the models
that supported thinking in the model selector.
This only applies to Anthropic models in the Zed provider, currently.
This is gated behind the `cloud-thinking-toggle` feature flag.
Release Notes:
- N/A
---------
Co-authored-by: Neel <neel@zed.dev>
## Problem
When subagents use the `edit_file` tool, it creates an `EditAgent` that
makes its own model request to get the edit instructions. These "nested"
requests compete with the parent subagent conversation requests for rate
limiter permits.
The rate limiter uses a semaphore with a limit of 4 concurrent requests
per model instance. When multiple subagents run in parallel:
1. 3 subagents each hold 1 permit for their ongoing conversation streams
(3 permits used)
2. When all 3 try to use `edit_file` simultaneously, their edit agents
need permits too
3. Only 1 edit agent can get the 4th permit; the other 2 block waiting
4. The blocked edit agents can't complete, so their parent subagent
conversations can't complete
5. The parent conversations hold their permits, so the blocked edit
agents stay blocked
6. **Deadlock**
## Solution
Added a `bypass_rate_limit` field to `LanguageModelRequest`. When set to
`true`, the request skips the rate limiter semaphore entirely. The
`EditAgent` sets this flag because its requests are already "part of" a
rate-limited parent request.
(No release notes because subagents are still feature-flagged.)
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Follow-Up-For: #47243
Previously, we would detach tasks spawned to watch config files.
However, the task blocked on receiving a file event before checking if
the receiver for the updates channel was dropped, causing the task to
never exit. The fix here was to return the task explicitly, so that it
can be dropped instead of calling `.detach()` on it. There is definitely
a way to `select!` between the receiver being dropped and the next file
system event, but I couldn't figure it out in a reasonable amount of
time and decided it wasn't worth it.
Release Notes:
- Fixed an issue where a few file descriptors would be leaked each time
a project was closed
This PR adds the ability to edit a queued message, which you can now do
by hitting `cmd-e` from the message editor, which will focus the first
queued message. To pull that off, I'm also making the queued messages
render as an editor, the same way we do with regular user messages. That
way, we ensure less layout shift when focusing in and out of the queued
message for editing and gain the ability to render context
buttons/creases the same way we do in the main message editor.
https://github.com/user-attachments/assets/fb68fd48-c0cd-491f-a7d9-5065a9151b0b
Note that in the video, I show the state in which you're still editing
in the moment in which the queued message would be sent. If that
happens, your queued message won't be sent even if you unfocus the
queued message editor. In this case, you need to explicitly hit "Send
Now".
Release Notes:
- Agent: Added the ability to edit queued messages.
Closes#31351
# Diagnostics Mention in New Threads
## Overview
Adds the `@diagnostics` mention to the new Agent Panel threads so users
can inject current LSP diagnostics (errors by default) without switching
to a text thread. The diagnostics mention is fully integrated into ACP
mention parsing, the context picker, and the message-editor pipeline so
it round-trips cleanly and shows up in the standard `@` menu.
## Context
- **Request:** bring `/diagnostics` parity to the “New Thread” assistant
experience.
- **Scope:** diagnostics only; `/terminal` mention would be implemented
in a separate PR.
- **Docs:** updated Agent Panel docs + changelog.
## Implementation Details
1. **Mention plumbing**
- Added `MentionUri::Diagnostics` to `acp_thread`, including parsing
(`zed:///agent/diagnostics?include_warnings=true`) and icon/name
metadata.
- Tests ensure diagnostics links round-trip via Markdown mention
serialization.
2. **Context picker / completion**
- New `ContextPickerMode::Diagnostics` exposes an `@diagnostics` entry
in the mention menu.
- Completions turn `@diagnostics` into a fully fledged mention, reusing
the existing confirmation pipeline.
3. **Message editor + thread serialization**
- Resolving the mention calls the existing diagnostics collector from
`assistant_slash_commands`, embedding the tool output inline with other
context blocks (`<diagnostics>…</diagnostics>`).
- Thread-link handling ignores diagnostics backlinks so clicking them
doesn’t try to reopen nonexistent resources.
# How it looks
<img width="800" height="480" alt="image"
src="https://cf5gpe8lxo.ufs.sh/f/EmJ5Xl877qJO1mzC9Zrn8AmJZHeShC4RoUwvTMlF2tfPzj06"
/>
Release Notes:
- Allow mentioning diagnostics in the agent panel via `@diagnostics`
---------
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
This makes sure all of the new granular permission logic and ui only
applies to the zed agent and doesn't affect the UI of external agents.
Release Notes:
- N/A
Previously, `always_confirm` patterns would force confirmation even when
`always_allow_tool_actions` was set to true. This was counterintuitive
since the global setting should provide a way to skip all confirmations.
The new precedence order is:
1. **`always_deny`** - still blocks for security
2. **`always_allow_tool_actions`** - when true, allows all non-denied
actions
3. **`always_confirm`** - prompts if `always_allow_tool_actions` is
false
4. **`always_allow`** - allows without prompting
5. **`default_mode`** - fallback behavior
This means setting `always_allow_tool_actions=true` will now skip
confirmation prompts from `always_confirm` patterns and override
`default_mode: Deny` settings, while still respecting `always_deny`
patterns for security.
(No release notes because granular tool permissions are still
feature-flagged.)
Release Notes:
- N/A
This feature cost $12
Release Notes:
- Changed the behavior of queued messages to gracefully wait for the
current activity to complete.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Closes #ISSUE
Reproduction steps:
- Zed main branch
- Use Ollama (likely provider agnostic) in the agent panel with the
following prompt: "Explore the codebase with subagents"
- Panic
```
thread 'main' (36268) panicked at C:\Users\username\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\futures-util-0.3.31\src\stream\unfold.rs:108:21:
Unfold must not be polled after it returned `Poll::Ready(None)`
```
Following the stack trace we get to `Thread::run_turn_internal`. I
believe the panic happens in the following code which was introduced in
#46802
```rust
// Collect all immediately available events to process as a batch
let mut batch = vec![first_event];
while let Some(event) = events.next().now_or_never().flatten() {
batch.push(event);
}
```
Both `Option`s get flattened, however the inner `Option` represents the
end of the stream, after which polling the stream using `.next()` will
result in a panic.
We could fix the logic in this particular spot, but I believe the
simpler solution is to `.fuse()` the stream, which stops the stream from
panic'ing even after it has ended. This also prevents misuse in the
future.
The panic was introduces on main and did not land on a release yet, so
no release notes.
Release Notes:
- N/A *or* Added/Fixed/Improved ...
This PR removes the code for the legacy plans.
No more users will be on this plan as of January 17th, so it's fine to
land these changes now (as they won't be released until the 21st).
Closes CLO-76.
Release Notes:
- N/A
Release Notes:
- Opening bundled files, keymap, and local release notes now opens in
remote windows instead of opening a new local zed window
- Opening the settings files, keymap files, task files, debug files and
logs will now open within wsl windows instead of opening a new local zed
window
This feature cost $15.
Up -> Tokens we're sending to the model
Down -> Tokens we've received from the model.
<img width="377" height="69" alt="Screenshot 2026-01-14 at 12 31 01 PM"
src="https://github.com/user-attachments/assets/fc15824f-de5d-466b-8cc1-329f3c1940bb"
/>
Release Notes:
- Changed the display of tokens for OpenAI models to reflect the
input/output limits.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Closes https://github.com/zed-industries/zed/issues/34402
Release Notes:
- MCP servers can now be run on the remote server when using remote
development. This can be enabled by setting the `"remote": true`
property in the settings entry for the MCP server.
---------
Co-authored-by: localcc <kate@zed.dev>
Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
## Summary
This PR adds the UI for displaying subagent tool calls:
### Thread view changes
- Add `expanded_subagents` state HashMap for tracking expanded cards
- Implement `render_subagent_tool_call()` for collapsed card with label
and chevron
- Add subagent detection via `is_subagent()` and `tool_name` field
- Handle `SubagentThread` content type in tool call rendering
- Add expand/collapse toggle button for subagent cards
- Style collapsed cards similar to terminal tool calls
- Support inline image rendering in content blocks
### Agent panel changes
- Add `open_external_thread_with_server()` for testing with stubbed
servers
### Test support
- Add `acp_thread/test-support` feature to agent_ui
- Add base64 dev dependency for image tests
Release Notes:
- N/A
---------
Co-authored-by: Amp <amp@ampcode.com>
## Problem
Profiling showed that during agent streaming, `thread.rs:1393:23` was
appearing constantly as a hotspot. The issue was that every single token
from the model triggered:
1. `this.update(cx, ...)`
2. `handle_text_event()` (or thinking/redacted_thinking)
3. `cx.notify()`
4. UI re-render
This created significant foreground thread pressure, contributing to
~500ms delays visible in the profiler.
## Solution
Batch all immediately-available events using `now_or_never()` and
process them in a single `update()` call with one `notify()` at the end.
This approach is deterministic - it processes exactly what's available
right now, adapting naturally to network speed:
- When tokens arrive slowly, you get one at a time
- When they arrive in bursts, they batch automatically
## Changes
- Remove `cx.notify()` from `handle_text_event`,
`handle_thinking_event`, and `handle_redacted_thinking_event`
- Batch events in the streaming loop using `now_or_never()`
- Call `cx.notify()` once per batch instead of per-event
- Keep `cx.notify()` in `handle_tool_use_event` for immediate tool
feedback
Release Notes:
- Improve streaming tool call performance by batching UI updates.
Closes#40322
When users run multi-line terminal commands, the confirmation dialog was
only showing the first line with '- N more lines' truncated. This meant
dangerous commands like 'rm -rf' or 'sudo' operations could be hidden
from view, creating a security risk.
Now terminal commands always display in full, with scroll support for
very long commands (20+ lines) to keep the confirmation buttons visible.
Other tools continue using truncation for better UI efficiency since
they don't pose the same security concerns.
Release Notes:
- Agent: Fixed terminal command truncation in the agent panel to better
expose long commands (e.g., potentially dangerous multi-line commands
are now fully visible before execution)
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: dino <dinojoaocosta@gmail.com>
Feature flagged for now as we test this out with actual agents to see if
we need to provide any more feedback to the RFD before committing to the
current setup.
Release Notes:
- N/A
This should move almost all access of the threadstore behind the trait,
which unlocks external agents supplying the list
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Add permission checking to the remaining 7 tools that require granular
permissions:
- `edit_file`: Checks path against permission rules
- `delete_path`: Checks path against permission rules
- `move_path`: Checks both source and destination paths
- `create_directory`: Checks path against permission rules
- `save_file`: Checks all paths, denies if any are blocked
- `fetch`: Checks URL against permission rules
- `web_search`: Checks query against permission rules
Each tool follows the pattern established in PR #46155 (terminal tool):
- `Allow` = proceed without prompting
- `Deny` = return error immediately
- `Confirm` = prompt user for confirmation
The deny > confirm > allow precedence is enforced by the
`decide_permission_from_settings()` function.
Release Notes:
- N/A
---------
Co-authored-by: Amp <amp@ampcode.com>
PR #46306 changed cancellation to wait for tools to complete before
returning. This was correct behavior - it allows tools like terminal to
capture their output on cancellation. The real issue was that many tools
didn't check for cancellation, so they would continue running until they
finished.
## The Problem
When the user pressed Escape to cancel during a tool operation, tools
would continue running because they never checked for the cancellation
signal. The thread correctly waited for tools to complete (so terminal
could capture output), but tools like edit_file, grep, fetch, etc. would
just keep going.
## The Fix
Add cancellation handling to all tools using the same pattern as
`terminal_tool`: use `select!` to race between the tool's main work and
`event_stream.cancelled_by_user()`. When cancelled, tools break out of
their loops or return early.
## All Tools Now Cancellation-Aware
| Tool | Change |
|------|--------|
| `edit_file_tool` | Checks cancellation in edit event processing loop |
| `terminal_tool` | Already handled cancellation |
| `grep_tool` | Checks cancellation in search result iteration loop |
| `fetch_tool` | Checks cancellation during HTTP fetch |
| `web_search_tool` | Checks cancellation during web search |
| `find_path_tool` | Checks cancellation during path search |
| `read_file_tool` | Checks cancellation during buffer open |
| `copy_path_tool` | Checks cancellation during file copy |
| `move_path_tool` | Checks cancellation during file move/rename |
| `delete_path_tool` | Checks cancellation during delete operation |
| `create_directory_tool` | Checks cancellation during directory
creation |
| `save_file_tool` | Checks cancellation during buffer open and save |
| `restore_file_from_disk_tool` | Checks cancellation during buffer open
and reload |
| `open_tool` | Checks cancellation during authorization |
| `diagnostics_tool` | Checks cancellation during buffer open |
| `ContextServerTool` (MCP) | Checks cancellation during external server
calls |
**Synchronous tools (no async work, return immediately):**
- `list_directory_tool` - Reads worktree snapshot synchronously
- `now_tool` - Returns current time immediately
- `thinking_tool` - Returns immediately
## MCP Tools Automatically Handled
MCP tools (user-defined tools via context servers) are now automatically
cancellation-aware without any user action. The `ContextServerTool`
wrapper races the external server request against
`event_stream.cancelled_by_user()`.
## Testing
- Added `CancellationAwareTool` test helper that mirrors the
cancellation pattern
- Updated `test_cancellation_aware_tool_responds_to_cancellation` to
properly await the cancel task and verify the tool detected cancellation
Release Notes:
- Fixed a regression where pressing Escape wouldn't immediately cancel
in-progress tool operations
## Motivation
This PR unifies the async execution infrastructure between GPUI and
other components that depend on the `scheduler` crate (such as our cloud
codebase). By having a scheduler that lives independently of GPUI, we
can enable deterministic testing across the entire stack - testing GPUI
applications alongside cloud services with a single, unified scheduler.
## Summary
This PR completes the integration of the `scheduler` crate into GPUI,
unifying async execution and enabling deterministic testing of GPUI
combined with other components that depend on the scheduler crate.
## Key Changes
### Scheduler Integration (Phases 1-5, previously completed)
- `TestDispatcher` now delegates to `TestScheduler` for timing, clock,
RNG, and task scheduling
- `PlatformScheduler` implements the `Scheduler` trait for production
use
- GPUI executors wrap scheduler executors, selecting `TestScheduler` or
`PlatformScheduler` based on environment
- Unified blocking logic via `Scheduler::block()`
### Dead Code Cleanup
- Deleted orphaned `crates/gpui/src/platform/platform_scheduler.rs`
(older incompatible version)
## Intentional Removals
### `spawn_labeled` and `deprioritize` removed
The `TaskLabel` system (`spawn_labeled`, `deprioritize`) was removed
during this integration. It was only used in a few places for test
ordering control.
cc @maxbrunsfeld @as-cii - The new priority-weighted scheduling in
`TestScheduler` provides similar functionality through
`Priority::High/Medium/Low`. If `deprioritize` is important for specific
test scenarios, we could add it back to the scheduler crate. Let me know
if this is blocking anything.
### `start_waiting` / `finish_waiting` debug methods removed
Replaced by `TracingWaker` in `TestScheduler` - run tests with
`PENDING_TRACES=1` to see backtraces of pending futures when parking is
forbidden.
### Realtime Priority removed
The realtime priority feature was unused in the codebase. I'd prefer to
reintroduce it when we have an actual use case, as the implementation
(bounded channel with capacity 1) could potentially block the main
thread. Having a real use case will help us validate the design.
## Testing
- All GPUI tests pass
- All scheduler tests pass
- Clippy clean
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ GPUI │
│ ┌──────────────────────┐ ┌────────────────────────────┐ │
│ │ gpui::Background- │ │ gpui::ForegroundExecutor │ │
│ │ Executor │ │ - wraps scheduler:: │ │
│ │ - scheduler: Arc< │ │ ForegroundExecutor │ │
│ │ dyn Scheduler> │ └────────────┬───────────────┘ │
│ └──────────┬───────────┘ │ │
│ │ │ │
│ └──────────┬──────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Arc<dyn Scheduler> │ │
│ └───────────┬───────────┘ │
│ ┌──────────────┴──────────────┐ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌────────────────────┐ │
│ │ PlatformScheduler│ │ TestScheduler │ │
│ │ (production) │ │ (deterministic) │ │
│ └──────────────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
Release Notes:
- N/A
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Yara <git@yara.blue>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
This PR adds the foundation for the subagents feature:
- Add `SubagentsFeatureFlag` with staff-disabled default
- Create `SubagentTool` struct with input schema for
task/summary/context-low prompts
- Register `SubagentTool` conditionally when feature flag is enabled
- Tool returns stub message 'not yet implemented' for now
Release Notes:
- N/A
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
Co-authored-by: Yara <yara@zed.dev>
This builds on https://github.com/zed-industries/zed/pull/46112 (which
should be merged first) and adds the permission evaluation logic and
integrates it with the terminal tool as part of the tool permissions
feature. This is a separate PR for [stacked
diffs](https://newsletter.pragmaticengineer.com/p/stacked-diffs) to make
review easier.
## Changes
- **Add `tool_permissions.rs`** with `decide_permission()` function that
implements:
- `deny > confirm > allow` precedence hierarchy (security-critical)
- Case-sensitive and case-insensitive regex matching
- Integration with existing `always_allow_tool_actions` setting
- Comprehensive unit tests (15 tests)
- **Integrate with terminal tool**:
- Commands matching deny rules are blocked immediately with an error
- Commands matching allow rules proceed without confirmation dialog
- Commands requiring confirmation show the dialog as before
- Added integration tests for deny and allow rule scenarios
Co-Authored-By: Claude Opus 4.5
Release Notes:
- N/A
---------
Co-authored-by: Amp <amp@ampcode.com>
I really enjoyed this feature in Claude Code. Helps me get a sense of
how effortful something is.
Release Notes:
- Added a "show_turn_stats" setting, default to false, that shows the
timer and the number of tokens down.
<img width="707" height="778" alt="Screenshot 2026-01-07 at 8 34 00 PM"
src="https://github.com/user-attachments/assets/59842820-079b-4d47-9bdd-f77300f8a60e"
/>
When the user presses Esc or the Stop button to interrupt a thread,
terminal tools now capture their output and include it in the tool
result. This allows the model to see what was happening in the terminal
when the user interrupted, so it can answer questions about the output.
## Changes
- `Thread::cancel()` now returns a `Task` that waits for tools to
respond to cancellation before flushing pending messages
- Terminal tool uses `select!` to detect cancellation signal and
immediately kills the terminal and captures output
- `run_turn_internal` uses `select!` to break out of event loop on
cancel
- Added test for terminal tool cancellation output capture
This is a follow-up to #46218 which added similar functionality for the
"Stop" button on individual terminal tool cards.
Release Notes:
- Interrupting the agent now captures terminal output so the model can
see what was running when you stopped it
Previously, if you stopped the terminal prematurely, the agent would
assume the terminal process had timed out. Now it knows what happened
and can see the output:
<img width="718" height="885" alt="Screenshot 2026-01-07 at 12 40 23 AM"
src="https://github.com/user-attachments/assets/a5ea14b2-249c-4ada-9f20-d6b608f829e5"
/>
Release Notes:
- Stopping the terminal tool now allows the agent to see its output up
to that point.
Now when the agent reads images (which the tool now explicitly
advertises to agents that it is capable of; previously the tool said it
could only read text even though it can actually read images), we see
them in the thread, and also they are auto-expanded by default so you
can see them when scrolling through:
<img width="725" height="1019" alt="Screenshot 2026-01-06 at 2 57 11 PM"
src="https://github.com/user-attachments/assets/5c908bad-48f2-46c2-afaa-7f189a178e05"
/>
This also adds a visual regression test that verifies images render
correctly in the agent thread view.
Unlike our previous visual tests, this one only renders the agent panel,
not the entire Zed window.
The "screenshot" it generates (rendered to a Metal texture) is from
completely mocked/simulated data structures, and looks like this:
<img width="546" height="984" alt="Screenshot 2026-01-06 at 2 54 41 PM"
src="https://github.com/user-attachments/assets/89a0921f-59e9-4dfe-94b2-4c3b625a851b"
/>
## Changes
- **New visual test**: `agent_thread_with_image` renders an
`AcpThreadView` containing a tool call with image content (the Zed app
icon)
- **Test infrastructure**: Added `StubAgentServer` helper and required
feature flags for visual testing
- **Test-support API**: Added `expand_tool_call()` method to
`AcpThreadView` to allow expanding tool calls for visual testing
- **Baseline screenshot**: Included baseline image showing the Zed logo
rendered in a tool call output
## How to run
```bash
# Run the visual tests
cargo run -p zed --bin visual_test_runner --features visual-tests
# Update baselines if UI intentionally changed
UPDATE_BASELINE=1 cargo run -p zed --bin visual_test_runner --features visual-tests
```
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
- **search: Make search cancellation more responsive (again)**
- **Fix project benchmarks build**
- **Less scoping and lifetimes for workers**
Related to #45300
Release Notes:
- Project search will consume less resources immediately after
cancellation.
---------
Co-authored-by: Max Brunsfeld <max@zed.dev>