git_ui: Remove dependency on agent crates (#49599)

Bennet Bo Fenner created

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

Release Notes:

- N/A

Change summary

Cargo.lock                                |  3 -
crates/agent_ui/src/agent_panel.rs        | 73 ++++++++++++++----------
crates/agent_ui/src/text_thread_editor.rs |  9 ---
crates/git_ui/Cargo.toml                  |  3 -
crates/git_ui/src/project_diff.rs         | 44 +++-----------
crates/zed_actions/src/lib.rs             | 15 ++++
6 files changed, 68 insertions(+), 79 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -7138,10 +7138,7 @@ dependencies = [
 name = "git_ui"
 version = "0.1.0"
 dependencies = [
- "acp_thread",
- "agent-client-protocol",
  "agent_settings",
- "agent_ui",
  "anyhow",
  "askpass",
  "buffer_diff",

crates/agent_ui/src/agent_panel.rs 🔗

@@ -1,6 +1,6 @@
 use std::{ops::Range, path::Path, rc::Rc, sync::Arc, time::Duration};
 
-use acp_thread::{AcpThread, AgentSessionInfo};
+use acp_thread::{AcpThread, AgentSessionInfo, MentionUri};
 use agent::{ContextServerRegistry, SharedThread, ThreadStore};
 use agent_client_protocol as acp;
 use agent_servers::AgentServer;
@@ -12,7 +12,7 @@ use project::{
 use serde::{Deserialize, Serialize};
 use settings::{LanguageModelProviderSetting, LanguageModelSelection};
 
-use zed_actions::agent::{OpenClaudeAgentOnboardingModal, ReauthenticateAgent};
+use zed_actions::agent::{OpenClaudeAgentOnboardingModal, ReauthenticateAgent, ReviewBranchDiff};
 
 use crate::ui::{AcpOnboardingModal, ClaudeCodeOnboardingModal};
 use crate::{
@@ -268,6 +268,47 @@ pub fn init(cx: &mut App) {
                             panel.load_thread_from_clipboard(window, cx);
                         });
                     }
+                })
+                .register_action(|workspace, action: &ReviewBranchDiff, window, cx| {
+                    let Some(panel) = workspace.panel::<AgentPanel>(cx) else {
+                        return;
+                    };
+
+                    let mention_uri = MentionUri::GitDiff {
+                        base_ref: action.base_ref.to_string(),
+                    };
+                    let diff_uri = mention_uri.to_uri().to_string();
+
+                    let content_blocks = vec![
+                        acp::ContentBlock::Text(acp::TextContent::new(
+                            "Please review this branch diff carefully. Point out any issues, \
+                             potential bugs, or improvement opportunities you find.\n\n"
+                                .to_string(),
+                        )),
+                        acp::ContentBlock::Resource(acp::EmbeddedResource::new(
+                            acp::EmbeddedResourceResource::TextResourceContents(
+                                acp::TextResourceContents::new(
+                                    action.diff_text.to_string(),
+                                    diff_uri,
+                                ),
+                            ),
+                        )),
+                    ];
+
+                    workspace.focus_panel::<AgentPanel>(window, cx);
+
+                    panel.update(cx, |panel, cx| {
+                        panel.external_thread(
+                            None,
+                            None,
+                            Some(AgentInitialContent::ContentBlock {
+                                blocks: content_blocks,
+                                auto_submit: true,
+                            }),
+                            window,
+                            cx,
+                        );
+                    });
                 });
         },
     )
@@ -3391,34 +3432,6 @@ impl AgentPanelDelegate for ConcreteAssistantPanelDelegate {
             });
         });
     }
-
-    fn new_thread_with_content(
-        &self,
-        workspace: &mut Workspace,
-        blocks: Vec<acp::ContentBlock>,
-        auto_submit: bool,
-        window: &mut Window,
-        cx: &mut Context<Workspace>,
-    ) {
-        let Some(panel) = workspace.panel::<AgentPanel>(cx) else {
-            return;
-        };
-
-        workspace.focus_panel::<AgentPanel>(window, cx);
-
-        panel.update(cx, |panel, cx| {
-            panel.external_thread(
-                None,
-                None,
-                Some(AgentInitialContent::ContentBlock {
-                    blocks,
-                    auto_submit,
-                }),
-                window,
-                cx,
-            );
-        });
-    }
 }
 
 struct OnboardingUpsell;

crates/agent_ui/src/text_thread_editor.rs 🔗

@@ -167,15 +167,6 @@ pub trait AgentPanelDelegate {
         window: &mut Window,
         cx: &mut Context<Workspace>,
     );
