diff --git a/app/src/ai/blocklist/controller.rs b/app/src/ai/blocklist/controller.rs index 758660ca60..bb3e0e65e5 100644 --- a/app/src/ai/blocklist/controller.rs +++ b/app/src/ai/blocklist/controller.rs @@ -2020,7 +2020,9 @@ impl BlocklistAIController { forked_from_conversation_token: conversation .forked_from_server_conversation_token() .cloned(), - ambient_agent_task_id: self.ambient_agent_task_id, + // Do not tie passive suggestion requests to the cloud agent task, since they are + // separate, read-only requests. + ambient_agent_task_id: None, existing_suggestions: None, }; (conversation_id, task_id, conversation_data) @@ -2036,7 +2038,9 @@ impl BlocklistAIController { tasks: vec![], server_conversation_token: None, forked_from_conversation_token: None, - ambient_agent_task_id: self.ambient_agent_task_id, + // Do not tie passive suggestion requests to the cloud agent task, since they are + // separate, read-only requests. + ambient_agent_task_id: None, existing_suggestions: None, }; (conversation_id, task_id, conversation_data) @@ -2148,6 +2152,11 @@ impl BlocklistAIController { }); } + #[cfg(test)] + pub fn get_ambient_agent_task_id(&self) -> Option { + self.ambient_agent_task_id + } + /// Set the per-session directory for downloading file attachments. pub fn set_attachments_download_dir(&mut self, dir: std::path::PathBuf) { self.attachments_download_dir = Some(dir); @@ -3183,3 +3192,7 @@ fn get_running_command(terminal_model: &TerminalModel) -> Option is_alt_screen_active, }) } + +#[cfg(test)] +#[path = "controller_tests.rs"] +mod tests; diff --git a/app/src/ai/blocklist/controller_tests.rs b/app/src/ai/blocklist/controller_tests.rs new file mode 100644 index 0000000000..f69a8a48ff --- /dev/null +++ b/app/src/ai/blocklist/controller_tests.rs @@ -0,0 +1,58 @@ +use crate::ai::agent::PassiveSuggestionTrigger; +use crate::ai::ambient_agents::AmbientAgentTaskId; +use crate::ai::blocklist::BlocklistAIHistoryModel; +use crate::test_util::terminal::{add_window_with_terminal, initialize_app_for_terminal_view}; +use uuid::Uuid; +use warpui::{App, SingletonEntity}; + +fn new_ambient_agent_task_id() -> AmbientAgentTaskId { + Uuid::new_v4().to_string().parse().unwrap() +} + +#[test] +fn passive_suggestions_request_params_omit_ambient_agent_task_id() { + App::test((), |mut app| async move { + initialize_app_for_terminal_view(&mut app); + let terminal = add_window_with_terminal(&mut app, None); + + terminal.update(&mut app, |terminal, ctx| { + let task_id = new_ambient_agent_task_id(); + let conversation_id = + BlocklistAIHistoryModel::handle(ctx).update(ctx, |history_model, ctx| { + history_model.start_new_conversation(terminal.id(), false, false, false, ctx) + }); + + terminal.ai_controller().update(ctx, |controller, ctx| { + controller.set_ambient_agent_task_id(Some(task_id), ctx); + + assert_eq!(controller.get_ambient_agent_task_id(), Some(task_id)); + assert_eq!( + controller + .build_passive_suggestions_request_params( + Some(conversation_id), + PassiveSuggestionTrigger::FilesChanged, + vec![], + ctx, + ) + .expect("existing conversation should build passive suggestion params") + .1 + .ambient_agent_task_id, + None + ); + assert_eq!( + controller + .build_passive_suggestions_request_params( + None, + PassiveSuggestionTrigger::FilesChanged, + vec![], + ctx, + ) + .expect("new conversation should build passive suggestion params") + .1 + .ambient_agent_task_id, + None + ); + }); + }); + }); +} diff --git a/app/src/pane_group/mod_tests.rs b/app/src/pane_group/mod_tests.rs index 1c496319b2..bf6b3f587d 100644 --- a/app/src/pane_group/mod_tests.rs +++ b/app/src/pane_group/mod_tests.rs @@ -9,7 +9,6 @@ use crate::{ conversation::{ AIAgentHarness, AIConversation, AIConversationId, ServerAIConversationMetadata, }, - PassiveSuggestionTrigger, }, agent_conversations_model::AgentConversationsModel, ambient_agents::github_auth_notifier::GitHubAuthNotifier, @@ -461,7 +460,6 @@ fn create_already_fullscreen_parent_pane_data( fn request_ambient_agent_task_id_for_hidden_child( panes: &PaneGroup, - child_conversation_id: AIConversationId, child_pane_id: PaneId, ctx: &mut ViewContext, ) -> Option { @@ -470,18 +468,7 @@ fn request_ambient_agent_task_id_for_hidden_child( .expect("child pane should have a terminal view"); let ai_controller = terminal_view.as_ref(ctx).ai_controller().clone(); - ai_controller.update(ctx, |controller, ctx| { - controller - .build_passive_suggestions_request_params( - Some(child_conversation_id), - PassiveSuggestionTrigger::FilesChanged, - vec![], - ctx, - ) - .expect("child pane should build passive suggestion request params") - .1 - .ambient_agent_task_id - }) + ai_controller.update(ctx, |controller, _| controller.get_ambient_agent_task_id()) } fn ambient_child_session_state( @@ -726,12 +713,7 @@ fn test_hidden_child_creation_applies_ambient_task_id_to_controller() { .expect("fresh hidden child pane should be tracked"); assert_eq!( - request_ambient_agent_task_id_for_hidden_child( - panes, - child.conversation_id, - child_pane_id, - ctx, - ), + request_ambient_agent_task_id_for_hidden_child(panes, child_pane_id, ctx,), Some(task_id) ); }); @@ -765,12 +747,7 @@ fn test_restored_hidden_child_pane_reapplies_ambient_task_id_to_controller() { .expect("restored hidden child pane should be tracked"); assert_eq!( - request_ambient_agent_task_id_for_hidden_child( - panes, - child_conversation_id, - child_pane_id, - ctx, - ), + request_ambient_agent_task_id_for_hidden_child(panes, child_pane_id, ctx,), Some(task_id) ); }); diff --git a/app/src/server/server_api.rs b/app/src/server/server_api.rs index 0dc2ae168f..dc66b2995a 100644 --- a/app/src/server/server_api.rs +++ b/app/src/server/server_api.rs @@ -1251,11 +1251,16 @@ impl ServerApi { } ); - let ambient_workload_token = self - .get_or_create_ambient_workload_token() - .await - .map_err(Into::into) - .map_err(Arc::new)?; + let ambient_workload_token = if is_passive { + // Do not include cloud agent workload metadata in passive suggestion requests - they + // read from the main conversation, but cannot modify it. + None + } else { + self.get_or_create_ambient_workload_token() + .await + .map_err(Into::into) + .map_err(Arc::new)? + }; let mut request_builder = self .client