diff --git a/crates/acp/src/acp.rs b/crates/acp/src/acp.rs index f6b58fea3a97348b2e47fe0efc516e62a81e5c7a..64b23b2541ec5863935ee1c0349976f033eb903c 100644 --- a/crates/acp/src/acp.rs +++ b/crates/acp/src/acp.rs @@ -108,6 +108,13 @@ pub struct AcpThread { project: Entity, } +enum AcpThreadEvent { + NewEntry, + LastEntryUpdated, +} + +impl EventEmitter for AcpThread {} + impl AcpThread { pub fn new( server: Arc, @@ -146,33 +153,34 @@ impl AcpThread { id: self.next_entry_id.post_inc(), content: entry, }); - cx.notify(); + cx.emit(AcpThreadEvent::NewEntry) } pub fn push_assistant_chunk(&mut self, chunk: MessageChunk, cx: &mut Context) { - if let Some(last_entry) = self.entries.last_mut() { - if let AgentThreadEntryContent::Message(Message { + if let Some(last_entry) = self.entries.last_mut() + && let AgentThreadEntryContent::Message(Message { ref mut chunks, role: Role::Assistant, }) = last_entry.content - { - if let ( - Some(MessageChunk::Text { chunk: old_chunk }), - MessageChunk::Text { chunk: new_chunk }, - ) = (chunks.last_mut(), &chunk) - { - old_chunk.push_str(&new_chunk); - return cx.notify(); - } + { + cx.emit(AcpThreadEvent::LastEntryUpdated); + if let ( + Some(MessageChunk::Text { chunk: old_chunk }), + MessageChunk::Text { chunk: new_chunk }, + ) = (chunks.last_mut(), &chunk) + { + old_chunk.push_str(&new_chunk); + } else { chunks.push(chunk); return cx.notify(); } + + return; } - self.entries.push(ThreadEntry { - id: self.next_entry_id.post_inc(), - content: AgentThreadEntryContent::Message(Message { + self.push_entry( + AgentThreadEntryContent::Message(Message { role: Role::Assistant, chunks: vec![chunk], }), diff --git a/crates/acp/src/thread_view.rs b/crates/acp/src/thread_view.rs index 6686c63fe648ba55cc2061eca96bedc1ac440ef9..59af84f39b6aace88000f52c1eff1cbddf81b9fe 100644 --- a/crates/acp/src/thread_view.rs +++ b/crates/acp/src/thread_view.rs @@ -10,7 +10,9 @@ use ui::Tooltip; use ui::prelude::*; use zed_actions::agent::Chat; -use crate::{AcpThread, AgentThreadEntryContent, Message, MessageChunk, Role, ThreadEntry}; +use crate::{ + AcpThread, AcpThreadEvent, AgentThreadEntryContent, Message, MessageChunk, Role, ThreadEntry, +}; pub struct AcpThreadView { thread: Entity, @@ -42,11 +44,16 @@ impl AcpThreadView { editor }); - let subscription = cx.observe(&thread, |this, thread, cx| { + let subscription = cx.subscribe(&thread, |this, _, event, cx| { let count = this.list_state.item_count(); - // TODO: Incremental updates - this.list_state - .splice(0..count, thread.read(cx).entries.len()); + match event { + AcpThreadEvent::NewEntry => { + this.list_state.splice(count..count, 1); + } + AcpThreadEvent::LastEntryUpdated => { + this.list_state.splice(count - 1..count, 1); + } + } cx.notify(); });