From 18f3f8097f2ac8c8f7610f1cb8defe7041eba46a Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 7 Mar 2025 17:41:56 -0500 Subject: [PATCH] assistant_tool: Decouple `Tool` from `Workspace` (#26309) This PR decouples the `Tool` trait from the `Workspace` (and from the UI, in general). `Tool::run` now takes a `WeakEntity` instead of a `WeakEntity` and a `Window`. Release Notes: - N/A --- Cargo.lock | 5 +---- crates/assistant2/src/active_thread.rs | 10 +++++----- crates/assistant2/src/assistant_panel.rs | 10 +++++----- crates/assistant_tool/Cargo.toml | 2 +- crates/assistant_tool/src/assistant_tool.rs | 7 +++---- crates/assistant_tools/Cargo.toml | 1 - crates/assistant_tools/src/list_worktrees_tool.rs | 13 +++++-------- crates/assistant_tools/src/now_tool.rs | 6 +++--- crates/assistant_tools/src/read_file_tool.rs | 13 +++++-------- crates/context_server/Cargo.toml | 1 - crates/context_server/src/context_server_tool.rs | 5 ++--- crates/scripting_tool/Cargo.toml | 2 -- crates/scripting_tool/src/scripting_tool.rs | 12 +++++------- 13 files changed, 35 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acec73fa6ba81e..9004719ae87873 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -658,9 +658,9 @@ dependencies = [ "derive_more", "gpui", "parking_lot", + "project", "serde", "serde_json", - "workspace", ] [[package]] @@ -675,7 +675,6 @@ dependencies = [ "schemars", "serde", "serde_json", - "workspace", ] [[package]] @@ -3140,7 +3139,6 @@ dependencies = [ "smol", "url", "util", - "workspace", ] [[package]] @@ -11930,7 +11928,6 @@ dependencies = [ "serde_json", "settings", "util", - "workspace", ] [[package]] diff --git a/crates/assistant2/src/active_thread.rs b/crates/assistant2/src/active_thread.rs index 1696305a7121b0..c3181b422c0e2b 100644 --- a/crates/assistant2/src/active_thread.rs +++ b/crates/assistant2/src/active_thread.rs @@ -11,11 +11,11 @@ use gpui::{ use language::{Buffer, LanguageRegistry}; use language_model::{LanguageModelRegistry, LanguageModelToolUseId, Role}; use markdown::{Markdown, MarkdownStyle}; +use project::Project; use settings::Settings as _; use theme::ThemeSettings; use ui::{prelude::*, Disclosure, KeyBinding}; use util::ResultExt as _; -use workspace::Workspace; use crate::thread::{MessageId, RequestKind, Thread, ThreadError, ThreadEvent}; use crate::thread_store::ThreadStore; @@ -23,7 +23,7 @@ use crate::tool_use::{ToolUse, ToolUseStatus}; use crate::ui::ContextPill; pub struct ActiveThread { - workspace: WeakEntity, + project: WeakEntity, language_registry: Arc, tools: Arc, thread_store: Entity, @@ -46,7 +46,7 @@ impl ActiveThread { pub fn new( thread: Entity, thread_store: Entity, - workspace: WeakEntity, + project: WeakEntity, language_registry: Arc, tools: Arc, window: &mut Window, @@ -58,7 +58,7 @@ impl ActiveThread { ]; let mut this = Self { - workspace, + project, language_registry, tools, thread_store, @@ -311,7 +311,7 @@ impl ActiveThread { for tool_use in pending_tool_uses { if let Some(tool) = self.tools.tool(&tool_use.name, cx) { - let task = tool.run(tool_use.input, self.workspace.clone(), window, cx); + let task = tool.run(tool_use.input, self.project.clone(), cx); self.thread.update(cx, |thread, cx| { thread.insert_tool_output(tool_use.id.clone(), task, cx); diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 86fad384539157..ef29610a9b8e56 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -170,8 +170,8 @@ impl AssistantPanel { Self { active_view: ActiveView::Thread, - workspace: workspace.clone(), - project, + workspace, + project: project.clone(), fs: fs.clone(), language_registry: language_registry.clone(), thread_store: thread_store.clone(), @@ -179,7 +179,7 @@ impl AssistantPanel { ActiveThread::new( thread.clone(), thread_store.clone(), - workspace, + project.downgrade(), language_registry, tools.clone(), window, @@ -246,7 +246,7 @@ impl AssistantPanel { ActiveThread::new( thread.clone(), self.thread_store.clone(), - self.workspace.clone(), + self.project.downgrade(), self.language_registry.clone(), self.tools.clone(), window, @@ -381,7 +381,7 @@ impl AssistantPanel { ActiveThread::new( thread.clone(), this.thread_store.clone(), - this.workspace.clone(), + this.project.downgrade(), this.language_registry.clone(), this.tools.clone(), window, diff --git a/crates/assistant_tool/Cargo.toml b/crates/assistant_tool/Cargo.toml index 1a5e954dfd075a..85eb36e30614d9 100644 --- a/crates/assistant_tool/Cargo.toml +++ b/crates/assistant_tool/Cargo.toml @@ -17,6 +17,6 @@ collections.workspace = true derive_more.workspace = true gpui.workspace = true parking_lot.workspace = true +project.workspace = true serde.workspace = true serde_json.workspace = true -workspace.workspace = true diff --git a/crates/assistant_tool/src/assistant_tool.rs b/crates/assistant_tool/src/assistant_tool.rs index 0b4f30da7d0146..b2eaead980a5aa 100644 --- a/crates/assistant_tool/src/assistant_tool.rs +++ b/crates/assistant_tool/src/assistant_tool.rs @@ -4,8 +4,8 @@ mod tool_working_set; use std::sync::Arc; use anyhow::Result; -use gpui::{App, Task, WeakEntity, Window}; -use workspace::Workspace; +use gpui::{App, Task, WeakEntity}; +use project::Project; pub use crate::tool_registry::*; pub use crate::tool_working_set::*; @@ -31,8 +31,7 @@ pub trait Tool: 'static + Send + Sync { fn run( self: Arc, input: serde_json::Value, - workspace: WeakEntity, - window: &mut Window, + project: WeakEntity, cx: &mut App, ) -> Task>; } diff --git a/crates/assistant_tools/Cargo.toml b/crates/assistant_tools/Cargo.toml index 3bb81fbba892cd..394cfe7e8ed466 100644 --- a/crates/assistant_tools/Cargo.toml +++ b/crates/assistant_tools/Cargo.toml @@ -20,4 +20,3 @@ project.workspace = true schemars.workspace = true serde.workspace = true serde_json.workspace = true -workspace.workspace = true diff --git a/crates/assistant_tools/src/list_worktrees_tool.rs b/crates/assistant_tools/src/list_worktrees_tool.rs index c1d9a722112159..6a4ed439540c1f 100644 --- a/crates/assistant_tools/src/list_worktrees_tool.rs +++ b/crates/assistant_tools/src/list_worktrees_tool.rs @@ -2,10 +2,10 @@ use std::sync::Arc; use anyhow::{anyhow, Result}; use assistant_tool::Tool; -use gpui::{App, Task, WeakEntity, Window}; +use gpui::{App, Task, WeakEntity}; +use project::Project; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use workspace::Workspace; #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct ListWorktreesToolInput {} @@ -34,16 +34,13 @@ impl Tool for ListWorktreesTool { fn run( self: Arc, _input: serde_json::Value, - workspace: WeakEntity, - _window: &mut Window, + project: WeakEntity, cx: &mut App, ) -> Task> { - let Some(workspace) = workspace.upgrade() else { - return Task::ready(Err(anyhow!("workspace dropped"))); + let Some(project) = project.upgrade() else { + return Task::ready(Err(anyhow!("project dropped"))); }; - let project = workspace.read(cx).project().clone(); - cx.spawn(|cx| async move { cx.update(|cx| { #[derive(Debug, Serialize)] diff --git a/crates/assistant_tools/src/now_tool.rs b/crates/assistant_tools/src/now_tool.rs index 4e4e7228922e0e..1736f6bd9a6c2f 100644 --- a/crates/assistant_tools/src/now_tool.rs +++ b/crates/assistant_tools/src/now_tool.rs @@ -3,7 +3,8 @@ use std::sync::Arc; use anyhow::{anyhow, Result}; use assistant_tool::Tool; use chrono::{Local, Utc}; -use gpui::{App, Task, WeakEntity, Window}; +use gpui::{App, Task, WeakEntity}; +use project::Project; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -41,8 +42,7 @@ impl Tool for NowTool { fn run( self: Arc, input: serde_json::Value, - _workspace: WeakEntity, - _window: &mut Window, + _project: WeakEntity, _cx: &mut App, ) -> Task> { let input: NowToolInput = match serde_json::from_value(input) { diff --git a/crates/assistant_tools/src/read_file_tool.rs b/crates/assistant_tools/src/read_file_tool.rs index e218a435b3943a..b12bc89a1fede0 100644 --- a/crates/assistant_tools/src/read_file_tool.rs +++ b/crates/assistant_tools/src/read_file_tool.rs @@ -3,11 +3,10 @@ use std::sync::Arc; use anyhow::{anyhow, Result}; use assistant_tool::Tool; -use gpui::{App, Task, WeakEntity, Window}; -use project::{ProjectPath, WorktreeId}; +use gpui::{App, Task, WeakEntity}; +use project::{Project, ProjectPath, WorktreeId}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use workspace::Workspace; #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct ReadFileToolInput { @@ -38,12 +37,11 @@ impl Tool for ReadFileTool { fn run( self: Arc, input: serde_json::Value, - workspace: WeakEntity, - _window: &mut Window, + project: WeakEntity, cx: &mut App, ) -> Task> { - let Some(workspace) = workspace.upgrade() else { - return Task::ready(Err(anyhow!("workspace dropped"))); + let Some(project) = project.upgrade() else { + return Task::ready(Err(anyhow!("project dropped"))); }; let input = match serde_json::from_value::(input) { @@ -51,7 +49,6 @@ impl Tool for ReadFileTool { Err(err) => return Task::ready(Err(anyhow!(err))), }; - let project = workspace.read(cx).project().clone(); let project_path = ProjectPath { worktree_id: WorktreeId::from_usize(input.worktree_id), path: input.path, diff --git a/crates/context_server/Cargo.toml b/crates/context_server/Cargo.toml index 33630c2b293ae0..5306b314d69f6d 100644 --- a/crates/context_server/Cargo.toml +++ b/crates/context_server/Cargo.toml @@ -31,4 +31,3 @@ settings.workspace = true smol.workspace = true url = { workspace = true, features = ["serde"] } util.workspace = true -workspace.workspace = true diff --git a/crates/context_server/src/context_server_tool.rs b/crates/context_server/src/context_server_tool.rs index d91c8e2e64392b..90bfebe7a674b0 100644 --- a/crates/context_server/src/context_server_tool.rs +++ b/crates/context_server/src/context_server_tool.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use anyhow::{anyhow, bail}; use assistant_tool::Tool; -use gpui::{App, Entity, Task, Window}; +use gpui::{App, Entity, Task}; use crate::manager::ContextServerManager; use crate::types; @@ -51,8 +51,7 @@ impl Tool for ContextServerTool { fn run( self: std::sync::Arc, input: serde_json::Value, - _workspace: gpui::WeakEntity, - _: &mut Window, + _project: gpui::WeakEntity, cx: &mut App, ) -> gpui::Task> { if let Some(server) = self.server_manager.read(cx).get_server(&self.server_id) { diff --git a/crates/scripting_tool/Cargo.toml b/crates/scripting_tool/Cargo.toml index 775cf87f7df5c7..ab80d96fe05509 100644 --- a/crates/scripting_tool/Cargo.toml +++ b/crates/scripting_tool/Cargo.toml @@ -27,11 +27,9 @@ serde.workspace = true serde_json.workspace = true settings.workspace = true util.workspace = true -workspace.workspace = true [dev-dependencies] collections = { workspace = true, features = ["test-support"] } gpui = { workspace = true, features = ["test-support"] } project = { workspace = true, features = ["test-support"] } settings = { workspace = true, features = ["test-support"] } -workspace = { workspace = true, features = ["test-support"] } diff --git a/crates/scripting_tool/src/scripting_tool.rs b/crates/scripting_tool/src/scripting_tool.rs index 35885519f88071..f8e660d213355f 100644 --- a/crates/scripting_tool/src/scripting_tool.rs +++ b/crates/scripting_tool/src/scripting_tool.rs @@ -1,13 +1,13 @@ mod session; +use project::Project; pub(crate) use session::*; use assistant_tool::{Tool, ToolRegistry}; -use gpui::{App, AppContext as _, Task, WeakEntity, Window}; +use gpui::{App, AppContext as _, Task, WeakEntity}; use schemars::JsonSchema; use serde::Deserialize; use std::sync::Arc; -use workspace::Workspace; pub fn init(cx: &App) { let registry = ToolRegistry::global(cx); @@ -38,17 +38,15 @@ impl Tool for ScriptingTool { fn run( self: Arc, input: serde_json::Value, - workspace: WeakEntity, - _window: &mut Window, + project: WeakEntity, cx: &mut App, ) -> Task> { let input = match serde_json::from_value::(input) { Err(err) => return Task::ready(Err(err.into())), Ok(input) => input, }; - let Ok(project) = workspace.read_with(cx, |workspace, _cx| workspace.project().clone()) - else { - return Task::ready(Err(anyhow::anyhow!("No project found"))); + let Some(project) = project.upgrade() else { + return Task::ready(Err(anyhow::anyhow!("project dropped"))); }; let session = cx.new(|cx| Session::new(project, cx));