diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index ec92a1452ac0dc0c775eb0c66997054e2b017b54..698b033cd0dd48240019867352ac921f3c0a1e6f 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -890,6 +890,7 @@ pub struct AgentPanel { selected_agent_type: AgentType, start_thread_in: StartThreadIn, worktree_creation_status: Option, + pending_config_overrides: Vec<(acp::SessionConfigId, acp::SessionConfigValueId)>, _thread_view_subscription: Option, _active_thread_focus_subscription: Option, _worktree_creation_task: Option>, @@ -1226,6 +1227,7 @@ impl AgentPanel { selected_agent_type: AgentType::default(), start_thread_in: StartThreadIn::default(), worktree_creation_status: None, + pending_config_overrides: Vec::new(), _thread_view_subscription: None, _active_thread_focus_subscription: None, _worktree_creation_task: None, @@ -2215,6 +2217,7 @@ impl AgentPanel { cx.observe_in(server_view, window, |this, server_view, window, cx| { this._thread_view_subscription = Self::subscribe_to_active_thread_view(&server_view, window, cx); + this.apply_pending_config_overrides(cx); cx.emit(AgentPanelEvent::ActiveViewChanged); this.serialize(cx); cx.notify(); @@ -2420,6 +2423,58 @@ impl AgentPanel { } } + /// Captures the currently selected config option values (e.g., model, + /// permissions mode) from the active thread's ACP session. + fn capture_config_overrides( + &self, + cx: &App, + ) -> Vec<(acp::SessionConfigId, acp::SessionConfigValueId)> { + let Some(thread_view) = self.as_active_thread_view(cx) else { + return Vec::new(); + }; + let thread = thread_view.read(cx).thread.read(cx); + let connection = thread.connection(); + let session_id = thread.session_id(); + let Some(config_provider) = connection.session_config_options(session_id, cx) else { + return Vec::new(); + }; + config_provider + .config_options() + .into_iter() + .filter_map(|opt| match &opt.kind { + acp::SessionConfigKind::Select(select) => { + Some((opt.id.clone(), select.current_value.clone())) + } + _ => None, + }) + .collect() + } + + /// Applies any pending config option overrides to the active thread's ACP + /// session. Called once after a new worktree workspace's thread becomes + /// ready, then the pending overrides are drained so they are applied only + /// once. + fn apply_pending_config_overrides(&mut self, cx: &mut Context) { + if self.pending_config_overrides.is_empty() { + return; + } + let Some(thread_view) = self.as_active_thread_view(cx) else { + return; + }; + let thread = thread_view.read(cx).thread.read(cx); + let connection = thread.connection(); + let session_id = thread.session_id(); + let Some(config_provider) = connection.session_config_options(session_id, cx) else { + return; + }; + let overrides = std::mem::take(&mut self.pending_config_overrides); + for (config_id, value) in overrides { + config_provider + .set_config_option(config_id, value, cx) + .detach(); + } + } + fn sync_agent_servers_from_extensions(&mut self, cx: &mut Context) { if let Some(extension_store) = ExtensionStore::try_global(cx) { let (manifests, extensions_dir) = { @@ -2889,6 +2944,7 @@ impl AgentPanel { .downcast::(); let selected_agent = self.selected_agent(); + let config_overrides = self.capture_config_overrides(cx); let task = cx.spawn_in(window, async move |this, cx| { // Await the branch listings we kicked off earlier. @@ -2990,6 +3046,7 @@ impl AgentPanel { has_non_git, content, selected_agent, + config_overrides, cx, ) .await @@ -3024,6 +3081,7 @@ impl AgentPanel { has_non_git: bool, content: Vec, selected_agent: Option, + config_overrides: Vec<(acp::SessionConfigId, acp::SessionConfigValueId)>, cx: &mut AsyncWindowContext, ) -> Result<()> { let init: Option< @@ -3108,6 +3166,7 @@ impl AgentPanel { workspace.focus_panel::(window, cx); if let Some(panel) = workspace.panel::(cx) { panel.update(cx, |panel, cx| { + panel.pending_config_overrides = config_overrides; panel.external_thread( selected_agent, None,