agent: Fix panic when opening Agent diff from the workspace (#28132)

Marshall Bowers created

This PR fixes a panic that could occur when opening the Agent diff from
the workspace (with the agent panel closed).

Release Notes:

- agent: Fixed a panic when running the `agent: open agent diff` command
with the Agent Panel closed.

Change summary

crates/agent/src/agent_diff.rs      | 33 +++++++++++++++++-------------
crates/agent/src/assistant_panel.rs | 11 ++++++---
2 files changed, 26 insertions(+), 18 deletions(-)

Detailed changes

crates/agent/src/agent_diff.rs 🔗

@@ -45,23 +45,28 @@ impl AgentDiff {
         window: &mut Window,
         cx: &mut App,
     ) -> Result<Entity<Self>> {
-        let existing_diff = workspace.update(cx, |workspace, cx| {
-            workspace
-                .items_of_type::<AgentDiff>(cx)
-                .find(|diff| diff.read(cx).thread == thread)
-        })?;
+        workspace.update(cx, |workspace, cx| {
+            Self::deploy_in_workspace(thread, workspace, window, cx)
+        })
+    }
+
+    pub fn deploy_in_workspace(
+        thread: Entity<Thread>,
+        workspace: &mut Workspace,
+        window: &mut Window,
+        cx: &mut Context<Workspace>,
+    ) -> Entity<Self> {
+        let existing_diff = workspace
+            .items_of_type::<AgentDiff>(cx)
+            .find(|diff| diff.read(cx).thread == thread);
         if let Some(existing_diff) = existing_diff {
-            workspace.update(cx, |workspace, cx| {
-                workspace.activate_item(&existing_diff, true, true, window, cx);
-            })?;
-            Ok(existing_diff)
+            workspace.activate_item(&existing_diff, true, true, window, cx);
+            existing_diff
         } else {
             let agent_diff =
-                cx.new(|cx| AgentDiff::new(thread.clone(), workspace.clone(), window, cx));
-            workspace.update(cx, |workspace, cx| {
-                workspace.add_item_to_center(Box::new(agent_diff.clone()), window, cx);
-            })?;
-            Ok(agent_diff)
+                cx.new(|cx| AgentDiff::new(thread.clone(), workspace.weak_handle(), window, cx));
+            workspace.add_item_to_center(Box::new(agent_diff.clone()), window, cx);
+            agent_diff
         }
     }
 

crates/agent/src/assistant_panel.rs 🔗

@@ -92,9 +92,8 @@ pub fn init(cx: &mut App) {
                 .register_action(|workspace, _: &OpenAgentDiff, window, cx| {
                     if let Some(panel) = workspace.panel::<AssistantPanel>(cx) {
                         workspace.focus_panel::<AssistantPanel>(window, cx);
-                        panel.update(cx, |panel, cx| {
-                            panel.open_agent_diff(&OpenAgentDiff, window, cx);
-                        });
+                        let thread = panel.read(cx).thread.read(cx).thread().clone();
+                        AgentDiff::deploy_in_workspace(thread, workspace, window, cx);
                     }
                 });
         },
@@ -538,7 +537,11 @@ impl AssistantPanel {
         cx: &mut Context<Self>,
     ) {
         let thread = self.thread.read(cx).thread().clone();
-        AgentDiff::deploy(thread, self.workspace.clone(), window, cx).log_err();
+        self.workspace
+            .update(cx, |workspace, cx| {
+                AgentDiff::deploy_in_workspace(thread, workspace, window, cx)
+            })
+            .log_err();
     }
 
     pub(crate) fn open_configuration(&mut self, window: &mut Window, cx: &mut Context<Self>) {