Consolidate Assistant panels in `assistant2` feature flag (#23442)

Marshall Bowers created

This PR consolidates the two Assistant panels into one for users in the
`assistant2` feature flag.

Now that the Assistant1 prompt editor is accessible through the
Assistant2 panel, we no longer have a need to show both panels.

Release Notes:

- N/A

Change summary

crates/assistant/src/assistant.rs                 |  1 
crates/assistant/src/assistant_panel.rs           | 25 ++++---
crates/assistant/src/inline_assistant.rs          |  2 
crates/assistant/src/terminal_inline_assistant.rs |  2 
crates/assistant2/src/assistant.rs                |  1 
crates/assistant2/src/assistant_panel.rs          | 21 +++++-
crates/assistant2/src/inline_assistant.rs         |  2 
crates/assistant2/src/inline_prompt_editor.rs     |  7 +
crates/prompt_library/src/prompt_library.rs       |  2 
crates/terminal_view/src/terminal_panel.rs        |  2 
crates/terminal_view/src/terminal_view.rs         |  2 
crates/zed/src/zed.rs                             | 53 ++++++++++------
crates/zed/src/zed/quick_action_bar.rs            |  2 
crates/zed_actions/src/lib.rs                     | 18 ++++-
14 files changed, 89 insertions(+), 51 deletions(-)

Detailed changes

crates/assistant/src/assistant.rs 🔗

@@ -31,7 +31,6 @@ use crate::slash_command_settings::SlashCommandSettings;
 actions!(
     assistant,
     [
-        ToggleFocus,
         InsertActivePrompt,
         DeployHistory,
         DeployPromptLibrary,

crates/assistant/src/assistant_panel.rs 🔗

@@ -1,6 +1,6 @@
 use crate::{
     terminal_inline_assistant::TerminalInlineAssistant, DeployHistory, DeployPromptLibrary,
-    InlineAssistant, NewContext, ToggleFocus,
+    InlineAssistant, NewContext,
 };
 use anyhow::{anyhow, Result};
 use assistant_context_editor::{
@@ -42,7 +42,7 @@ use workspace::{
     item::Item,
     pane, DraggedSelection, Pane, ShowConfiguration, ToggleZoom, Workspace,
 };
-use zed_actions::InlineAssist;
+use zed_actions::assistant::{InlineAssist, ToggleFocus};
 
 pub fn init(cx: &mut AppContext) {
     <dyn AssistantPanelDelegate>::set_global(Arc::new(ConcreteAssistantPanelDelegate), cx);
@@ -51,14 +51,6 @@ pub fn init(cx: &mut AppContext) {
     cx.observe_new_views(
         |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
             workspace
-                .register_action(|workspace, _: &ToggleFocus, cx| {
-                    let settings = AssistantSettings::get_global(cx);
-                    if !settings.enabled {
-                        return;
-                    }
-
-                    workspace.toggle_panel_focus::<AssistantPanel>(cx);
-                })
                 .register_action(ContextEditor::quote_selection)
                 .register_action(ContextEditor::insert_selection)
                 .register_action(ContextEditor::copy_code)
@@ -341,6 +333,19 @@ impl AssistantPanel {
         this
     }
 
+    pub fn toggle_focus(
+        workspace: &mut Workspace,
+        _: &ToggleFocus,
+        cx: &mut ViewContext<Workspace>,
+    ) {
+        let settings = AssistantSettings::get_global(cx);
+        if !settings.enabled {
+            return;
+        }
+
+        workspace.toggle_panel_focus::<Self>(cx);
+    }
+
     fn watch_client_status(client: Arc<Client>, cx: &mut ViewContext<Self>) -> Task<()> {
         let mut status_rx = client.status();
 

crates/assistant/src/inline_assistant.rs 🔗

@@ -1728,7 +1728,7 @@ impl PromptEditor {
     }
 
     fn placeholder_text(codegen: &Codegen, cx: &WindowContext) -> String {
-        let context_keybinding = text_for_action(&crate::ToggleFocus, cx)
+        let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, cx)
             .map(|keybinding| format!(" • {keybinding} for context"))
             .unwrap_or_default();
 

crates/assistant/src/terminal_inline_assistant.rs 🔗

@@ -740,7 +740,7 @@ impl PromptEditor {
     }
 
     fn placeholder_text(cx: &WindowContext) -> String {
-        let context_keybinding = text_for_action(&crate::ToggleFocus, cx)
+        let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, cx)
             .map(|keybinding| format!(" • {keybinding} for context"))
             .unwrap_or_default();
 

crates/assistant2/src/assistant.rs 🔗

@@ -34,7 +34,6 @@ pub use crate::inline_assistant::InlineAssistant;
 actions!(
     assistant2,
     [
-        ToggleFocus,
         NewThread,
         NewPromptEditor,
         ToggleContextPicker,

crates/assistant2/src/assistant_panel.rs 🔗

@@ -24,22 +24,20 @@ use ui::{prelude::*, ContextMenu, KeyBinding, PopoverMenu, PopoverMenuHandle, Ta
 use util::ResultExt as _;
 use workspace::dock::{DockPosition, Panel, PanelEvent};
 use workspace::Workspace;
+use zed_actions::assistant::ToggleFocus;
 
 use crate::active_thread::ActiveThread;
 use crate::message_editor::MessageEditor;
 use crate::thread::{Thread, ThreadError, ThreadId};
 use crate::thread_history::{PastThread, ThreadHistory};
 use crate::thread_store::ThreadStore;
-use crate::{NewPromptEditor, NewThread, OpenHistory, OpenPromptEditorHistory, ToggleFocus};
+use crate::{NewPromptEditor, NewThread, OpenHistory, OpenPromptEditorHistory};
 
 pub fn init(cx: &mut AppContext) {
     <dyn AssistantPanelDelegate>::set_global(Arc::new(ConcreteAssistantPanelDelegate), cx);
     cx.observe_new_views(
         |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
             workspace
-                .register_action(|workspace, _: &ToggleFocus, cx| {
-                    workspace.toggle_panel_focus::<AssistantPanel>(cx);
-                })
                 .register_action(|workspace, _: &NewThread, cx| {
                     if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
                         panel.update(cx, |panel, cx| panel.new_thread(cx));
@@ -189,6 +187,19 @@ impl AssistantPanel {
         }
     }
 
+    pub fn toggle_focus(
+        workspace: &mut Workspace,
+        _: &ToggleFocus,
+        cx: &mut ViewContext<Workspace>,
+    ) {
+        let settings = AssistantSettings::get_global(cx);
+        if !settings.enabled {
+            return;
+        }
+
+        workspace.toggle_panel_focus::<Self>(cx);
+    }
+
     pub(crate) fn local_timezone(&self) -> UtcOffset {
         self.local_timezone
     }
@@ -438,7 +449,7 @@ impl Panel for AssistantPanel {
             return None;
         }
 
-        Some(IconName::ZedAssistant2)
+        Some(IconName::ZedAssistant)
     }
 
     fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {

crates/assistant2/src/inline_assistant.rs 🔗

@@ -204,7 +204,7 @@ impl InlineAssistant {
 
     pub fn inline_assist(
         workspace: &mut Workspace,
-        _action: &zed_actions::InlineAssist,
+        _action: &zed_actions::assistant::InlineAssist,
         cx: &mut ViewContext<Workspace>,
     ) {
         let settings = AssistantSettings::get_global(cx);

crates/assistant2/src/inline_prompt_editor.rs 🔗

@@ -270,9 +270,10 @@ impl<T: 'static> PromptEditor<T> {
             PromptEditorMode::Terminal { .. } => "Generate",
         };
 
-        let assistant_panel_keybinding = ui::text_for_action(&crate::ToggleFocus, cx)
-            .map(|keybinding| format!("{keybinding} to chat ― "))
-            .unwrap_or_default();
+        let assistant_panel_keybinding =
+            ui::text_for_action(&zed_actions::assistant::ToggleFocus, cx)
+                .map(|keybinding| format!("{keybinding} to chat ― "))
+                .unwrap_or_default();
 
         format!("{action}… ({assistant_panel_keybinding}↓↑ for history)")
     }

crates/prompt_library/src/prompt_library.rs 🔗

@@ -27,7 +27,7 @@ use ui::{
 };
 use util::{ResultExt, TryFutureExt};
 use workspace::Workspace;
-use zed_actions::InlineAssist;
+use zed_actions::assistant::InlineAssist;
 
 pub use crate::prompt_store::*;
 pub use crate::prompts::*;

crates/terminal_view/src/terminal_panel.rs 🔗

@@ -42,7 +42,7 @@ use workspace::{
 };
 
 use anyhow::{anyhow, Context, Result};
-use zed_actions::InlineAssist;
+use zed_actions::assistant::InlineAssist;
 
 const TERMINAL_PANEL_KEY: &str = "TerminalPanel";
 

crates/terminal_view/src/terminal_view.rs 🔗

@@ -56,7 +56,7 @@ use anyhow::Context;
 use serde::Deserialize;
 use settings::{Settings, SettingsStore};
 use smol::Timer;
-use zed_actions::InlineAssist;
+use zed_actions::assistant::InlineAssist;
 
 use std::{
     cmp,

crates/zed/src/zed.rs 🔗

@@ -362,11 +362,6 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
             workspace_handle.clone(),
             cx.clone(),
         );
-        let assistant_panel = assistant::AssistantPanel::load(
-            workspace_handle.clone(),
-            prompt_builder.clone(),
-            cx.clone(),
-        );
 
         let (
             project_panel,
@@ -375,7 +370,6 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
             channels_panel,
             chat_panel,
             notification_panel,
-            assistant_panel,
         ) = futures::try_join!(
             project_panel,
             outline_panel,
@@ -383,7 +377,6 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
             channels_panel,
             chat_panel,
             notification_panel,
-            assistant_panel,
         )?;
 
         workspace_handle.update(&mut cx, |workspace, cx| {
@@ -393,7 +386,6 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
             workspace.add_panel(channels_panel, cx);
             workspace.add_panel(chat_panel, cx);
             workspace.add_panel(notification_panel, cx);
-            workspace.add_panel(assistant_panel, cx)
         })?;
 
         let git_ui_enabled = {
@@ -429,27 +421,50 @@ fn initialize_panels(prompt_builder: Arc<PromptBuilder>, cx: &mut ViewContext<Wo
                 _ = timeout => false,
             }
         };
-        let assistant2_panel = if is_assistant2_enabled {
-            Some(
-                assistant2::AssistantPanel::load(
-                    workspace_handle.clone(),
-                    prompt_builder,
-                    cx.clone(),
-                )
-                .await?,
+
+        let (assistant_panel, assistant2_panel) = if is_assistant2_enabled {
+            let assistant2_panel = assistant2::AssistantPanel::load(
+                workspace_handle.clone(),
+                prompt_builder,
+                cx.clone(),
             )
+            .await?;
+
+            (None, Some(assistant2_panel))
         } else {
-            None
+            let assistant_panel = assistant::AssistantPanel::load(
+                workspace_handle.clone(),
+                prompt_builder.clone(),
+                cx.clone(),
+            )
+            .await?;
+
+            (Some(assistant_panel), None)
         };
+
         workspace_handle.update(&mut cx, |workspace, cx| {
             if let Some(assistant2_panel) = assistant2_panel {
                 workspace.add_panel(assistant2_panel, cx);
             }
 
+            if let Some(assistant_panel) = assistant_panel {
+                workspace.add_panel(assistant_panel, cx);
+            }
+
+            // Register the actions that are shared between `assistant` and `assistant2`.
+            //
+            // We need to do this here instead of within the individual `init`
+            // functions so that we only register the actions once.
+            //
+            // Once we ship `assistant2` we can push this back down into `assistant2::assistant_panel::init`.
             if is_assistant2_enabled {
-                workspace.register_action(assistant2::InlineAssistant::inline_assist);
+                workspace
+                    .register_action(assistant2::AssistantPanel::toggle_focus)
+                    .register_action(assistant2::InlineAssistant::inline_assist);
             } else {
-                workspace.register_action(assistant::AssistantPanel::inline_assist);
+                workspace
+                    .register_action(assistant::AssistantPanel::toggle_focus)
+                    .register_action(assistant::AssistantPanel::inline_assist);
             }
         })?;
 

crates/zed/src/zed/quick_action_bar.rs 🔗

@@ -23,7 +23,7 @@ use vim_mode_setting::VimModeSetting;
 use workspace::{
     item::ItemHandle, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace,
 };
-use zed_actions::{outline::ToggleOutline, InlineAssist};
+use zed_actions::{assistant::InlineAssist, outline::ToggleOutline};
 
 pub struct QuickActionBar {
     _inlay_hints_enabled_subscription: Option<Subscription>,

crates/zed_actions/src/lib.rs 🔗

@@ -77,12 +77,20 @@ pub mod theme_selector {
     impl_actions!(theme_selector, [Toggle]);
 }
 
-#[derive(Clone, Default, Deserialize, PartialEq, JsonSchema)]
-pub struct InlineAssist {
-    pub prompt: Option<String>,
-}
+pub mod assistant {
+    use gpui::{actions, impl_actions};
+    use schemars::JsonSchema;
+    use serde::Deserialize;
+
+    actions!(assistant, [ToggleFocus]);
 
-impl_actions!(assistant, [InlineAssist]);
+    #[derive(Clone, Default, Deserialize, PartialEq, JsonSchema)]
+    pub struct InlineAssist {
+        pub prompt: Option<String>,
+    }
+
+    impl_actions!(assistant, [InlineAssist]);
+}
 
 #[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
 pub struct OpenRecent {