agent: Add a setting choose the default view (#31353)

Alvaro Parker created

Related discussions #30240 #30596

Release Notes:

- Added an option on the settings file to choose either the `agent`
panel or the `thread` panel as the default assistant panel when you
first open it. On `settings.json`:
```json
{
  "agent": {
    "default_view": "thread", // default is agent
    }
}
```

Change summary

crates/agent/src/agent_panel.rs                     | 27 +++++++++++++-
crates/assistant_settings/src/assistant_settings.rs | 18 ++++++++++
2 files changed, 43 insertions(+), 2 deletions(-)

Detailed changes

crates/agent/src/agent_panel.rs 🔗

@@ -12,7 +12,7 @@ use assistant_context_editor::{
     ContextSummary, SlashCommandCompletionProvider, humanize_token_count,
     make_lsp_adapter_delegate, render_remaining_tokens,
 };
-use assistant_settings::{AssistantDockPosition, AssistantSettings};
+use assistant_settings::{AssistantDockPosition, AssistantSettings, DefaultView};
 use assistant_slash_command::SlashCommandWorkingSet;
 use assistant_tool::ToolWorkingSet;
 
@@ -522,7 +522,30 @@ impl AgentPanel {
 
         cx.observe(&history_store, |_, _, cx| cx.notify()).detach();
 
-        let active_view = ActiveView::thread(thread.clone(), window, cx);
+        let panel_type = AssistantSettings::get_global(cx).default_view;
+        let active_view = match panel_type {
+            DefaultView::Agent => ActiveView::thread(thread.clone(), window, cx),
+            DefaultView::Thread => {
+                let context =
+                    context_store.update(cx, |context_store, cx| context_store.create(cx));
+                let lsp_adapter_delegate = make_lsp_adapter_delegate(&project.clone(), cx).unwrap();
+                let context_editor = cx.new(|cx| {
+                    let mut editor = ContextEditor::for_context(
+                        context,
+                        fs.clone(),
+                        workspace.clone(),
+                        project.clone(),
+                        lsp_adapter_delegate,
+                        window,
+                        cx,
+                    );
+                    editor.insert_default_prompt(window, cx);
+                    editor
+                });
+                ActiveView::prompt_editor(context_editor, language_registry.clone(), window, cx)
+            }
+        };
+
         let thread_subscription = cx.subscribe(&thread, |_, _, event, cx| {
             if let ThreadEvent::MessageAdded(_) = &event {
                 // needed to leave empty state

crates/assistant_settings/src/assistant_settings.rs 🔗

@@ -31,6 +31,14 @@ pub enum AssistantDockPosition {
     Bottom,
 }
 
+#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub enum DefaultView {
+    #[default]
+    Agent,
+    Thread,
+}
+
 #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
 #[serde(rename_all = "snake_case")]
 pub enum NotifyWhenAgentWaiting {
@@ -93,6 +101,7 @@ pub struct AssistantSettings {
     pub inline_alternatives: Vec<LanguageModelSelection>,
     pub using_outdated_settings_version: bool,
     pub default_profile: AgentProfileId,
+    pub default_view: DefaultView,
     pub profiles: IndexMap<AgentProfileId, AgentProfile>,
     pub always_allow_tool_actions: bool,
     pub notify_when_agent_waiting: NotifyWhenAgentWaiting,
@@ -267,6 +276,7 @@ impl AssistantSettingsContent {
                     thread_summary_model: None,
                     inline_alternatives: None,
                     default_profile: None,
+                    default_view: None,
                     profiles: None,
                     always_allow_tool_actions: None,
                     notify_when_agent_waiting: None,
@@ -298,6 +308,7 @@ impl AssistantSettingsContent {
                 thread_summary_model: None,
                 inline_alternatives: None,
                 default_profile: None,
+                default_view: None,
                 profiles: None,
                 always_allow_tool_actions: None,
                 notify_when_agent_waiting: None,
@@ -583,6 +594,7 @@ impl Default for VersionedAssistantSettingsContent {
             thread_summary_model: None,
             inline_alternatives: None,
             default_profile: None,
+            default_view: None,
             profiles: None,
             always_allow_tool_actions: None,
             notify_when_agent_waiting: None,
@@ -632,6 +644,10 @@ pub struct AssistantSettingsContentV2 {
     ///
     /// Default: write
     default_profile: Option<AgentProfileId>,
+    /// The default assistant panel type.
+    ///
+    /// Default: agentic
+    default_view: Option<DefaultView>,
     /// The available agent profiles.
     pub profiles: Option<IndexMap<AgentProfileId, AgentProfileContent>>,
     /// Whenever a tool action would normally wait for your confirmation
@@ -872,6 +888,7 @@ impl Settings for AssistantSettings {
             merge(&mut settings.stream_edits, value.stream_edits);
             merge(&mut settings.single_file_review, value.single_file_review);
             merge(&mut settings.default_profile, value.default_profile);
+            merge(&mut settings.default_view, value.default_view);
             merge(
                 &mut settings.preferred_completion_mode,
                 value.preferred_completion_mode,
@@ -1008,6 +1025,7 @@ mod tests {
                                 default_width: None,
                                 default_height: None,
                                 default_profile: None,
+                                default_view: None,
                                 profiles: None,
                                 always_allow_tool_actions: None,
                                 notify_when_agent_waiting: None,