Files
zed/crates/agent/src/tools.rs
T
Bennet Bo Fenner 04269c5fd0 agent: Stream new_text in StreamingEditFileTool (#50240)
We now stream the new text into the buffer as soon as we receive partial
chunks of `new_text`. This is pretty much a full re-write of the way
streaming worked, which is now much closer to how the edit agent works:
- `ToolEditParser` buffers chunks as they stream in, and emits relevant
events (`OldTextChunk`,`NewTextChunk`, ...) that we use to power the
`EditSession` pipeline.
- `EditSession::process_events` takes care of consuming these events and
applying the edits incrementally as chunks stream in. `EditPipeline`
maintains the underlying state machine for each edit.
- We handle whitespace mismatches similar to the edit agent, the code is
shared by moving that logic to `reindent.rs`

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- N/A
2026-02-27 13:24:57 +01:00

137 lines
3.7 KiB
Rust

mod context_server_registry;
mod copy_path_tool;
mod create_directory_tool;
mod delete_path_tool;
mod diagnostics_tool;
mod edit_file_tool;
mod fetch_tool;
mod find_path_tool;
mod grep_tool;
mod list_directory_tool;
mod move_path_tool;
mod now_tool;
mod open_tool;
mod read_file_tool;
mod restore_file_from_disk_tool;
mod save_file_tool;
mod spawn_agent_tool;
mod streaming_edit_file_tool;
mod terminal_tool;
mod tool_edit_parser;
mod tool_permissions;
mod web_search_tool;
use crate::AgentTool;
use language_model::{LanguageModelRequestTool, LanguageModelToolSchemaFormat};
pub use context_server_registry::*;
pub use copy_path_tool::*;
pub use create_directory_tool::*;
pub use delete_path_tool::*;
pub use diagnostics_tool::*;
pub use edit_file_tool::*;
pub use fetch_tool::*;
pub use find_path_tool::*;
pub use grep_tool::*;
pub use list_directory_tool::*;
pub use move_path_tool::*;
pub use now_tool::*;
pub use open_tool::*;
pub use read_file_tool::*;
pub use restore_file_from_disk_tool::*;
pub use save_file_tool::*;
pub use spawn_agent_tool::*;
pub use streaming_edit_file_tool::*;
pub use terminal_tool::*;
pub use tool_permissions::*;
pub use web_search_tool::*;
macro_rules! tools {
($($tool:ty),* $(,)?) => {
/// Every built-in tool name, determined at compile time.
pub const ALL_TOOL_NAMES: &[&str] = &[
$(<$tool>::NAME,)*
];
const _: () = {
const fn str_eq(a: &str, b: &str) -> bool {
let a = a.as_bytes();
let b = b.as_bytes();
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}
const NAMES: &[&str] = ALL_TOOL_NAMES;
let mut i = 0;
while i < NAMES.len() {
let mut j = i + 1;
while j < NAMES.len() {
if str_eq(NAMES[i], NAMES[j]) {
panic!("Duplicate tool name in tools! macro");
}
j += 1;
}
i += 1;
}
};
/// Returns whether the tool with the given name supports the given provider.
pub fn tool_supports_provider(name: &str, provider: &language_model::LanguageModelProviderId) -> bool {
$(
if name == <$tool>::NAME {
return <$tool>::supports_provider(provider);
}
)*
false
}
/// A list of all built-in tools
pub fn built_in_tools() -> impl Iterator<Item = LanguageModelRequestTool> {
fn language_model_tool<T: AgentTool>() -> LanguageModelRequestTool {
LanguageModelRequestTool {
name: T::NAME.to_string(),
description: T::description().to_string(),
input_schema: T::input_schema(LanguageModelToolSchemaFormat::JsonSchema).to_value(),
use_input_streaming: T::supports_input_streaming(),
}
}
[
$(
language_model_tool::<$tool>(),
)*
]
.into_iter()
}
};
}
tools! {
CopyPathTool,
CreateDirectoryTool,
DeletePathTool,
DiagnosticsTool,
EditFileTool,
FetchTool,
FindPathTool,
GrepTool,
ListDirectoryTool,
MovePathTool,
NowTool,
OpenTool,
ReadFileTool,
RestoreFileFromDiskTool,
SaveFileTool,
SpawnAgentTool,
TerminalTool,
WebSearchTool,
}