diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index 380a1dd4ef8a46c763c5ff80fff758ad0b976afb..ccdefc2b762749272b2ad0731e8d99c47096be23 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -246,7 +246,7 @@ pub fn init(cx: &mut App) { .and_then(|conversation| { conversation .read(cx) - .active_thread() + .root_thread_view() .map(|r| r.read(cx).thread.clone()) }); @@ -797,7 +797,7 @@ impl AgentPanel { Some( conversation .read(cx) - .root_thread(cx)? + .root_thread_view()? .read(cx) .thread .read(cx) @@ -1287,7 +1287,7 @@ impl AgentPanel { }; if let Some(draft) = &self.draft_thread { let agent_matches = *draft.read(cx).agent_key() == desired_agent; - let has_editor_content = draft.read(cx).active_thread().is_some_and(|tv| { + let has_editor_content = draft.read(cx).root_thread_view().is_some_and(|tv| { !tv.read(cx) .message_editor .read(cx) @@ -1321,7 +1321,7 @@ impl AgentPanel { conversation_view: &Entity, cx: &mut Context, ) { - if let Some(acp_thread) = conversation_view.read(cx).root_acp_thread(cx) { + if let Some(acp_thread) = conversation_view.read(cx).root_thread(cx) { self._draft_editor_observation = Some(cx.subscribe( &acp_thread, |this, _, e: &AcpThreadEvent, cx| { @@ -1333,7 +1333,7 @@ impl AgentPanel { } else { let cv = conversation_view.clone(); self._draft_editor_observation = Some(cx.observe(&cv, |this, cv, cx| { - if cv.read(cx).root_acp_thread(cx).is_some() { + if cv.read(cx).root_thread(cx).is_some() { this.observe_draft_editor(&cv, cx); } })); @@ -1421,7 +1421,7 @@ impl AgentPanel { } _ => None, })?; - let tv = cv.read(cx).active_thread()?; + let tv = cv.read(cx).root_thread_view()?; let text = tv.read(cx).message_editor.read(cx).text(cx); if text.trim().is_empty() { None @@ -1443,7 +1443,7 @@ impl AgentPanel { _ => None, }); let Some(cv) = cv else { return }; - let Some(tv) = cv.read(cx).active_thread() else { + let Some(tv) = cv.read(cx).root_thread_view() else { return; }; let editor = tv.read(cx).message_editor.clone(); @@ -1581,7 +1581,7 @@ impl AgentPanel { return; }; - let Some(active_thread) = conversation_view.read(cx).active_thread().cloned() else { + let Some(active_thread) = conversation_view.read(cx).root_thread_view() else { return; }; @@ -2051,15 +2051,14 @@ impl AgentPanel { pub fn active_thread_view(&self, cx: &App) -> Option> { let server_view = self.active_conversation_view()?; - server_view.read(cx).active_thread().cloned() + server_view.read(cx).root_thread_view() } pub fn active_agent_thread(&self, cx: &App) -> Option> { match &self.base_view { - BaseView::AgentThread { conversation_view } => conversation_view - .read(cx) - .active_thread() - .map(|r| r.read(cx).thread.clone()), + BaseView::AgentThread { conversation_view } => { + conversation_view.read(cx).root_thread(cx) + } _ => None, } } @@ -2076,7 +2075,7 @@ impl AgentPanel { for conversation_view in conversation_views { if *thread_id == conversation_view.read(cx).thread_id { - if let Some(thread_view) = conversation_view.read(cx).root_thread_view(cx) { + if let Some(thread_view) = conversation_view.read(cx).root_thread_view() { thread_view.update(cx, |view, cx| view.cancel_generation(cx)); return true; } @@ -2091,13 +2090,13 @@ impl AgentPanel { let mut views = Vec::new(); if let Some(server_view) = self.active_conversation_view() { - if let Some(thread_view) = server_view.read(cx).root_thread(cx) { + if let Some(thread_view) = server_view.read(cx).root_thread_view() { views.push(thread_view); } } for server_view in self.retained_threads.values() { - if let Some(thread_view) = server_view.read(cx).root_thread(cx) { + if let Some(thread_view) = server_view.read(cx).root_thread_view() { views.push(thread_view); } } @@ -2164,7 +2163,7 @@ impl AgentPanel { .retained_threads .iter() .filter(|(_id, view)| { - let Some(thread_view) = view.read(cx).root_thread(cx) else { + let Some(thread_view) = view.read(cx).root_thread_view() else { return true; }; let thread = thread_view.read(cx).thread.read(cx); @@ -2391,7 +2390,7 @@ impl AgentPanel { window: &mut Window, cx: &mut Context, ) -> Option { - server_view.read(cx).active_thread().cloned().map(|tv| { + server_view.read(cx).root_thread_view().map(|tv| { cx.subscribe_in( &tv, window, @@ -3809,12 +3808,12 @@ impl AgentPanel { VisibleSurface::AgentThread(conversation_view) => { let server_view_ref = conversation_view.read(cx); let is_generating_title = server_view_ref.as_native_thread(cx).is_some() - && server_view_ref.root_thread(cx).map_or(false, |tv| { + && server_view_ref.root_thread_view().map_or(false, |tv| { tv.read(cx).thread.read(cx).has_provisional_title() }); if let Some(title_editor) = server_view_ref - .root_thread(cx) + .root_thread_view() .map(|r| r.read(cx).title_editor.clone()) { if is_generating_title { @@ -6825,7 +6824,7 @@ mod tests { // Verify thread A's (background) work_dirs are also updated. let updated_a_paths = panel.read_with(&cx, |panel, cx| { let bg_view = panel.retained_threads.get(&thread_id_a).unwrap(); - let root_thread = bg_view.read(cx).root_thread(cx).unwrap(); + let root_thread = bg_view.read(cx).root_thread_view().unwrap(); root_thread .read(cx) .thread @@ -6845,7 +6844,7 @@ mod tests { // Verify thread idle C was also updated. let updated_c_paths = panel.read_with(&cx, |panel, cx| { let bg_view = panel.retained_threads.get(&thread_id_c).unwrap(); - let root_thread = bg_view.read(cx).root_thread(cx).unwrap(); + let root_thread = bg_view.read(cx).root_thread_view().unwrap(); root_thread .read(cx) .thread @@ -6899,7 +6898,7 @@ mod tests { let after_remove_a = panel.read_with(&cx, |panel, cx| { let bg_view = panel.retained_threads.get(&thread_id_a).unwrap(); - let root_thread = bg_view.read(cx).root_thread(cx).unwrap(); + let root_thread = bg_view.read(cx).root_thread_view().unwrap(); root_thread .read(cx) .thread diff --git a/crates/agent_ui/src/conversation_view.rs b/crates/agent_ui/src/conversation_view.rs index 6f49361bc6a8cad1d14174256873fd5af8745cb1..bb19274711b5e654cab775c32bd6766b5d84b1f5 100644 --- a/crates/agent_ui/src/conversation_view.rs +++ b/crates/agent_ui/src/conversation_view.rs @@ -460,13 +460,7 @@ impl ConversationView { &'a self, cx: &'a App, ) -> Option<(acp::SessionId, acp::ToolCallId, &'a PermissionOptions)> { - let session_id = self - .active_thread()? - .read(cx) - .thread - .read(cx) - .session_id() - .clone(); + let session_id = self.active_thread()?.read(cx).session_id.clone(); self.as_connected()? .conversation .read(cx) @@ -474,7 +468,7 @@ impl ConversationView { } pub fn root_thread_has_pending_tool_call(&self, cx: &App) -> bool { - let Some(root_thread) = self.root_thread(cx) else { + let Some(root_thread) = self.root_thread_view() else { return false; }; let root_session_id = root_thread.read(cx).thread.read(cx).session_id().clone(); @@ -487,47 +481,18 @@ impl ConversationView { }) } - pub fn root_thread(&self, cx: &App) -> Option> { - match &self.server_state { - ServerState::Connected(connected) => { - let mut current = connected.active_view()?; - while let Some(parent_session_id) = - current.read(cx).thread.read(cx).parent_session_id() - { - if let Some(parent) = connected.threads.get(parent_session_id) { - current = parent; - } else { - break; - } - } - Some(current.clone()) - } - _ => None, - } - } - - pub(crate) fn root_acp_thread(&self, cx: &App) -> Option> { - let connected = self.as_connected()?; - let root_session_id = self.root_session_id.as_ref()?; - connected - .conversation - .read(cx) - .threads - .get(root_session_id) - .cloned() + pub(crate) fn root_thread(&self, cx: &App) -> Option> { + self.root_thread_view() + .map(|view| view.read(cx).thread.clone()) } - pub fn root_thread_view(&self, cx: &App) -> Option> { + pub fn root_thread_view(&self) -> Option> { self.root_session_id .as_ref() - .and_then(|sid| self.thread_view(sid, cx)) + .and_then(|id| self.thread_view(id)) } - pub fn thread_view( - &self, - session_id: &acp::SessionId, - _cx: &App, - ) -> Option> { + pub fn thread_view(&self, session_id: &acp::SessionId) -> Option> { let connected = self.as_connected()?; connected.threads.get(session_id).cloned() } @@ -737,7 +702,7 @@ impl ConversationView { fn reset(&mut self, window: &mut Window, cx: &mut Context) { let (resume_session_id, cwd, title) = self - .active_thread() + .root_thread_view() .map(|thread_view| { let tv = thread_view.read(cx); let thread = tv.thread.read(cx); @@ -764,7 +729,7 @@ impl ConversationView { ); self.set_server_state(state, cx); - if let Some(view) = self.active_thread() { + if let Some(view) = self.root_thread_view() { view.update(cx, |this, cx| { this.message_editor.update(cx, |editor, cx| { editor.set_session_capabilities(this.session_capabilities.clone(), cx); @@ -805,7 +770,7 @@ impl ConversationView { let connection_entry_subscription = cx.subscribe(&connection_entry, |this, _entry, event, cx| match event { AgentConnectionEntryEvent::NewVersionAvailable(version) => { - if let Some(thread) = this.active_thread() { + if let Some(thread) = this.root_thread_view() { thread.update(cx, |thread, cx| { thread.new_server_version_available = Some(version.clone()); cx.notify(); @@ -1259,7 +1224,7 @@ impl ConversationView { } fn handle_load_error(&mut self, err: LoadError, window: &mut Window, cx: &mut Context) { - if let Some(view) = self.active_thread() { + if let Some(view) = self.root_thread_view() { if view .read(cx) .message_editor @@ -1292,7 +1257,7 @@ impl ConversationView { }; if should_retry { - if let Some(active) = self.active_thread() { + if let Some(active) = self.root_thread_view() { active.update(cx, |active, cx| { active.clear_thread_error(cx); }); @@ -1345,14 +1310,6 @@ impl ConversationView { matches!(self.server_state, ServerState::Loading { .. }) } - fn update_turn_tokens(&mut self, cx: &mut Context) { - if let Some(active) = self.active_thread() { - active.update(cx, |active, cx| { - active.update_turn_tokens(cx); - }); - } - } - fn send_queued_message_at_index( &mut self, index: usize, @@ -1360,7 +1317,7 @@ impl ConversationView { window: &mut Window, cx: &mut Context, ) { - if let Some(active) = self.active_thread() { + if let Some(active) = self.root_thread_view() { active.update(cx, |active, cx| { active.send_queued_message_at_index(index, is_send_now, window, cx); }); @@ -1375,7 +1332,7 @@ impl ConversationView { window: &mut Window, cx: &mut Context, ) { - if let Some(active) = self.active_thread() { + if let Some(active) = self.root_thread_view() { active.update(cx, |active, cx| { active.move_queued_message_to_main_editor( index, @@ -1410,7 +1367,7 @@ impl ConversationView { AcpThreadEvent::NewEntry => { let len = thread.read(cx).entries().len(); let index = len - 1; - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { let entry_view_state = active.read(cx).entry_view_state.clone(); let list_state = active.read(cx).list_state.clone(); entry_view_state.update(cx, |view_state, cx| { @@ -1428,7 +1385,7 @@ impl ConversationView { } } AcpThreadEvent::EntryUpdated(index) => { - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { let entry_view_state = active.read(cx).entry_view_state.clone(); let list_state = active.read(cx).list_state.clone(); entry_view_state.update(cx, |view_state, cx| { @@ -1441,7 +1398,7 @@ impl ConversationView { } } AcpThreadEvent::EntriesRemoved(range) => { - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { let entry_view_state = active.read(cx).entry_view_state.clone(); let list_state = active.read(cx).list_state.clone(); entry_view_state.update(cx, |view_state, _cx| view_state.remove(range.clone())); @@ -1459,14 +1416,14 @@ impl ConversationView { } AcpThreadEvent::ToolAuthorizationReceived(_) => {} AcpThreadEvent::Retry(retry) => { - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { active.update(cx, |active, _cx| { active.thread_retry_status = Some(retry.clone()); }); } } AcpThreadEvent::Stopped(stop_reason) => { - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { let is_generating = matches!(thread.read(cx).status(), ThreadStatus::Generating); active.update(cx, |active, cx| { @@ -1501,7 +1458,7 @@ impl ConversationView { cx, ); - let should_send_queued = if let Some(active) = self.active_thread() { + let should_send_queued = if let Some(active) = self.root_thread_view() { active.update(cx, |active, cx| { if active.skip_queue_processing_count > 0 { active.skip_queue_processing_count -= 1; @@ -1530,7 +1487,7 @@ impl ConversationView { } AcpThreadEvent::Refusal => { let error = ThreadError::Refusal; - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { active.update(cx, |active, cx| { active.handle_thread_error(error, cx); active.thread_retry_status.take(); @@ -1544,7 +1501,7 @@ impl ConversationView { } } AcpThreadEvent::Error => { - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { let is_generating = matches!(thread.read(cx).status(), ThreadStatus::Generating); active.update(cx, |active, cx| { @@ -1567,7 +1524,7 @@ impl ConversationView { } } AcpThreadEvent::LoadError(error) => { - if let Some(view) = self.active_thread() { + if let Some(view) = self.root_thread_view() { if view .read(cx) .message_editor @@ -1586,7 +1543,7 @@ impl ConversationView { } AcpThreadEvent::TitleUpdated => { if let Some(title) = thread.read(cx).title() - && let Some(active_thread) = self.thread_view(&session_id, cx) + && let Some(active_thread) = self.thread_view(&session_id) { let title_editor = active_thread.read(cx).title_editor.clone(); title_editor.update(cx, |editor, cx| { @@ -1598,7 +1555,7 @@ impl ConversationView { cx.notify(); } AcpThreadEvent::PromptCapabilitiesUpdated => { - if let Some(active) = self.thread_view(&session_id, cx) { + if let Some(active) = self.thread_view(&session_id) { active.update(cx, |active, _cx| { active .session_capabilities @@ -1608,11 +1565,14 @@ impl ConversationView { } } AcpThreadEvent::TokenUsageUpdated => { - self.update_turn_tokens(cx); - self.emit_token_limit_telemetry_if_needed(thread, cx); + if let Some(active) = self.thread_view(&session_id) { + active.update(cx, |active, cx| { + active.update_turn_tokens(cx); + }); + } } AcpThreadEvent::AvailableCommandsUpdated(available_commands) => { - if let Some(thread_view) = self.thread_view(&session_id, cx) { + if let Some(thread_view) = self.thread_view(&session_id) { let has_commands = !available_commands.is_empty(); let agent_display_name = self @@ -1729,7 +1689,7 @@ impl ConversationView { { pending_auth_method.take(); } - if let Some(active) = this.active_thread() { + if let Some(active) = this.root_thread_view() { active.update(cx, |active, cx| { active.handle_thread_error(err, cx); }) @@ -1777,7 +1737,7 @@ impl ConversationView { { pending_auth_method.take(); } - if let Some(active) = this.active_thread() { + if let Some(active) = this.root_thread_view() { active.update(cx, |active, cx| active.handle_thread_error(err, cx)); } } else { @@ -1983,7 +1943,7 @@ impl ConversationView { } pub fn has_user_submitted_prompt(&self, cx: &App) -> bool { - self.active_thread().is_some_and(|active| { + self.root_thread_view().is_some_and(|active| { active .read(cx) .thread @@ -2109,59 +2069,6 @@ impl ConversationView { .into_any_element() } - fn emit_token_limit_telemetry_if_needed( - &mut self, - thread: &Entity, - cx: &mut Context, - ) { - let Some(active_thread) = self.active_thread() else { - return; - }; - - let (ratio, agent_telemetry_id, session_id) = { - let thread_data = thread.read(cx); - let Some(token_usage) = thread_data.token_usage() else { - return; - }; - ( - token_usage.ratio(), - thread_data.connection().telemetry_id(), - thread_data.session_id().clone(), - ) - }; - - let kind = match ratio { - acp_thread::TokenUsageRatio::Normal => { - active_thread.update(cx, |active, _cx| { - active.last_token_limit_telemetry = None; - }); - return; - } - acp_thread::TokenUsageRatio::Warning => "warning", - acp_thread::TokenUsageRatio::Exceeded => "exceeded", - }; - - let should_skip = active_thread - .read(cx) - .last_token_limit_telemetry - .as_ref() - .is_some_and(|last| *last >= ratio); - if should_skip { - return; - } - - active_thread.update(cx, |active, _cx| { - active.last_token_limit_telemetry = Some(ratio); - }); - - telemetry::event!( - "Agent Token Limit Warning", - agent = agent_telemetry_id, - session_id = session_id, - kind = kind, - ); - } - fn emit_load_error_telemetry(&self, error: &LoadError) { let error_kind = match error { LoadError::Unsupported { .. } => "unsupported", @@ -2268,18 +2175,20 @@ impl ConversationView { &self, cx: &App, ) -> Option> { - let acp_thread = self.active_thread()?.read(cx).thread.read(cx); - acp_thread.connection().clone().downcast() + self.root_thread(cx)? + .read(cx) + .connection() + .clone() + .downcast() } pub fn as_native_thread(&self, cx: &App) -> Option> { - let acp_thread = self.active_thread()?.read(cx).thread.read(cx); self.as_native_connection(cx)? - .thread(acp_thread.session_id(), cx) + .thread(self.root_session_id.as_ref()?, cx) } fn queued_messages_len(&self, cx: &App) -> usize { - self.active_thread() + self.root_thread_view() .map(|thread| thread.read(cx).local_queued_messages.len()) .unwrap_or_default() } @@ -2291,7 +2200,7 @@ impl ConversationView { tracked_buffers: Vec>, cx: &mut Context, ) -> bool { - match self.active_thread() { + match self.root_thread_view() { Some(thread) => thread.update(cx, |thread, _cx| { if index < thread.local_queued_messages.len() { thread.local_queued_messages[index] = QueuedMessage { @@ -2308,7 +2217,7 @@ impl ConversationView { } fn queued_message_contents(&self, cx: &App) -> Vec> { - match self.active_thread() { + match self.root_thread_view() { None => Vec::new(), Some(thread) => thread .read(cx) @@ -2320,7 +2229,7 @@ impl ConversationView { } fn save_queued_message_at_index(&mut self, index: usize, cx: &mut Context) { - let editor = match self.active_thread() { + let editor = match self.root_thread_view() { Some(thread) => thread.read(cx).queued_message_editors.get(index).cloned(), None => None, }; @@ -2451,7 +2360,7 @@ impl ConversationView { }); } - if let Some(active) = self.active_thread() { + if let Some(active) = self.root_thread_view() { active.update(cx, |active, _cx| { active.last_synced_queue_length = needed_count; }); @@ -2545,7 +2454,7 @@ impl ConversationView { return; } - let Some(root_thread) = self.root_thread(cx) else { + let Some(root_thread) = self.root_thread_view() else { return; }; let root_thread = root_thread.read(cx).thread.read(cx); @@ -2764,7 +2673,7 @@ impl ConversationView { // For ACP agents, use the agent name (e.g., "Claude Agent", "Gemini CLI") // This provides better clarity about what refused the request if self.as_native_connection(cx).is_some() { - self.active_thread() + self.root_thread_view() .and_then(|active| active.read(cx).model_selector.clone()) .and_then(|selector| selector.read(cx).active_model(cx)) .map(|model| model.name.clone()) @@ -2783,7 +2692,7 @@ impl ConversationView { pub(crate) fn reauthenticate(&mut self, window: &mut Window, cx: &mut Context) { let agent_id = self.agent.agent_id(); - if let Some(active) = self.active_thread() { + if let Some(active) = self.root_thread_view() { active.update(cx, |active, cx| active.clear_thread_error(cx)); } let this = cx.weak_entity(); @@ -3927,7 +3836,7 @@ pub(crate) mod tests { let root_session_id = conversation_view .read_with(cx, |view, cx| { - view.root_thread(cx) + view.root_thread_view() .map(|thread| thread.read(cx).thread.read(cx).session_id().clone()) }) .expect("Conversation view should have a root thread"); diff --git a/crates/agent_ui/src/conversation_view/thread_view.rs b/crates/agent_ui/src/conversation_view/thread_view.rs index 95d3f3599b41a5028a6bed6fa51c179eb51e767f..86f920c157a7ea0a5895f03342df73e0403b473f 100644 --- a/crates/agent_ui/src/conversation_view/thread_view.rs +++ b/crates/agent_ui/src/conversation_view/thread_view.rs @@ -885,10 +885,51 @@ impl ThreadView { if let Some(usage) = self.thread.read(cx).token_usage() { if let Some(tokens) = &mut self.turn_fields.turn_tokens { *tokens += usage.output_tokens; + self.emit_token_limit_telemetry_if_needed(cx); } } } + fn emit_token_limit_telemetry_if_needed(&mut self, cx: &App) { + let (ratio, agent_telemetry_id, session_id) = { + let thread_data = self.thread.read(cx); + let Some(token_usage) = thread_data.token_usage() else { + return; + }; + ( + token_usage.ratio(), + thread_data.connection().telemetry_id(), + thread_data.session_id().clone(), + ) + }; + + let kind = match ratio { + acp_thread::TokenUsageRatio::Normal => { + self.last_token_limit_telemetry = None; + return; + } + acp_thread::TokenUsageRatio::Warning => "warning", + acp_thread::TokenUsageRatio::Exceeded => "exceeded", + }; + + let should_skip = self + .last_token_limit_telemetry + .as_ref() + .is_some_and(|last| *last >= ratio); + if should_skip { + return; + } + + self.last_token_limit_telemetry = Some(ratio); + + telemetry::event!( + "Agent Token Limit Warning", + agent = agent_telemetry_id, + session_id = session_id, + kind = kind, + ); + } + // sending fn clear_external_source_prompt_warning(&mut self, cx: &mut Context) { @@ -3096,7 +3137,7 @@ impl ThreadView { self.server_view .upgrade() - .and_then(|sv| sv.read(cx).thread_view(parent_session_id, cx)) + .and_then(|sv| sv.read(cx).thread_view(parent_session_id)) .is_some_and(|parent_view| { parent_view .read(cx) diff --git a/crates/agent_ui/src/thread_metadata_store.rs b/crates/agent_ui/src/thread_metadata_store.rs index 8501601012bcfeac76ea404c6120401339805348..768951c8f4b8dae4904963d45d0f49d22b230167 100644 --- a/crates/agent_ui/src/thread_metadata_store.rs +++ b/crates/agent_ui/src/thread_metadata_store.rs @@ -1133,7 +1133,7 @@ impl ThreadMetadataStore { ) { let view = conversation_view.read(cx); let thread_id = view.thread_id; - let Some(thread) = view.root_acp_thread(cx) else { + let Some(thread) = view.root_thread(cx) else { return; }; diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index a49997f2d3ff9bdc9b41aaa536d456f9d38f892c..f583cef98d6521252b79191a90f6c98db654d06b 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -4726,7 +4726,7 @@ fn all_thread_infos_for_workspace( .read(cx) .root_thread_has_pending_tool_call(cx); let conversation_thread_id = conversation_view.read(cx).parent_id(); - let thread_view = conversation_view.read(cx).root_thread(cx)?; + let thread_view = conversation_view.read(cx).root_thread_view()?; let thread_view_ref = thread_view.read(cx); let thread = thread_view_ref.thread.read(cx); @@ -4979,7 +4979,7 @@ fn dump_single_workspace(workspace: &Workspace, output: &mut String, cx: &gpui:: ) .ok(); for (session_id, conversation_view) in background_threads { - if let Some(thread_view) = conversation_view.read(cx).root_thread(cx) { + if let Some(thread_view) = conversation_view.read(cx).root_thread_view() { let thread = thread_view.read(cx).thread.read(cx); let title = thread.title().unwrap_or_else(|| "(untitled)".into()); let status = match thread.status() { diff --git a/crates/sidebar/src/sidebar_tests.rs b/crates/sidebar/src/sidebar_tests.rs index 8aaf19f44d45688dbee7cdf258ef98a946a92b17..5cb836ebedb5ff2de3d177116555a1b53b586981 100644 --- a/crates/sidebar/src/sidebar_tests.rs +++ b/crates/sidebar/src/sidebar_tests.rs @@ -1385,7 +1385,7 @@ async fn test_subagent_permission_request_marks_parent_sidebar_thread_waiting( let subagent_thread = panel.read_with(cx, |panel, cx| { panel .active_conversation_view() - .and_then(|conversation| conversation.read(cx).thread_view(&subagent_session_id, cx)) + .and_then(|conversation| conversation.read(cx).thread_view(&subagent_session_id)) .map(|thread_view| thread_view.read(cx).thread.clone()) .expect("Expected subagent thread to be loaded into the conversation") });