Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:36:27.949Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

rename_tool.rs

126 lines · 3.8 KB · rust
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
Served at tenant.openagents/omega Member data and write actions are omitted.