manage_profiles_modal.rs

  1mod profile_modal_header;
  2
  3use std::sync::Arc;
  4
  5use agent_settings::{AgentProfileId, AgentSettings, builtin_profiles};
  6use assistant_tool::ToolWorkingSet;
  7use editor::Editor;
  8use fs::Fs;
  9use gpui::{DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Subscription, prelude::*};
 10use settings::Settings as _;
 11use ui::{
 12    KeyBinding, ListItem, ListItemSpacing, ListSeparator, Navigable, NavigableEntry, prelude::*,
 13};
 14use workspace::{ModalView, Workspace};
 15
 16use crate::agent_configuration::manage_profiles_modal::profile_modal_header::ProfileModalHeader;
 17use crate::agent_configuration::tool_picker::{ToolPicker, ToolPickerDelegate};
 18use crate::{AgentPanel, ManageProfiles};
 19use agent::agent_profile::AgentProfile;
 20
 21use super::tool_picker::ToolPickerMode;
 22
 23enum Mode {
 24    ChooseProfile(ChooseProfileMode),
 25    NewProfile(NewProfileMode),
 26    ViewProfile(ViewProfileMode),
 27    ConfigureTools {
 28        profile_id: AgentProfileId,
 29        tool_picker: Entity<ToolPicker>,
 30        _subscription: Subscription,
 31    },
 32    ConfigureMcps {
 33        profile_id: AgentProfileId,
 34        tool_picker: Entity<ToolPicker>,
 35        _subscription: Subscription,
 36    },
 37}
 38
 39impl Mode {
 40    pub fn choose_profile(_window: &mut Window, cx: &mut Context<ManageProfilesModal>) -> Self {
 41        let settings = AgentSettings::get_global(cx);
 42
 43        let mut builtin_profiles = Vec::new();
 44        let mut custom_profiles = Vec::new();
 45
 46        for (profile_id, profile) in settings.profiles.iter() {
 47            let entry = ProfileEntry {
 48                id: profile_id.clone(),
 49                name: profile.name.clone(),
 50                navigation: NavigableEntry::focusable(cx),
 51            };
 52            if builtin_profiles::is_builtin(profile_id) {
 53                builtin_profiles.push(entry);
 54            } else {
 55                custom_profiles.push(entry);
 56            }
 57        }
 58
 59        builtin_profiles.sort_unstable_by(|a, b| a.name.cmp(&b.name));
 60        custom_profiles.sort_unstable_by(|a, b| a.name.cmp(&b.name));
 61
 62        Self::ChooseProfile(ChooseProfileMode {
 63            builtin_profiles,
 64            custom_profiles,
 65            add_new_profile: NavigableEntry::focusable(cx),
 66        })
 67    }
 68}
 69
 70#[derive(Clone)]
 71struct ProfileEntry {
 72    pub id: AgentProfileId,
 73    pub name: SharedString,
 74    pub navigation: NavigableEntry,
 75}
 76
 77#[derive(Clone)]
 78pub struct ChooseProfileMode {
 79    builtin_profiles: Vec<ProfileEntry>,
 80    custom_profiles: Vec<ProfileEntry>,
 81    add_new_profile: NavigableEntry,
 82}
 83
 84#[derive(Clone)]
 85pub struct ViewProfileMode {
 86    profile_id: AgentProfileId,
 87    fork_profile: NavigableEntry,
 88    configure_tools: NavigableEntry,
 89    configure_mcps: NavigableEntry,
 90    cancel_item: NavigableEntry,
 91}
 92
 93#[derive(Clone)]
 94pub struct NewProfileMode {
 95    name_editor: Entity<Editor>,
 96    base_profile_id: Option<AgentProfileId>,
 97}
 98
 99pub struct ManageProfilesModal {
100    fs: Arc<dyn Fs>,
101    tools: Entity<ToolWorkingSet>,
102    focus_handle: FocusHandle,
103    mode: Mode,
104}
105
106impl ManageProfilesModal {
107    pub fn register(
108        workspace: &mut Workspace,
109        _window: Option<&mut Window>,
110        _cx: &mut Context<Workspace>,
111    ) {
112        workspace.register_action(|workspace, action: &ManageProfiles, window, cx| {
113            if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
114                let fs = workspace.app_state().fs.clone();
115                let thread_store = panel.read(cx).thread_store();
116                let tools = thread_store.read(cx).tools();
117                workspace.toggle_modal(window, cx, |window, cx| {
118                    let mut this = Self::new(fs, tools, window, cx);
119
120                    if let Some(profile_id) = action.customize_tools.clone() {
121                        this.configure_builtin_tools(profile_id, window, cx);
122                    }
123
124                    this
125                })
126            }
127        });
128    }
129
130    pub fn new(
131        fs: Arc<dyn Fs>,
132        tools: Entity<ToolWorkingSet>,
133        window: &mut Window,
134        cx: &mut Context<Self>,
135    ) -> Self {
136        let focus_handle = cx.focus_handle();
137
138        Self {
139            fs,
140            tools,
141            focus_handle,
142            mode: Mode::choose_profile(window, cx),
143        }
144    }
145
146    fn choose_profile(&mut self, window: &mut Window, cx: &mut Context<Self>) {
147        self.mode = Mode::choose_profile(window, cx);
148        self.focus_handle(cx).focus(window);
149    }
150
151    fn new_profile(
152        &mut self,
153        base_profile_id: Option<AgentProfileId>,
154        window: &mut Window,
155        cx: &mut Context<Self>,
156    ) {
157        let name_editor = cx.new(|cx| Editor::single_line(window, cx));
158        name_editor.update(cx, |editor, cx| {
159            editor.set_placeholder_text("Profile name", cx);
160        });
161
162        self.mode = Mode::NewProfile(NewProfileMode {
163            name_editor,
164            base_profile_id,
165        });
166        self.focus_handle(cx).focus(window);
167    }
168
169    pub fn view_profile(
170        &mut self,
171        profile_id: AgentProfileId,
172        window: &mut Window,
173        cx: &mut Context<Self>,
174    ) {
175        self.mode = Mode::ViewProfile(ViewProfileMode {
176            profile_id,
177            fork_profile: NavigableEntry::focusable(cx),
178            configure_tools: NavigableEntry::focusable(cx),
179            configure_mcps: NavigableEntry::focusable(cx),
180            cancel_item: NavigableEntry::focusable(cx),
181        });
182        self.focus_handle(cx).focus(window);
183    }
184
185    fn configure_mcp_tools(
186        &mut self,
187        profile_id: AgentProfileId,
188        window: &mut Window,
189        cx: &mut Context<Self>,
190    ) {
191        let settings = AgentSettings::get_global(cx);
192        let Some(profile) = settings.profiles.get(&profile_id).cloned() else {
193            return;
194        };
195
196        let tool_picker = cx.new(|cx| {
197            let delegate = ToolPickerDelegate::new(
198                ToolPickerMode::McpTools,
199                self.fs.clone(),
200                self.tools.clone(),
201                profile_id.clone(),
202                profile,
203                cx,
204            );
205            ToolPicker::mcp_tools(delegate, window, cx)
206        });
207        let dismiss_subscription = cx.subscribe_in(&tool_picker, window, {
208            let profile_id = profile_id.clone();
209            move |this, _tool_picker, _: &DismissEvent, window, cx| {
210                this.view_profile(profile_id.clone(), window, cx);
211            }
212        });
213
214        self.mode = Mode::ConfigureMcps {
215            profile_id,
216            tool_picker,
217            _subscription: dismiss_subscription,
218        };
219        self.focus_handle(cx).focus(window);
220    }
221
222    fn configure_builtin_tools(
223        &mut self,
224        profile_id: AgentProfileId,
225        window: &mut Window,
226        cx: &mut Context<Self>,
227    ) {
228        let settings = AgentSettings::get_global(cx);
229        let Some(profile) = settings.profiles.get(&profile_id).cloned() else {
230            return;
231        };
232
233        let tool_picker = cx.new(|cx| {
234            let delegate = ToolPickerDelegate::new(
235                ToolPickerMode::BuiltinTools,
236                self.fs.clone(),
237                self.tools.clone(),
238                profile_id.clone(),
239                profile,
240                cx,
241            );
242            ToolPicker::builtin_tools(delegate, window, cx)
243        });
244        let dismiss_subscription = cx.subscribe_in(&tool_picker, window, {
245            let profile_id = profile_id.clone();
246            move |this, _tool_picker, _: &DismissEvent, window, cx| {
247                this.view_profile(profile_id.clone(), window, cx);
248            }
249        });
250
251        self.mode = Mode::ConfigureTools {
252            profile_id,
253            tool_picker,
254            _subscription: dismiss_subscription,
255        };
256        self.focus_handle(cx).focus(window);
257    }
258
259    fn confirm(&mut self, window: &mut Window, cx: &mut Context<Self>) {
260        match &self.mode {
261            Mode::ChooseProfile { .. } => {}
262            Mode::NewProfile(mode) => {
263                let name = mode.name_editor.read(cx).text(cx);
264
265                let profile_id =
266                    AgentProfile::create(name, mode.base_profile_id.clone(), self.fs.clone(), cx);
267                self.view_profile(profile_id, window, cx);
268            }
269            Mode::ViewProfile(_) => {}
270            Mode::ConfigureTools { .. } => {}
271            Mode::ConfigureMcps { .. } => {}
272        }
273    }
274
275    fn cancel(&mut self, window: &mut Window, cx: &mut Context<Self>) {
276        match &self.mode {
277            Mode::ChooseProfile { .. } => {
278                cx.emit(DismissEvent);
279            }
280            Mode::NewProfile(mode) => {
281                if let Some(profile_id) = mode.base_profile_id.clone() {
282                    self.view_profile(profile_id, window, cx);
283                } else {
284                    self.choose_profile(window, cx);
285                }
286            }
287            Mode::ViewProfile(_) => self.choose_profile(window, cx),
288            Mode::ConfigureTools { profile_id, .. } => {
289                self.view_profile(profile_id.clone(), window, cx)
290            }
291            Mode::ConfigureMcps { profile_id, .. } => {
292                self.view_profile(profile_id.clone(), window, cx)
293            }
294        }
295    }
296}
297
298impl ModalView for ManageProfilesModal {}
299
300impl Focusable for ManageProfilesModal {
301    fn focus_handle(&self, cx: &App) -> FocusHandle {
302        match &self.mode {
303            Mode::ChooseProfile(_) => self.focus_handle.clone(),
304            Mode::NewProfile(mode) => mode.name_editor.focus_handle(cx),
305            Mode::ViewProfile(_) => self.focus_handle.clone(),
306            Mode::ConfigureTools { tool_picker, .. } => tool_picker.focus_handle(cx),
307            Mode::ConfigureMcps { tool_picker, .. } => tool_picker.focus_handle(cx),
308        }
309    }
310}
311
312impl EventEmitter<DismissEvent> for ManageProfilesModal {}
313
314impl ManageProfilesModal {
315    fn render_profile(
316        &self,
317        profile: &ProfileEntry,
318        window: &mut Window,
319        cx: &mut Context<Self>,
320    ) -> impl IntoElement + use<> {
321        div()
322            .id(SharedString::from(format!("profile-{}", profile.id)))
323            .track_focus(&profile.navigation.focus_handle)
324            .on_action({
325                let profile_id = profile.id.clone();
326                cx.listener(move |this, _: &menu::Confirm, window, cx| {
327                    this.view_profile(profile_id.clone(), window, cx);
328                })
329            })
330            .child(
331                ListItem::new(SharedString::from(format!("profile-{}", profile.id)))
332                    .toggle_state(profile.navigation.focus_handle.contains_focused(window, cx))
333                    .inset(true)
334                    .spacing(ListItemSpacing::Sparse)
335                    .child(Label::new(profile.name.clone()))
336                    .end_slot(
337                        h_flex()
338                            .gap_1()
339                            .child(
340                                Label::new("Customize")
341                                    .size(LabelSize::Small)
342                                    .color(Color::Muted),
343                            )
344                            .children(KeyBinding::for_action_in(
345                                &menu::Confirm,
346                                &self.focus_handle,
347                                window,
348                                cx,
349                            )),
350                    )
351                    .on_click({
352                        let profile_id = profile.id.clone();
353                        cx.listener(move |this, _, window, cx| {
354                            this.view_profile(profile_id.clone(), window, cx);
355                        })
356                    }),
357            )
358    }
359
360    fn render_choose_profile(
361        &mut self,
362        mode: ChooseProfileMode,
363        window: &mut Window,
364        cx: &mut Context<Self>,
365    ) -> impl IntoElement {
366        Navigable::new(
367            div()
368                .track_focus(&self.focus_handle(cx))
369                .size_full()
370                .child(ProfileModalHeader::new("Agent Profiles", None))
371                .child(
372                    v_flex()
373                        .pb_1()
374                        .child(ListSeparator)
375                        .children(
376                            mode.builtin_profiles
377                                .iter()
378                                .map(|profile| self.render_profile(profile, window, cx)),
379                        )
380                        .when(!mode.custom_profiles.is_empty(), |this| {
381                            this.child(ListSeparator)
382                                .child(
383                                    div().pl_2().pb_1().child(
384                                        Label::new("Custom Profiles")
385                                            .size(LabelSize::Small)
386                                            .color(Color::Muted),
387                                    ),
388                                )
389                                .children(
390                                    mode.custom_profiles
391                                        .iter()
392                                        .map(|profile| self.render_profile(profile, window, cx)),
393                                )
394                        })
395                        .child(ListSeparator)
396                        .child(
397                            div()
398                                .id("new-profile")
399                                .track_focus(&mode.add_new_profile.focus_handle)
400                                .on_action(cx.listener(|this, _: &menu::Confirm, window, cx| {
401                                    this.new_profile(None, window, cx);
402                                }))
403                                .child(
404                                    ListItem::new("new-profile")
405                                        .toggle_state(
406                                            mode.add_new_profile
407                                                .focus_handle
408                                                .contains_focused(window, cx),
409                                        )
410                                        .inset(true)
411                                        .spacing(ListItemSpacing::Sparse)
412                                        .start_slot(Icon::new(IconName::Plus))
413                                        .child(Label::new("Add New Profile"))
414                                        .on_click({
415                                            cx.listener(move |this, _, window, cx| {
416                                                this.new_profile(None, window, cx);
417                                            })
418                                        }),
419                                ),
420                        ),
421                )
422                .into_any_element(),
423        )
424        .map(|mut navigable| {
425            for profile in mode.builtin_profiles {
426                navigable = navigable.entry(profile.navigation);
427            }
428            for profile in mode.custom_profiles {
429                navigable = navigable.entry(profile.navigation);
430            }
431
432            navigable
433        })
434        .entry(mode.add_new_profile)
435    }
436
437    fn render_new_profile(
438        &mut self,
439        mode: NewProfileMode,
440        _window: &mut Window,
441        cx: &mut Context<Self>,
442    ) -> impl IntoElement {
443        let settings = AgentSettings::get_global(cx);
444
445        let base_profile_name = mode.base_profile_id.as_ref().map(|base_profile_id| {
446            settings
447                .profiles
448                .get(base_profile_id)
449                .map(|profile| profile.name.clone())
450                .unwrap_or_else(|| "Unknown".into())
451        });
452
453        v_flex()
454            .id("new-profile")
455            .track_focus(&self.focus_handle(cx))
456            .child(ProfileModalHeader::new(
457                match &base_profile_name {
458                    Some(base_profile) => format!("Fork {base_profile}"),
459                    None => "New Profile".into(),
460                },
461                match base_profile_name {
462                    Some(_) => Some(IconName::Scissors),
463                    None => Some(IconName::Plus),
464                },
465            ))
466            .child(ListSeparator)
467            .child(h_flex().p_2().child(mode.name_editor))
468    }
469
470    fn render_view_profile(
471        &mut self,
472        mode: ViewProfileMode,
473        window: &mut Window,
474        cx: &mut Context<Self>,
475    ) -> impl IntoElement {
476        let settings = AgentSettings::get_global(cx);
477
478        let profile_name = settings
479            .profiles
480            .get(&mode.profile_id)
481            .map(|profile| profile.name.clone())
482            .unwrap_or_else(|| "Unknown".into());
483
484        let icon = match mode.profile_id.as_str() {
485            "write" => IconName::Pencil,
486            "ask" => IconName::Chat,
487            _ => IconName::UserRoundPen,
488        };
489
490        Navigable::new(
491            div()
492                .track_focus(&self.focus_handle(cx))
493                .size_full()
494                .child(ProfileModalHeader::new(profile_name, Some(icon)))
495                .child(
496                    v_flex()
497                        .pb_1()
498                        .child(ListSeparator)
499                        .child(
500                            div()
501                                .id("fork-profile")
502                                .track_focus(&mode.fork_profile.focus_handle)
503                                .on_action({
504                                    let profile_id = mode.profile_id.clone();
505                                    cx.listener(move |this, _: &menu::Confirm, window, cx| {
506                                        this.new_profile(Some(profile_id.clone()), window, cx);
507                                    })
508                                })
509                                .child(
510                                    ListItem::new("fork-profile")
511                                        .toggle_state(
512                                            mode.fork_profile
513                                                .focus_handle
514                                                .contains_focused(window, cx),
515                                        )
516                                        .inset(true)
517                                        .spacing(ListItemSpacing::Sparse)
518                                        .start_slot(
519                                            Icon::new(IconName::Scissors)
520                                                .size(IconSize::Small)
521                                                .color(Color::Muted),
522                                        )
523                                        .child(Label::new("Fork Profile"))
524                                        .on_click({
525                                            let profile_id = mode.profile_id.clone();
526                                            cx.listener(move |this, _, window, cx| {
527                                                this.new_profile(
528                                                    Some(profile_id.clone()),
529                                                    window,
530                                                    cx,
531                                                );
532                                            })
533                                        }),
534                                ),
535                        )
536                        .child(
537                            div()
538                                .id("configure-builtin-tools")
539                                .track_focus(&mode.configure_tools.focus_handle)
540                                .on_action({
541                                    let profile_id = mode.profile_id.clone();
542                                    cx.listener(move |this, _: &menu::Confirm, window, cx| {
543                                        this.configure_builtin_tools(
544                                            profile_id.clone(),
545                                            window,
546                                            cx,
547                                        );
548                                    })
549                                })
550                                .child(
551                                    ListItem::new("configure-builtin-tools-item")
552                                        .toggle_state(
553                                            mode.configure_tools
554                                                .focus_handle
555                                                .contains_focused(window, cx),
556                                        )
557                                        .inset(true)
558                                        .spacing(ListItemSpacing::Sparse)
559                                        .start_slot(
560                                            Icon::new(IconName::Settings)
561                                                .size(IconSize::Small)
562                                                .color(Color::Muted),
563                                        )
564                                        .child(Label::new("Configure Built-in Tools"))
565                                        .on_click({
566                                            let profile_id = mode.profile_id.clone();
567                                            cx.listener(move |this, _, window, cx| {
568                                                this.configure_builtin_tools(
569                                                    profile_id.clone(),
570                                                    window,
571                                                    cx,
572                                                );
573                                            })
574                                        }),
575                                ),
576                        )
577                        .child(
578                            div()
579                                .id("configure-mcps")
580                                .track_focus(&mode.configure_mcps.focus_handle)
581                                .on_action({
582                                    let profile_id = mode.profile_id.clone();
583                                    cx.listener(move |this, _: &menu::Confirm, window, cx| {
584                                        this.configure_mcp_tools(profile_id.clone(), window, cx);
585                                    })
586                                })
587                                .child(
588                                    ListItem::new("configure-mcp-tools")
589                                        .toggle_state(
590                                            mode.configure_mcps
591                                                .focus_handle
592                                                .contains_focused(window, cx),
593                                        )
594                                        .inset(true)
595                                        .spacing(ListItemSpacing::Sparse)
596                                        .start_slot(
597                                            Icon::new(IconName::ToolHammer)
598                                                .size(IconSize::Small)
599                                                .color(Color::Muted),
600                                        )
601                                        .child(Label::new("Configure MCP Tools"))
602                                        .on_click({
603                                            let profile_id = mode.profile_id.clone();
604                                            cx.listener(move |this, _, window, cx| {
605                                                this.configure_mcp_tools(
606                                                    profile_id.clone(),
607                                                    window,
608                                                    cx,
609                                                );
610                                            })
611                                        }),
612                                ),
613                        )
614                        .child(ListSeparator)
615                        .child(
616                            div()
617                                .id("cancel-item")
618                                .track_focus(&mode.cancel_item.focus_handle)
619                                .on_action({
620                                    cx.listener(move |this, _: &menu::Confirm, window, cx| {
621                                        this.cancel(window, cx);
622                                    })
623                                })
624                                .child(
625                                    ListItem::new("cancel-item")
626                                        .toggle_state(
627                                            mode.cancel_item
628                                                .focus_handle
629                                                .contains_focused(window, cx),
630                                        )
631                                        .inset(true)
632                                        .spacing(ListItemSpacing::Sparse)
633                                        .start_slot(
634                                            Icon::new(IconName::ArrowLeft)
635                                                .size(IconSize::Small)
636                                                .color(Color::Muted),
637                                        )
638                                        .child(Label::new("Go Back"))
639                                        .end_slot(
640                                            div().children(
641                                                KeyBinding::for_action_in(
642                                                    &menu::Cancel,
643                                                    &self.focus_handle,
644                                                    window,
645                                                    cx,
646                                                )
647                                                .map(|kb| kb.size(rems_from_px(12.))),
648                                            ),
649                                        )
650                                        .on_click({
651                                            cx.listener(move |this, _, window, cx| {
652                                                this.cancel(window, cx);
653                                            })
654                                        }),
655                                ),
656                        ),
657                )
658                .into_any_element(),
659        )
660        .entry(mode.fork_profile)
661        .entry(mode.configure_tools)
662        .entry(mode.configure_mcps)
663        .entry(mode.cancel_item)
664    }
665}
666
667impl Render for ManageProfilesModal {
668    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
669        let settings = AgentSettings::get_global(cx);
670
671        let go_back_item = div()
672            .id("cancel-item")
673            .track_focus(&self.focus_handle)
674            .on_action({
675                cx.listener(move |this, _: &menu::Confirm, window, cx| {
676                    this.cancel(window, cx);
677                })
678            })
679            .child(
680                ListItem::new("cancel-item")
681                    .toggle_state(self.focus_handle.contains_focused(window, cx))
682                    .inset(true)
683                    .spacing(ListItemSpacing::Sparse)
684                    .start_slot(
685                        Icon::new(IconName::ArrowLeft)
686                            .size(IconSize::Small)
687                            .color(Color::Muted),
688                    )
689                    .child(Label::new("Go Back"))
690                    .end_slot(
691                        div().children(
692                            KeyBinding::for_action_in(
693                                &menu::Cancel,
694                                &self.focus_handle,
695                                window,
696                                cx,
697                            )
698                            .map(|kb| kb.size(rems_from_px(12.))),
699                        ),
700                    )
701                    .on_click({
702                        cx.listener(move |this, _, window, cx| {
703                            this.cancel(window, cx);
704                        })
705                    }),
706            );
707
708        div()
709            .elevation_3(cx)
710            .w(rems(34.))
711            .key_context("ManageProfilesModal")
712            .on_action(cx.listener(|this, _: &menu::Cancel, window, cx| this.cancel(window, cx)))
713            .on_action(cx.listener(|this, _: &menu::Confirm, window, cx| this.confirm(window, cx)))
714            .capture_any_mouse_down(cx.listener(|this, _, window, cx| {
715                this.focus_handle(cx).focus(window);
716            }))
717            .on_mouse_down_out(cx.listener(|_this, _, _, cx| cx.emit(DismissEvent)))
718            .child(match &self.mode {
719                Mode::ChooseProfile(mode) => self
720                    .render_choose_profile(mode.clone(), window, cx)
721                    .into_any_element(),
722                Mode::NewProfile(mode) => self
723                    .render_new_profile(mode.clone(), window, cx)
724                    .into_any_element(),
725                Mode::ViewProfile(mode) => self
726                    .render_view_profile(mode.clone(), window, cx)
727                    .into_any_element(),
728                Mode::ConfigureTools {
729                    profile_id,
730                    tool_picker,
731                    ..
732                } => {
733                    let profile_name = settings
734                        .profiles
735                        .get(profile_id)
736                        .map(|profile| profile.name.clone())
737                        .unwrap_or_else(|| "Unknown".into());
738
739                    v_flex()
740                        .pb_1()
741                        .child(ProfileModalHeader::new(
742                            format!("{profile_name} — Configure Built-in Tools"),
743                            Some(IconName::Cog),
744                        ))
745                        .child(ListSeparator)
746                        .child(tool_picker.clone())
747                        .child(ListSeparator)
748                        .child(go_back_item)
749                        .into_any_element()
750                }
751                Mode::ConfigureMcps {
752                    profile_id,
753                    tool_picker,
754                    ..
755                } => {
756                    let profile_name = settings
757                        .profiles
758                        .get(profile_id)
759                        .map(|profile| profile.name.clone())
760                        .unwrap_or_else(|| "Unknown".into());
761
762                    v_flex()
763                        .pb_1()
764                        .child(ProfileModalHeader::new(
765                            format!("{profile_name} — Configure MCP Tools"),
766                            Some(IconName::ToolHammer),
767                        ))
768                        .child(ListSeparator)
769                        .child(tool_picker.clone())
770                        .child(ListSeparator)
771                        .child(go_back_item)
772                        .into_any_element()
773                }
774            })
775    }
776}