-
-    fn new_thread_with_content(
-        &self,
-        workspace: &mut Workspace,
-        blocks: Vec<agent_client_protocol::ContentBlock>,
-        auto_submit: bool,
-        window: &mut Window,
-        cx: &mut Context<Workspace>,
-    );
 }
 
 impl dyn AgentPanelDelegate {

crates/git_ui/Cargo.toml 🔗

@@ -16,10 +16,7 @@ path = "src/git_ui.rs"
 test-support = ["multi_buffer/test-support", "remote_connection/test-support"]
 
 [dependencies]
-acp_thread.workspace = true
-agent-client-protocol.workspace = true
 agent_settings.workspace = true
-agent_ui.workspace = true
 anyhow.workspace = true
 askpass.workspace = true
 buffer_diff.workspace = true

crates/git_ui/src/project_diff.rs 🔗

@@ -5,10 +5,7 @@ use crate::{
     remote_button::{render_publish_button, render_push_button},
     resolve_active_repository,
 };
-use acp_thread::MentionUri;
-use agent_client_protocol as acp;
 use agent_settings::AgentSettings;
-use agent_ui::AgentPanelDelegate;
 use anyhow::{Context as _, Result, anyhow};
 use buffer_diff::{BufferDiff, DiffHunkSecondaryStatus};
 use collections::{HashMap, HashSet};
@@ -52,6 +49,7 @@ use workspace::{
     notifications::NotifyTaskExt,
     searchable::SearchableItemHandle,
 };
+use zed_actions::agent::ReviewBranchDiff;
 use ztracing::instrument;
 
 actions!(
@@ -187,34 +185,15 @@ impl ProjectDiff {
             .spawn(cx, async move |cx| {
                 let diff_text = diff_receiver.await??;
 
-                let mention_uri = MentionUri::GitDiff {
-                    base_ref: base_ref.into(),
-                };
-                let diff_uri = mention_uri.to_uri().to_string();
-
-                let content_blocks = vec![
-                    acp::ContentBlock::Text(acp::TextContent::new(
-                        "Please review this branch diff carefully. Point out any issues, potential bugs, \
-                         or improvement opportunities you find.\n\n"
-                            .to_string(),
-                    )),
-                    acp::ContentBlock::Resource(acp::EmbeddedResource::new(
-                        acp::EmbeddedResourceResource::TextResourceContents(
-                            acp::TextResourceContents::new(diff_text, diff_uri),
-                        ),
-                    )),
-                ];
-
-                workspace_handle.update_in(cx, |workspace, window, cx| {
-                    if let Some(delegate) = <dyn AgentPanelDelegate>::try_global(cx) {
-                        delegate.new_thread_with_content(
-                            workspace,
-                            content_blocks,
-                            true,
-                            window,
-                            cx,
-                        );
-                    }
+                workspace_handle.update_in(cx, |_workspace, window, cx| {
+                    window.dispatch_action(
+                        ReviewBranchDiff {
+                            diff_text: diff_text.into(),
+                            base_ref: base_ref.to_string().into(),
+                        }
+                        .boxed_clone(),
+                        cx,
+                    );
                 })?;
 
                 anyhow::Ok(())
@@ -1647,8 +1626,7 @@ impl Render for BranchDiffToolbar {
         let focus_handle = project_diff.focus_handle(cx);
         let review_count = project_diff.read(cx).total_review_comment_count();
 
-        let show_review_button = AgentSettings::get_global(cx).enabled(cx)
-            && <dyn AgentPanelDelegate>::try_global(cx).is_some();
+        let show_review_button = AgentSettings::get_global(cx).enabled(cx);
 
         h_group_xl()
             .my_neg_1()

crates/zed_actions/src/lib.rs 🔗

@@ -424,7 +424,9 @@ pub mod settings_profile_selector {
 }
 
 pub mod agent {
-    use gpui::actions;
+    use gpui::{Action, SharedString, actions};
+    use schemars::JsonSchema;
+    use serde::Deserialize;
 
     actions!(
         agent,
@@ -456,6 +458,17 @@ pub mod agent {
             PasteRaw,
         ]
     );
+
+    /// Opens a new agent thread with the provided branch diff for review.
+    #[derive(Clone, PartialEq, Deserialize, JsonSchema, Action)]
+    #[action(namespace = agent)]
+    #[serde(deny_unknown_fields)]
+    pub struct ReviewBranchDiff {
+        /// The full text of the diff to review.
+        pub diff_text: SharedString,
+        /// The base ref that the diff was computed against (e.g. "main").
+        pub base_ref: SharedString,
+    }
 }
 
 pub mod assistant {