agent: Restore last used agent session on startup (#36401)

Bennet Bo Fenner created

Release Notes:

- N/A

Change summary

crates/agent2/src/agent.rs         | 17 ++++--
crates/agent2/src/thread.rs        |  5 +
crates/agent_ui/src/agent_panel.rs | 71 +++++++++++++++++++------------
crates/agent_ui/src/agent_ui.rs    |  2 
4 files changed, 60 insertions(+), 35 deletions(-)

Detailed changes

crates/agent2/src/agent.rs 🔗

@@ -425,13 +425,18 @@ impl NativeAgent {
         cx: &mut Context<Self>,
     ) {
         self.models.refresh_list(cx);
+
+        let default_model = LanguageModelRegistry::read_global(cx)
+            .default_model()
+            .map(|m| m.model.clone());
+
         for session in self.sessions.values_mut() {
-            session.thread.update(cx, |thread, _| {
-                if let Some(model) = thread.model() {
-                    let model_id = LanguageModels::model_id(model);
-                    if let Some(model) = self.models.model_from_id(&model_id) {
-                        thread.set_model(model.clone());
-                    }
+            session.thread.update(cx, |thread, cx| {
+                if thread.model().is_none()
+                    && let Some(model) = default_model.clone()
+                {
+                    thread.set_model(model);
+                    cx.notify();
                 }
             });
         }

crates/agent2/src/thread.rs 🔗

@@ -622,7 +622,10 @@ impl Thread {
     ) -> Result<mpsc::UnboundedReceiver<Result<AgentResponseEvent>>> {
         self.cancel();
 
-        let model = self.model.clone().context("No language model configured")?;
+        let model = self
+            .model()
+            .cloned()
+            .context("No language model configured")?;
         let (events_tx, events_rx) = mpsc::unbounded::<Result<AgentResponseEvent>>();
         let event_stream = AgentResponseEventStream(events_tx);
         let message_ix = self.messages.len().saturating_sub(1);

crates/agent_ui/src/agent_panel.rs 🔗

@@ -573,6 +573,7 @@ impl AgentPanel {
                         panel.width = serialized_panel.width.map(|w| w.round());
                         if let Some(selected_agent) = serialized_panel.selected_agent {
                             panel.selected_agent = selected_agent;
+                            panel.new_agent_thread(selected_agent, window, cx);
                         }
                         cx.notify();
                     });
@@ -1631,16 +1632,53 @@ impl AgentPanel {
         menu
     }
 
-    pub fn set_selected_agent(&mut self, agent: AgentType, cx: &mut Context<Self>) {
+    pub fn set_selected_agent(
+        &mut self,
+        agent: AgentType,
+        window: &mut Window,
+        cx: &mut Context<Self>,
+    ) {
         if self.selected_agent != agent {
             self.selected_agent = agent;
             self.serialize(cx);
+            self.new_agent_thread(agent, window, cx);
         }
     }
 
     pub fn selected_agent(&self) -> AgentType {
         self.selected_agent
     }
+
+    pub fn new_agent_thread(
+        &mut self,
+        agent: AgentType,
+        window: &mut Window,
+        cx: &mut Context<Self>,
+    ) {
+        match agent {
+            AgentType::Zed => {
+                window.dispatch_action(
+                    NewThread {
+                        from_thread_id: None,
+                    }
+                    .boxed_clone(),
+                    cx,
+                );
+            }
+            AgentType::TextThread => {
+                window.dispatch_action(NewTextThread.boxed_clone(), cx);
+            }
+            AgentType::NativeAgent => {
+                self.new_external_thread(Some(crate::ExternalAgent::NativeAgent), window, cx)
+            }
+            AgentType::Gemini => {
+                self.new_external_thread(Some(crate::ExternalAgent::Gemini), window, cx)
+            }
+            AgentType::ClaudeCode => {
+                self.new_external_thread(Some(crate::ExternalAgent::ClaudeCode), window, cx)
+            }
+        }
+    }
 }
 
 impl Focusable for AgentPanel {
@@ -2221,16 +2259,13 @@ impl AgentPanel {
                                                         panel.update(cx, |panel, cx| {
                                                             panel.set_selected_agent(
                                                                 AgentType::Zed,
+                                                                window,
                                                                 cx,
                                                             );
                                                         });
                                                     }
                                                 });
                                             }
-                                            window.dispatch_action(
-                                                NewThread::default().boxed_clone(),
-                                                cx,
-                                            );
                                         }
                                     }),
                             )
@@ -2250,13 +2285,13 @@ impl AgentPanel {
                                                         panel.update(cx, |panel, cx| {
                                                             panel.set_selected_agent(
                                                                 AgentType::TextThread,
+                                                                window,
                                                                 cx,
                                                             );
                                                         });
                                                     }
                                                 });
                                             }
-                                            window.dispatch_action(NewTextThread.boxed_clone(), cx);
                                         }
                                     }),
                             )
@@ -2275,19 +2310,13 @@ impl AgentPanel {
                                                         panel.update(cx, |panel, cx| {
                                                             panel.set_selected_agent(
                                                                 AgentType::NativeAgent,
+                                                                window,
                                                                 cx,
                                                             );
                                                         });
                                                     }
                                                 });
                                             }
-                                            window.dispatch_action(
-                                                NewExternalAgentThread {
-                                                    agent: Some(crate::ExternalAgent::NativeAgent),
-                                                }
-                                                .boxed_clone(),
-                                                cx,
-                                            );
                                         }
                                     }),
                             )
@@ -2308,19 +2337,13 @@ impl AgentPanel {
                                                         panel.update(cx, |panel, cx| {
                                                             panel.set_selected_agent(
                                                                 AgentType::Gemini,
+                                                                window,
                                                                 cx,
                                                             );
                                                         });
                                                     }
                                                 });
                                             }
-                                            window.dispatch_action(
-                                                NewExternalAgentThread {
-                                                    agent: Some(crate::ExternalAgent::Gemini),
-                                                }
-                                                .boxed_clone(),
-                                                cx,
-                                            );
                                         }
                                     }),
                             )
@@ -2339,19 +2362,13 @@ impl AgentPanel {
                                                         panel.update(cx, |panel, cx| {
                                                             panel.set_selected_agent(
                                                                 AgentType::ClaudeCode,
+                                                                window,
                                                                 cx,
                                                             );
                                                         });
                                                     }
                                                 });
                                             }
-                                            window.dispatch_action(
-                                                NewExternalAgentThread {
-                                                    agent: Some(crate::ExternalAgent::ClaudeCode),
-                                                }
-                                                .boxed_clone(),
-                                                cx,
-                                            );
                                         }
                                     }),
                             );

crates/agent_ui/src/agent_ui.rs 🔗

@@ -146,7 +146,7 @@ pub struct NewExternalAgentThread {
     agent: Option<ExternalAgent>,
 }
 
-#[derive(Default, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)]
+#[derive(Default, Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)]
 #[serde(rename_all = "snake_case")]
 enum ExternalAgent {
     #[default]