repl: Correctly discover user's kernels (#50978)

Nadir and Finn Evers created

Closes #50977

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

Before:
<img width="1700" height="1063" alt="image"
src="https://github.com/user-attachments/assets/fd8e8438-a8a8-4d00-ac72-7e5ab75c8723"
/>

After:
<img width="1700" height="1066" alt="image"
src="https://github.com/user-attachments/assets/e31e449d-93ce-433e-94fd-cfdc08d61f49"
/>


Release Notes:

- Fixed kernels discovery in python notebook editor.

---------

Co-authored-by: Finn Evers <finn@zed.dev>

Change summary

crates/repl/src/notebook/notebook_ui.rs | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)

Detailed changes

crates/repl/src/notebook/notebook_ui.rs 🔗

@@ -206,13 +206,14 @@ impl NotebookEditor {
             cell_order: cell_order.clone(),
             original_cell_order: cell_order.clone(),
             cell_map: cell_map.clone(),
-            kernel: Kernel::Shutdown, // TODO: use recommended kernel after the implementation is done in repl
+            kernel: Kernel::Shutdown,
             kernel_specification: None,
             execution_requests: HashMap::default(),
             kernel_picker_handle: PopoverMenuHandle::default(),
         };
         editor.launch_kernel(window, cx);
         editor.refresh_language(cx);
+        editor.refresh_kernelspecs(cx);
 
         cx.subscribe(&notebook_item, |this, _item, _event, cx| {
             this.refresh_language(cx);
@@ -222,6 +223,18 @@ impl NotebookEditor {
         editor
     }
 
+    fn refresh_kernelspecs(&mut self, cx: &mut Context<Self>) {
+        let store = ReplStore::global(cx);
+        let project = self.project.clone();
+        let worktree_id = self.worktree_id;
+
+        let refresh_task = store.update(cx, |store, cx| {
+            store.refresh_python_kernelspecs(worktree_id, &project, cx)
+        });
+
+        cx.background_spawn(refresh_task).detach_and_log_err(cx);
+    }
+
     fn refresh_language(&mut self, cx: &mut Context<Self>) {
         let notebook_language = self.notebook_item.read(cx).notebook_language();
         let task = cx.spawn(async move |this, cx| {
@@ -313,8 +326,13 @@ impl NotebookEditor {
     }
 
     fn launch_kernel(&mut self, window: &mut Window, cx: &mut Context<Self>) {
-        // use default Python kernel if no specification is set
-        let spec = self.kernel_specification.clone().unwrap_or_else(|| {
+        let spec = self.kernel_specification.clone().or_else(|| {
+            ReplStore::global(cx)
+                .read(cx)
+                .active_kernelspec(self.worktree_id, None, cx)
+        });
+
+        let spec = spec.unwrap_or_else(|| {
             KernelSpecification::Jupyter(LocalKernelSpecification {
                 name: "python3".to_string(),
                 path: PathBuf::from("python3"),