Skip to repository content126 lines · 3.8 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T02:36:27.949Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
rename_tool.rs
1use std::fmt::Write;
2use std::sync::Arc;
3
4use agent_client_protocol::schema::v1 as acp;
5use collections::HashSet;
6use gpui::{App, Entity, SharedString, Task};
7use project::Project;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10
11use super::symbol_locator::SymbolLocator;
12use crate::{AgentTool, ToolCallEventStream, ToolInput};
13
14/// Renames a symbol across the project using the language server.
15///
16/// This performs a semantic rename, updating all references to the symbol across all files in the project. The language server determines which occurrences to rename based on the symbol's type and scope.
17///
18/// Before using this tool, use read_file or grep to find the exact symbol name and line number.
19#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
20pub struct RenameToolInput {
21 /// The symbol to rename.
22 pub symbol: SymbolLocator,
23
24 /// The new name for the symbol.
25 pub new_name: String,
26}
27
28pub struct RenameTool {
29 project: Entity<Project>,
30}
31
32impl RenameTool {
33 pub fn new(project: Entity<Project>) -> Self {
34 Self { project }
35 }
36}
37
38impl AgentTool for RenameTool {
39 type Input = RenameToolInput;
40 type Output = String;
41
42 const NAME: &'static str = "rename_symbol";
43
44 fn kind() -> acp::ToolKind {
45 acp::ToolKind::Other
46 }
47
48 fn initial_title(
49 &self,
50 input: Result<Self::Input, serde_json::Value>,
51 _cx: &mut App,
52 ) -> SharedString {
53 if let Ok(input) = input {
54 format!(
55 "Rename `{}` to `{}`",
56 input.symbol.symbol_name, input.new_name
57 )
58 .into()
59 } else {
60 "Rename symbol".into()
61 }
62 }
63
64 fn run(
65 self: Arc<Self>,
66 input: ToolInput<Self::Input>,
67 _event_stream: ToolCallEventStream,
68 cx: &mut App,
69 ) -> Task<Result<String, String>> {
70 let project = self.project.clone();
71 cx.spawn(async move |cx| {
72 let input = input
73 .recv()
74 .await
75 .map_err(|e| format!("Failed to receive tool input: {e}"))?;
76
77 let resolved = input.symbol.resolve(&project, cx).await?;
78
79 let rename_task = project.update(cx, |project, cx| {
80 project.perform_rename(
81 resolved.buffer.clone(),
82 resolved.position,
83 input.new_name.clone(),
84 cx,
85 )
86 });
87
88 let transaction = rename_task
89 .await
90 .map_err(|e| format!("Rename failed: {e}"))?;
91
92 if transaction.0.is_empty() {
93 return Ok(format!(
94 "No changes were made. The language server could not rename '{}'.",
95 input.symbol.symbol_name
96 ));
97 }
98
99 let buffers = transaction.0.keys().cloned().collect::<HashSet<_>>();
100 project
101 .update(cx, |project, cx| project.save_buffers(buffers, cx))
102 .await
103 .map_err(|e| format!("Rename succeeded, but failed to save renamed files: {e}"))?;
104
105 let mut output = format!(
106 "Renamed `{}` to `{}` in {} file(s):\n",
107 input.symbol.symbol_name,
108 input.new_name,
109 transaction.0.len()
110 );
111
112 for (buffer, _) in &transaction.0 {
113 buffer.read_with(cx, |buffer, cx| {
114 let path = buffer
115 .file()
116 .map(|f| f.full_path(cx).display().to_string())
117 .unwrap_or_else(|| "<untitled>".to_string());
118 writeln!(output, "- {path}").ok();
119 });
120 }
121
122 Ok(output)
123 })
124 }
125}
126