Commit Graph
644 Commits
Author SHA1 Message Date
Ben Brandt c31ad941fe agent: Encourage more parallel tool use (#47644)
Also standardizes the list format in the prompt

Release Notes:

- N/A
2026-01-26 12:14:46 +00:00
Michael Benfield 9201e1f7b7 Don't always expose streaming edit tool (#47495)
Release Notes:

- N/A
2026-01-23 09:32:27 -08:00
Richard Feldman 29cf14ed2f Fix rate limiter holding permits during tool execution (#47494)
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
2026-01-23 12:15:55 -05:00
Michael Benfield 21f49eba7a agent: Ensure the activity bar shows up with the StreamingEditFileTool (#47417)
Release Notes:

- N/A
2026-01-23 08:07:26 -08:00
Jakub Konka 3a7c746043 Revert " Add vim/emacs modeline support " (#47479)
Reverts zed-industries/zed#44210

I am forced to revert this PR as it completely breaks release builds
with the following panic:

```
thread 'main' (2648653) panicked at crates/rope/src/rope.rs:893:25:
byte index 73 is not a char boundary; it is inside 'স' (bytes 71..74) of `কৰক</translation>
<translation id="9216898458513705996">টেবসমূহ এই ডিভাইচত খোলা `
stack backtrace:
2026-01-23T15:37:48+01:00 INFO  [node_runtime] using Zed managed Node.js at /Users/kubkon/Library/Application Support/Zed/node/node-v24.11.0-darwin-arm64 since system Node.js wasn't found on PATH: cannot find binary path
   0: __rustc::rust_begin_unwind
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/std/src/panicking.rs:698:5
   1: core::panicking::panic_fmt
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:80:14
   2: core::str::slice_error_fail_rt
   3: core::str::slice_error_fail
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/str/mod.rs:69:5
   4: core::str::traits::<impl core::slice::index::SliceIndex<str> for core::ops::range::Range<usize>>::index
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/str/traits.rs:248:21
   5: <str as core::ops::index::Index<core::ops::range::Range<usize>>>::index
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/str/traits.rs:63:15
   6: <rope::Chunks>::peek
             at /Users/kubkon/dev/zed/crates/rope/src/rope.rs:893:25
   7: <rope::Lines>::next
             at /Users/kubkon/dev/zed/crates/rope/src/rope.rs:1111:45
   8: <project::lsp_store::LspStore>::parse_modeline
             at /Users/kubkon/dev/zed/crates/project/src/lsp_store.rs:4570:43
   9: <project::lsp_store::LspStore>::on_buffer_added
             at /Users/kubkon/dev/zed/crates/project/src/lsp_store.rs:4301:14
  10: <project::lsp_store::LspStore>::on_buffer_store_event
             at /Users/kubkon/dev/zed/crates/project/src/lsp_store.rs:4166:22
  11: <<project::lsp_store::LspStore>::on_buffer_store_event as core::ops::function::FnMut<(&mut project::lsp_store::LspStore, gpui::app::entity_map::Entity<project::buffer_store::BufferStore>, &project::buffer_store::BufferStoreEvent, &mut gpui::app::context::Context<project::lsp_store::LspStore>)>>::call_mut
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/ops/function.rs:166:5
  12: <gpui::app::context::Context<project::lsp_store::LspStore>>::subscribe::<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <project::lsp_store::LspStore>::on_buffer_store_event>::{closure#0}::{closure#0}
             at /Users/kubkon/dev/zed/crates/gpui/src/app/context.rs:111:44
  13: <gpui::app::App as gpui::AppContext>::update_entity::<project::lsp_store::LspStore, (), <gpui::app::context::Context<project::lsp_store::LspStore>>::subscribe<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <project::lsp_store::LspStore>::on_buffer_store_event>::{closure#0}::{closure#0}>::{closure#0}
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:2281:26
  14: <gpui::app::App>::update::<(), <gpui::app::App as gpui::AppContext>::update_entity<project::lsp_store::LspStore, (), <gpui::app::context::Context<project::lsp_store::LspStore>>::subscribe<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <project::lsp_store::LspStore>::on_buffer_store_event>::{closure#0}::{closure#0}>::{closure#0}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:818:22
  15: <gpui::app::App as gpui::AppContext>::update_entity::<project::lsp_store::LspStore, (), <gpui::app::context::Context<project::lsp_store::LspStore>>::subscribe<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <project::lsp_store::LspStore>::on_buffer_store_event>::{closure#0}::{closure#0}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:2279:14
  16: <gpui::app::entity_map::Entity<project::lsp_store::LspStore>>::update::<(), gpui::app::App, <gpui::app::context::Context<project::lsp_store::LspStore>>::subscribe<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <project::lsp_store::LspStore>::on_buffer_store_event>::{closure#0}::{closure#0}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app/entity_map.rs:445:12
  17: <gpui::app::context::Context<project::lsp_store::LspStore>>::subscribe::<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <project::lsp_store::LspStore>::on_buffer_store_event>::{closure#0}
             at /Users/kubkon/dev/zed/crates/gpui/src/app/context.rs:111:22
  18: <gpui::app::App>::subscribe_internal::<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <gpui::app::context::Context<project::lsp_store::LspStore>>::subscribe<project::buffer_store::BufferStore, project::buffer_store::BufferStoreEvent, <project::lsp_store::LspStore>::on_buffer_store_event>::{closure#0}>::{closure#0}
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:964:25
  19: <alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>> as core::ops::function::FnMut<(&dyn core::any::Any, &mut gpui::app::App)>>::call_mut
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/alloc/src/boxed.rs:2012:9
  20: <gpui::app::App>::apply_emit_effect::{closure#0}
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:1407:21
  21: <gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain::<<gpui::app::App>::apply_emit_effect::{closure#0}>::{closure#1}
             at /Users/kubkon/dev/zed/crates/gpui/src/subscription.rs:132:17
  22: <alloc::collections::btree::map::BTreeMap<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>>::retain::<<gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain<<gpui::app::App>::apply_emit_effect::{closure#0}>::{closure#1}>::{closure#0}
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/alloc/src/collections/btree/map.rs:1177:37
  23: <alloc::collections::btree::map::ExtractIfInner<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>, core::ops::range::RangeFull>>::next::<<alloc::collections::btree::map::BTreeMap<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>>::retain<<gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain<<gpui::app::App>::apply_emit_effect::{closure#0}>::{closure#1}>::{closure#0}, alloc::alloc::Global>
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/alloc/src/collections/btree/map.rs:2036:16
  24: <alloc::collections::btree::map::ExtractIf<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>, core::ops::range::RangeFull, <alloc::collections::btree::map::BTreeMap<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>>::retain<<gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain<<gpui::app::App>::apply_emit_effect::{closure#0}>::{closure#1}>::{closure#0}> as core::iter::traits::iterator::Iterator>::next
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/alloc/src/collections/btree/map.rs:2002:20
  25: <alloc::collections::btree::map::ExtractIf<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>, core::ops::range::RangeFull, <alloc::collections::btree::map::BTreeMap<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>>::retain<<gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain<<gpui::app::App>::apply_emit_effect::{closure#0}>::{closure#1}>::{closure#0}> as core::iter::traits::iterator::Iterator>::fold::<(), core::iter::traits::iterator::Iterator::for_each::call<(usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>), core::mem::drop<(usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>)>>::{closure#0}>
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/iter/traits/iterator.rs:2602:34
  26: <alloc::collections::btree::map::ExtractIf<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>, core::ops::range::RangeFull, <alloc::collections::btree::map::BTreeMap<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>>::retain<<gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain<<gpui::app::App>::apply_emit_effect::{closure#0}>::{closure#1}>::{closure#0}> as core::iter::traits::iterator::Iterator>::for_each::<core::mem::drop<(usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>)>>
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/iter/traits/iterator.rs:828:14
  27: <alloc::collections::btree::map::BTreeMap<usize, gpui::subscription::Subscriber<(core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>>::retain::<<gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain<<gpui::app::App>::apply_emit_effect::{closure#0}>::{closure#1}>
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/alloc/src/collections/btree/map.rs:1177:46
  28: <gpui::subscription::SubscriberSet<gpui::app::entity_map::EntityId, (core::any::TypeId, alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::FnMut<(&'a dyn core::any::Any, &'b mut gpui::app::App), Output = bool>>)>>::retain::<<gpui::app::App>::apply_emit_effect::{closure#0}>
             at /Users/kubkon/dev/zed/crates/gpui/src/subscription.rs:130:21
  29: <gpui::app::App>::apply_emit_effect
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:1405:14
  30: <gpui::app::App>::flush_effects
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:1308:31
  31: <gpui::app::App>::finish_update
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:830:18
  32: <gpui::app::App>::update::<core::result::Result<(), anyhow::Error>, <gpui::app::App as gpui::AppContext>::update_entity<project::buffer_store::BufferStore, core::result::Result<(), anyhow::Error>, <project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}::{closure#0}::{closure#3}>::{closure#0}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:819:14
  33: <gpui::app::App as gpui::AppContext>::update_entity::<project::buffer_store::BufferStore, core::result::Result<(), anyhow::Error>, <project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}::{closure#0}::{closure#3}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:2279:14
  34: <gpui::app::async_context::AsyncApp as gpui::AppContext>::update_entity::<project::buffer_store::BufferStore, core::result::Result<(), anyhow::Error>, <project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}::{closure#0}::{closure#3}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app/async_context.rs:65:13
  35: <gpui::app::entity_map::WeakEntity<project::buffer_store::BufferStore>>::update::<gpui::app::async_context::AsyncApp, core::result::Result<(), anyhow::Error>, <project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}::{closure#0}::{closure#3}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app/entity_map.rs:750:15
  36: <project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}::{closure#0}::<i32>
             at /Users/kubkon/dev/zed/crates/project/src/buffer_store.rs:683:18
  37: <gpui::app::context::Context<project::buffer_store::BufferStore>>::spawn::<<project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}::{closure#0}::<i32>
             at /Users/kubkon/dev/zed/crates/gpui/src/app/context.rs:244:52
  38: <gpui::app::App>::spawn::<<gpui::app::context::Context<project::buffer_store::BufferStore>>::spawn<<project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:1532:44
  39: <scheduler::executor::spawn_local_with_source_location::Checked<<gpui::app::App>::spawn<<gpui::app::context::Context<project::buffer_store::BufferStore>>::spawn<<project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}> as core::future::future::Future>::poll
             at /Users/kubkon/dev/zed/crates/scheduler/src/executor.rs:393:64
  40: <async_task::raw::RawTask<scheduler::executor::spawn_local_with_source_location::Checked<<gpui::app::App>::spawn<<gpui::app::context::Context<project::buffer_store::BufferStore>>::spawn<<project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}>, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>, <scheduler::executor::ForegroundExecutor>::spawn<<gpui::app::App>::spawn<<gpui::app::context::Context<project::buffer_store::BufferStore>>::spawn<<project::buffer_store::LocalBufferStore>::open_buffer::{closure#1}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}, core::result::Result<gpui::app::entity_map::Entity<language::buffer::Buffer>, anyhow::Error>>::{closure#0}>::{closure#0}, scheduler::RunnableMeta>>::run
             at /Users/kubkon/.cargo/git/checkouts/async-task-e468f817236eac43/b4486cd/src/raw.rs:296:17
  41: <async_task::runnable::Runnable<scheduler::RunnableMeta>>::run
             at /Users/kubkon/.cargo/git/checkouts/async-task-e468f817236eac43/b4486cd/src/runnable.rs:788:18
  42: gpui::platform::mac::dispatcher::trampoline
             at /Users/kubkon/dev/zed/crates/gpui/src/platform/mac/dispatcher.rs:248:14
  43: <unknown>
  44: <unknown>
  45: <unknown>
  46: <unknown>
  47: <unknown>
  48: <unknown>
  49: <unknown>
  50: <unknown>
  51: <unknown>
  52: <unknown>
  53: <unknown>
  54: <unknown>
  55: <unknown>
  56: <unknown>
  57: <unknown>
  58: <gpui::platform::mac::platform::MacPlatform as gpui::platform::Platform>::run
             at /Users/kubkon/dev/zed/crates/gpui/src/platform/mac/platform.rs:473:17
  59: <gpui::app::Application>::run::<zed::main::{closure#9}>
             at /Users/kubkon/dev/zed/crates/gpui/src/app.rs:192:18
  60: zed::main
             at /Users/kubkon/dev/zed/crates/zed/src/main.rs:419:9
  61: <fn() as core::ops::function::FnOnce<()>>::call_once
             at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```

cc @ConradIrwin @elmarco
2026-01-23 15:24:37 +00:00
Danilo Leal 4333d6b472 agent_ui: Enable the message queue feature for external agents (#47379)
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.
2026-01-23 08:36:55 -03:00
4186e5764f Add vim/emacs modeline support (#44210)
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>
2026-01-23 07:55:39 +00:00
Marshall BowersandNeel ec981b8301 agent: Add thinking toggle for Zed provider (#47407)
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>
2026-01-22 18:08:32 +00:00
Ben Brandt 03a5f7b07f acp_thread: Rename resume to retry (#47370)
Changing the name to better capture what this message does and also
avoid confusion with the actual session/resume method in ACP

Release Notes:

- N/A
2026-01-22 11:39:46 +00:00
Ben Brandt c35d1da245 acp: Support the session_info_update notification (#47363)
Release Notes:

- N/A
2026-01-22 11:06:13 +00:00
Michael Benfield 6b5c06e323 Add a streaming edit file tool (#47244)
Release Notes:

- N/A
2026-01-21 09:41:03 -08:00
Richard FeldmanandZed Zippy 21050e2d37 Fix nested request rate limiting deadlock for subagent edit_file (#47232)
## 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>
2026-01-20 21:51:54 -05:00
Ben Kunkle d63067762a Fix config file watch task leak (#47246)
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
2026-01-20 15:58:35 -05:00
Danilo Leal 2ccca66dc1 agent_ui: Add support for editing queued messages (#47234)
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.
2026-01-20 17:26:30 -03:00
Mikhail PertsevandBennet Bo Fenner d71fe4cc7f agent_ui: Add @diagnostics mention to the thread (#42270)
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>
2026-01-20 13:19:24 +00:00
Ben Brandt 36873662cf agent: Make sure ACP still gets classic tool permission UI (#47142)
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
2026-01-19 14:47:04 +01:00
Richard Feldman 258d9223e4 Make always_allow_tool_actions override always_confirm and default_mode (#47012)
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
2026-01-16 18:18:39 -05:00
Ben Brandt 43d5326075 acp: Support loading a session for external agents (#46992)
Release Notes:

- N/A
2026-01-16 16:05:43 +00:00
Ben Brandt 59707157af agent: Move thread loading to the AgentConnection (#46985)
Preps for external agents being able to load a thread

Release Notes:

- N/A
2026-01-16 14:52:00 +01:00
Mikayla MakiandClaude Opus 4.5 f1a8b05391 agent: End turn at message boundary when queue has pending messages (#46980)
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>
2026-01-16 02:17:08 -08:00
Marshall Bowers a92df1eee4 Remove Burn Mode code (#46950)
This PR removes the code for Burn Mode, as we won't need it anymore
after the 17th.

Closes CLO-79.

Release Notes:

- N/A
2026-01-15 21:28:33 +00:00
tidely 20163f1bc4 agent: Fix panic caused by polling ended stream (#46839)
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 ...
2026-01-15 14:03:31 -05:00
Marshall Bowers 6fcc5e9461 Remove legacy billing code (#46927)
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
2026-01-15 13:06:45 -05:00
Lukas Wirth 3d0222a5af remote: Support opening builtin host files in remote workspaces on wsl (#46910)
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
2026-01-15 15:21:57 +00:00
Mikayla MakiandClaude Opus 4.5 9c5fc6ecbd Split token display for OpenAI (#46829)
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>
2026-01-14 14:29:56 -08:00
cd41a21ca7 Allow running MCP servers on the remote server when using remote development (#46756)
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>
2026-01-14 14:41:22 -05:00
4791e1ddc4 Granular Tool Permission Buttons (#46284)
Adds buttons for confirming (and optionally persisting) granular
permissions on tool calls:

<img width="688" height="302" alt="Screenshot 2026-01-14 at 1 58 40 PM"
src="https://github.com/user-attachments/assets/3228cc39-efd5-4a73-989f-ddb28969847f"
/>
<img width="690" height="282" alt="Screenshot 2026-01-14 at 1 58 31 PM"
src="https://github.com/user-attachments/assets/8367a888-5728-4877-a502-1ff20ac929ec"
/>

## Features

### Tool Permission Settings
- **Per-tool rules** in `agent.tool_permissions.tools.<tool_name>`:
  - `default_mode`: `"allow"`, `"deny"`, or `"confirm"` (default)
  - `always_allow`: Array of regex patterns to auto-approve
  - `always_deny`: Array of regex patterns to block
  - `always_confirm`: Array of regex patterns requiring confirmation
- **Supported tools**: `terminal`, `edit_file`, `delete_path`,
`move_path`, `create_directory`, `save_file`, `copy_path`, `fetch`,
`web_search`
- **MCP tool support**: Third-party tools from context servers with
`mcp:<server>:<tool>` naming

### Smart Permission Buttons
When a tool requires confirmation, the dialog shows contextual buttons:
- **"Always allow \`<tool>\`"** - Sets `default_mode = "allow"` for the
tool
- **"Always allow \`<pattern>\`"** - Adds a pattern to `always_allow`:
  - Terminal: Command name (e.g., `cargo`, `npm`, `git`)
  - File tools: Parent directory path
  - URL tools: Domain name
- **"Allow"** / **"Deny"** - One-time decision

### Pattern Extraction
Automatically extracts meaningful patterns from tool inputs:
- Terminal commands → `^cargo\s`, `^npm\s`, etc.
- File paths → `^/Users/alice/project/src/`
- URLs → `^https?://github\.com`

### Invalid Pattern Handling
- Malformed regex patterns are detected at settings load time
- Tools with invalid patterns show an error and block execution
- Clear error messages identify which pattern failed

## Changes

### New Files
- `crates/agent/src/tool_permissions.rs` - Permission evaluation logic
- `crates/agent/src/pattern_extraction.rs` - Pattern extraction
functions

### Modified Files
- `crates/agent_settings/src/agent_settings.rs` - `ToolPermissions`,
`ToolRules` structs
- `crates/settings/src/settings_content/agent.rs` - Settings schema and
serialization
- `crates/settings/src/settings_file.rs` - Helper methods for modifying
settings
- `crates/agent/src/thread.rs` - `authorize_with_context()`,
`authorize_third_party_tool()` methods
- `crates/agent/src/tools/*.rs` - Updated all granular tools to use
permission system
- `crates/agent/src/tools/context_server_registry.rs` - MCP tool
authorization
- `crates/agent_ui/src/acp/thread_view.rs` - Permission button UI,
removed Keep/Reject buttons

## Example Configuration

```json
{
  "agent": {
    "tool_permissions": {
      "tools": {
        "terminal": {
          "default_mode": "confirm",
          "always_allow": ["^cargo\\s", "^npm\\s", "^git\\s"],
          "always_deny": ["^rm\\s+-rf", "^sudo\\s"]
        },
        "edit_file": {
          "default_mode": "allow",
          "always_deny": ["^\\.env", "^/etc/"]
        },
        "mcp:filesystem:write_file": {
          "default_mode": "confirm"
        }
      }
    }
  }
}
```

Release Notes:

- You can now set per-tool permissions when confirming/denying tool use

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Michael Benfield <mbenfield@zed.dev>
2026-01-14 19:39:04 +00:00
Richard FeldmanandAmp 581e559002 Render subagents in thread (#46188)
## 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>
2026-01-14 13:49:51 -05:00
Richard Feldman 5e9634c718 Batch completion events to reduce notify() calls during streaming (#46802)
## 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.
2026-01-14 12:14:28 -05:00
8150d59b27 agent: Fix terminal command truncation in confirmation dialogs (#40570)
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>
2026-01-14 13:40:12 -03:00
Ben Brandt cd12d45e4a agent: Initial support for ACP session listing (#46796)
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
2026-01-14 14:41:31 +01:00
4aa3cd07c3 Revert "Revert scheduler update (#46659)" (#46671)
Reland the new scheduler

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-01-14 07:19:13 +00:00
Conrad Irwin 8b4ab260e6 Revert scheduler update (#46659)
Reverts the new scheduler; it's destroyed our CI

Release Notes:

- N/A
2026-01-12 16:46:15 -07:00
Ben BrandtandZed Zippy 291611e3db agent: Move thread history access behind AgentConnection trait (#46631)
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>
2026-01-12 21:42:12 +00:00
Richard FeldmanandAmp 756637fef5 Subagents PR 2: Thread spawning + execution (#46187)
This PR implements the behind-the-scenes subagent execution logic:

### Core subagent execution
- Add `Thread::new_subagent()` constructor for creating subagent threads
- Implement `SubagentTool::run()` to spawn and manage subagent lifecycle
- Add `SubagentContext` for parent-child thread relationship
- Implement `submit_user_message()`, `interrupt_for_summary()`,
`request_final_summary()`
- Add timeout support and context-low detection (25% threshold)
- Propagate cancellation from parent to child threads

### Thread management
- Add `MAX_SUBAGENT_DEPTH` (4) and `MAX_PARALLEL_SUBAGENTS` (8) limits
- Add `register/unregister_running_subagent()` for tracking
- Add `restrict_tools()` for allowed_tools filtering
- Add `is_subagent()`, `depth()`, `is_turn_complete()` accessors

### Thread changes
- Add `ToolCallContent::SubagentThread` variant
- Add `ToolCallUpdateSubagentThread` for UI updates
- Add `tool_name` field for subagent detection
- Add `is_subagent()` method on `ToolCall`
- Add image support in `ContentBlock`

Release Notes:

- N/A

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-12 18:07:41 +00:00
Richard FeldmanandAmp 2b6e935b09 Add remaining tool permissions (#46164)
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>
2026-01-12 11:08:06 -05:00
Richard Feldman ecc3928040 Fix cancellation regression: make edit_file_tool handle cancellation (#46527)
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
2026-01-11 00:30:25 +00:00
73d935330e Integrate scheduler crate into GPUI (#44810)
## 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>
2026-01-10 15:41:49 +01:00
Ben Brandt a94157714a agent: Split up Agent and Text Thread History (#46457)
Scopes the history to the individual panes and paves the way for history
per external agent.

Release Notes:

- N/A
2026-01-09 17:13:00 +00:00
Richard Feldman 295f9d6ff9 Add guidance for terminal tool about being a pty (#46417)
Release Notes:

- N/A
2026-01-09 04:13:36 +00:00
acbb32d19f Subagents PR 1: Feature flag + tool skeleton (#46186)
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>
2026-01-08 22:53:02 -05:00
Richard FeldmanClaude Opus 4.5Amp
274b1f3ac9 Add tool permission evaluation logic (#46155)
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>
2026-01-08 22:49:15 -05:00
Mikayla Maki 06bd9005ab agent: Add turn statistics to agent panel (#46390)
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.
2026-01-09 00:33:38 +00:00
Richard Feldman 9be436b1ef Capture terminal output when thread is interrupted (#46306)
<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
2026-01-08 09:40:56 -05:00
Mikayla MakiandClaude Opus 4.5 97c35c084b gpui: Actually remove the Result from AsyncApp (#45809)
Depends on: https://github.com/zed-industries/zed/pull/45768

Refactor plan:
https://gist.github.com/mikayla-maki/6c4bf263fd80050715ba01f45478796e
Overall plan:
https://gist.github.com/mikayla-maki/7bb5078e4385a2e683e1e1eb40d17d38

This is the big one.

Release Notes:

- N/A

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 12:48:24 -08:00
Richard Feldman 69acab7f81 Let agent see output of killed terminal tools (#46218)
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.
2026-01-07 10:58:18 -05:00
Bo HeandKunall Banerjee a1bacce89a agent: Remove extraneous character in system_prompt template (#46238)
Release Notes:
- N/A

---------

Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
2026-01-07 04:45:16 -05:00
b5ac0f9bc6 Render images in agent threads (#46167)
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>
2026-01-06 19:48:49 -05:00
Mikayla MakiandMarshall Bowers 3da926981c Add agent thread sharing (#46140)
Staff only ship for now

Here's the agent planning doc that guided this:
https://gist.github.com/mikayla-maki/c826b7997bd85b58273c1def9397940b

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2026-01-06 12:49:51 -08:00
Piotr OsiewiczandMax Brunsfeld 843be766df project search: Make cancellation smoother (#45406)
- **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>
2025-12-30 15:11:05 +01:00