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<Project>` instead of a `WeakEntity<Workspace>` and a `Window`. Release Notes: - N/A
This commit is contained in:
parent
4f6682c7fe
commit
18f3f8097f
13 changed files with 35 additions and 52 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -658,9 +658,9 @@ dependencies = [
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"gpui",
|
"gpui",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"project",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"workspace",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -675,7 +675,6 @@ dependencies = [
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"workspace",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3140,7 +3139,6 @@ dependencies = [
|
||||||
"smol",
|
"smol",
|
||||||
"url",
|
"url",
|
||||||
"util",
|
"util",
|
||||||
"workspace",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -11930,7 +11928,6 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"settings",
|
"settings",
|
||||||
"util",
|
"util",
|
||||||
"workspace",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -11,11 +11,11 @@ use gpui::{
|
||||||
use language::{Buffer, LanguageRegistry};
|
use language::{Buffer, LanguageRegistry};
|
||||||
use language_model::{LanguageModelRegistry, LanguageModelToolUseId, Role};
|
use language_model::{LanguageModelRegistry, LanguageModelToolUseId, Role};
|
||||||
use markdown::{Markdown, MarkdownStyle};
|
use markdown::{Markdown, MarkdownStyle};
|
||||||
|
use project::Project;
|
||||||
use settings::Settings as _;
|
use settings::Settings as _;
|
||||||
use theme::ThemeSettings;
|
use theme::ThemeSettings;
|
||||||
use ui::{prelude::*, Disclosure, KeyBinding};
|
use ui::{prelude::*, Disclosure, KeyBinding};
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
use workspace::Workspace;
|
|
||||||
|
|
||||||
use crate::thread::{MessageId, RequestKind, Thread, ThreadError, ThreadEvent};
|
use crate::thread::{MessageId, RequestKind, Thread, ThreadError, ThreadEvent};
|
||||||
use crate::thread_store::ThreadStore;
|
use crate::thread_store::ThreadStore;
|
||||||
|
@ -23,7 +23,7 @@ use crate::tool_use::{ToolUse, ToolUseStatus};
|
||||||
use crate::ui::ContextPill;
|
use crate::ui::ContextPill;
|
||||||
|
|
||||||
pub struct ActiveThread {
|
pub struct ActiveThread {
|
||||||
workspace: WeakEntity<Workspace>,
|
project: WeakEntity<Project>,
|
||||||
language_registry: Arc<LanguageRegistry>,
|
language_registry: Arc<LanguageRegistry>,
|
||||||
tools: Arc<ToolWorkingSet>,
|
tools: Arc<ToolWorkingSet>,
|
||||||
thread_store: Entity<ThreadStore>,
|
thread_store: Entity<ThreadStore>,
|
||||||
|
@ -46,7 +46,7 @@ impl ActiveThread {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
thread: Entity<Thread>,
|
thread: Entity<Thread>,
|
||||||
thread_store: Entity<ThreadStore>,
|
thread_store: Entity<ThreadStore>,
|
||||||
workspace: WeakEntity<Workspace>,
|
project: WeakEntity<Project>,
|
||||||
language_registry: Arc<LanguageRegistry>,
|
language_registry: Arc<LanguageRegistry>,
|
||||||
tools: Arc<ToolWorkingSet>,
|
tools: Arc<ToolWorkingSet>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
|
@ -58,7 +58,7 @@ impl ActiveThread {
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
workspace,
|
project,
|
||||||
language_registry,
|
language_registry,
|
||||||
tools,
|
tools,
|
||||||
thread_store,
|
thread_store,
|
||||||
|
@ -311,7 +311,7 @@ impl ActiveThread {
|
||||||
|
|
||||||
for tool_use in pending_tool_uses {
|
for tool_use in pending_tool_uses {
|
||||||
if let Some(tool) = self.tools.tool(&tool_use.name, cx) {
|
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| {
|
self.thread.update(cx, |thread, cx| {
|
||||||
thread.insert_tool_output(tool_use.id.clone(), task, cx);
|
thread.insert_tool_output(tool_use.id.clone(), task, cx);
|
||||||
|
|
|
@ -170,8 +170,8 @@ impl AssistantPanel {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
active_view: ActiveView::Thread,
|
active_view: ActiveView::Thread,
|
||||||
workspace: workspace.clone(),
|
workspace,
|
||||||
project,
|
project: project.clone(),
|
||||||
fs: fs.clone(),
|
fs: fs.clone(),
|
||||||
language_registry: language_registry.clone(),
|
language_registry: language_registry.clone(),
|
||||||
thread_store: thread_store.clone(),
|
thread_store: thread_store.clone(),
|
||||||
|
@ -179,7 +179,7 @@ impl AssistantPanel {
|
||||||
ActiveThread::new(
|
ActiveThread::new(
|
||||||
thread.clone(),
|
thread.clone(),
|
||||||
thread_store.clone(),
|
thread_store.clone(),
|
||||||
workspace,
|
project.downgrade(),
|
||||||
language_registry,
|
language_registry,
|
||||||
tools.clone(),
|
tools.clone(),
|
||||||
window,
|
window,
|
||||||
|
@ -246,7 +246,7 @@ impl AssistantPanel {
|
||||||
ActiveThread::new(
|
ActiveThread::new(
|
||||||
thread.clone(),
|
thread.clone(),
|
||||||
self.thread_store.clone(),
|
self.thread_store.clone(),
|
||||||
self.workspace.clone(),
|
self.project.downgrade(),
|
||||||
self.language_registry.clone(),
|
self.language_registry.clone(),
|
||||||
self.tools.clone(),
|
self.tools.clone(),
|
||||||
window,
|
window,
|
||||||
|
@ -381,7 +381,7 @@ impl AssistantPanel {
|
||||||
ActiveThread::new(
|
ActiveThread::new(
|
||||||
thread.clone(),
|
thread.clone(),
|
||||||
this.thread_store.clone(),
|
this.thread_store.clone(),
|
||||||
this.workspace.clone(),
|
this.project.downgrade(),
|
||||||
this.language_registry.clone(),
|
this.language_registry.clone(),
|
||||||
this.tools.clone(),
|
this.tools.clone(),
|
||||||
window,
|
window,
|
||||||
|
|
|
@ -17,6 +17,6 @@ collections.workspace = true
|
||||||
derive_more.workspace = true
|
derive_more.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
|
project.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
workspace.workspace = true
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ mod tool_working_set;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gpui::{App, Task, WeakEntity, Window};
|
use gpui::{App, Task, WeakEntity};
|
||||||
use workspace::Workspace;
|
use project::Project;
|
||||||
|
|
||||||
pub use crate::tool_registry::*;
|
pub use crate::tool_registry::*;
|
||||||
pub use crate::tool_working_set::*;
|
pub use crate::tool_working_set::*;
|
||||||
|
@ -31,8 +31,7 @@ pub trait Tool: 'static + Send + Sync {
|
||||||
fn run(
|
fn run(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
input: serde_json::Value,
|
input: serde_json::Value,
|
||||||
workspace: WeakEntity<Workspace>,
|
project: WeakEntity<Project>,
|
||||||
window: &mut Window,
|
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Task<Result<String>>;
|
) -> Task<Result<String>>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,4 +20,3 @@ project.workspace = true
|
||||||
schemars.workspace = true
|
schemars.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
workspace.workspace = true
|
|
||||||
|
|
|
@ -2,10 +2,10 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_tool::Tool;
|
use assistant_tool::Tool;
|
||||||
use gpui::{App, Task, WeakEntity, Window};
|
use gpui::{App, Task, WeakEntity};
|
||||||
|
use project::Project;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use workspace::Workspace;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct ListWorktreesToolInput {}
|
pub struct ListWorktreesToolInput {}
|
||||||
|
@ -34,16 +34,13 @@ impl Tool for ListWorktreesTool {
|
||||||
fn run(
|
fn run(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
_input: serde_json::Value,
|
_input: serde_json::Value,
|
||||||
workspace: WeakEntity<Workspace>,
|
project: WeakEntity<Project>,
|
||||||
_window: &mut Window,
|
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Task<Result<String>> {
|
) -> Task<Result<String>> {
|
||||||
let Some(workspace) = workspace.upgrade() else {
|
let Some(project) = project.upgrade() else {
|
||||||
return Task::ready(Err(anyhow!("workspace dropped")));
|
return Task::ready(Err(anyhow!("project dropped")));
|
||||||
};
|
};
|
||||||
|
|
||||||
let project = workspace.read(cx).project().clone();
|
|
||||||
|
|
||||||
cx.spawn(|cx| async move {
|
cx.spawn(|cx| async move {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
|
|
@ -3,7 +3,8 @@ use std::sync::Arc;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_tool::Tool;
|
use assistant_tool::Tool;
|
||||||
use chrono::{Local, Utc};
|
use chrono::{Local, Utc};
|
||||||
use gpui::{App, Task, WeakEntity, Window};
|
use gpui::{App, Task, WeakEntity};
|
||||||
|
use project::Project;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -41,8 +42,7 @@ impl Tool for NowTool {
|
||||||
fn run(
|
fn run(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
input: serde_json::Value,
|
input: serde_json::Value,
|
||||||
_workspace: WeakEntity<workspace::Workspace>,
|
_project: WeakEntity<Project>,
|
||||||
_window: &mut Window,
|
|
||||||
_cx: &mut App,
|
_cx: &mut App,
|
||||||
) -> Task<Result<String>> {
|
) -> Task<Result<String>> {
|
||||||
let input: NowToolInput = match serde_json::from_value(input) {
|
let input: NowToolInput = match serde_json::from_value(input) {
|
||||||
|
|
|
@ -3,11 +3,10 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_tool::Tool;
|
use assistant_tool::Tool;
|
||||||
use gpui::{App, Task, WeakEntity, Window};
|
use gpui::{App, Task, WeakEntity};
|
||||||
use project::{ProjectPath, WorktreeId};
|
use project::{Project, ProjectPath, WorktreeId};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use workspace::Workspace;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct ReadFileToolInput {
|
pub struct ReadFileToolInput {
|
||||||
|
@ -38,12 +37,11 @@ impl Tool for ReadFileTool {
|
||||||
fn run(
|
fn run(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
input: serde_json::Value,
|
input: serde_json::Value,
|
||||||
workspace: WeakEntity<Workspace>,
|
project: WeakEntity<Project>,
|
||||||
_window: &mut Window,
|
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Task<Result<String>> {
|
) -> Task<Result<String>> {
|
||||||
let Some(workspace) = workspace.upgrade() else {
|
let Some(project) = project.upgrade() else {
|
||||||
return Task::ready(Err(anyhow!("workspace dropped")));
|
return Task::ready(Err(anyhow!("project dropped")));
|
||||||
};
|
};
|
||||||
|
|
||||||
let input = match serde_json::from_value::<ReadFileToolInput>(input) {
|
let input = match serde_json::from_value::<ReadFileToolInput>(input) {
|
||||||
|
@ -51,7 +49,6 @@ impl Tool for ReadFileTool {
|
||||||
Err(err) => return Task::ready(Err(anyhow!(err))),
|
Err(err) => return Task::ready(Err(anyhow!(err))),
|
||||||
};
|
};
|
||||||
|
|
||||||
let project = workspace.read(cx).project().clone();
|
|
||||||
let project_path = ProjectPath {
|
let project_path = ProjectPath {
|
||||||
worktree_id: WorktreeId::from_usize(input.worktree_id),
|
worktree_id: WorktreeId::from_usize(input.worktree_id),
|
||||||
path: input.path,
|
path: input.path,
|
||||||
|
|
|
@ -31,4 +31,3 @@ settings.workspace = true
|
||||||
smol.workspace = true
|
smol.workspace = true
|
||||||
url = { workspace = true, features = ["serde"] }
|
url = { workspace = true, features = ["serde"] }
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
workspace.workspace = true
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
use assistant_tool::Tool;
|
use assistant_tool::Tool;
|
||||||
use gpui::{App, Entity, Task, Window};
|
use gpui::{App, Entity, Task};
|
||||||
|
|
||||||
use crate::manager::ContextServerManager;
|
use crate::manager::ContextServerManager;
|
||||||
use crate::types;
|
use crate::types;
|
||||||
|
@ -51,8 +51,7 @@ impl Tool for ContextServerTool {
|
||||||
fn run(
|
fn run(
|
||||||
self: std::sync::Arc<Self>,
|
self: std::sync::Arc<Self>,
|
||||||
input: serde_json::Value,
|
input: serde_json::Value,
|
||||||
_workspace: gpui::WeakEntity<workspace::Workspace>,
|
_project: gpui::WeakEntity<project::Project>,
|
||||||
_: &mut Window,
|
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> gpui::Task<gpui::Result<String>> {
|
) -> gpui::Task<gpui::Result<String>> {
|
||||||
if let Some(server) = self.server_manager.read(cx).get_server(&self.server_id) {
|
if let Some(server) = self.server_manager.read(cx).get_server(&self.server_id) {
|
||||||
|
|
|
@ -27,11 +27,9 @@ serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
workspace.workspace = true
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
collections = { workspace = true, features = ["test-support"] }
|
collections = { workspace = true, features = ["test-support"] }
|
||||||
gpui = { workspace = true, features = ["test-support"] }
|
gpui = { workspace = true, features = ["test-support"] }
|
||||||
project = { workspace = true, features = ["test-support"] }
|
project = { workspace = true, features = ["test-support"] }
|
||||||
settings = { workspace = true, features = ["test-support"] }
|
settings = { workspace = true, features = ["test-support"] }
|
||||||
workspace = { workspace = true, features = ["test-support"] }
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
mod session;
|
mod session;
|
||||||
|
|
||||||
|
use project::Project;
|
||||||
pub(crate) use session::*;
|
pub(crate) use session::*;
|
||||||
|
|
||||||
use assistant_tool::{Tool, ToolRegistry};
|
use assistant_tool::{Tool, ToolRegistry};
|
||||||
use gpui::{App, AppContext as _, Task, WeakEntity, Window};
|
use gpui::{App, AppContext as _, Task, WeakEntity};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use workspace::Workspace;
|
|
||||||
|
|
||||||
pub fn init(cx: &App) {
|
pub fn init(cx: &App) {
|
||||||
let registry = ToolRegistry::global(cx);
|
let registry = ToolRegistry::global(cx);
|
||||||
|
@ -38,17 +38,15 @@ impl Tool for ScriptingTool {
|
||||||
fn run(
|
fn run(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
input: serde_json::Value,
|
input: serde_json::Value,
|
||||||
workspace: WeakEntity<Workspace>,
|
project: WeakEntity<Project>,
|
||||||
_window: &mut Window,
|
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Task<anyhow::Result<String>> {
|
) -> Task<anyhow::Result<String>> {
|
||||||
let input = match serde_json::from_value::<ScriptingToolInput>(input) {
|
let input = match serde_json::from_value::<ScriptingToolInput>(input) {
|
||||||
Err(err) => return Task::ready(Err(err.into())),
|
Err(err) => return Task::ready(Err(err.into())),
|
||||||
Ok(input) => input,
|
Ok(input) => input,
|
||||||
};
|
};
|
||||||
let Ok(project) = workspace.read_with(cx, |workspace, _cx| workspace.project().clone())
|
let Some(project) = project.upgrade() else {
|
||||||
else {
|
return Task::ready(Err(anyhow::anyhow!("project dropped")));
|
||||||
return Task::ready(Err(anyhow::anyhow!("No project found")));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let session = cx.new(|cx| Session::new(project, cx));
|
let session = cx.new(|cx| Session::new(project, cx));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue