@@ -155,6 +155,7 @@ impl AcpThreadView {
pub fn new(
agent: Rc<dyn AgentServer>,
resume_thread: Option<DbThreadMetadata>,
+ summarize_thread: Option<DbThreadMetadata>,
workspace: WeakEntity<Workspace>,
project: Entity<Project>,
history_store: Entity<HistoryStore>,
@@ -164,7 +165,7 @@ impl AcpThreadView {
) -> Self {
let prevent_slash_commands = agent.clone().downcast::<ClaudeCode>().is_some();
let message_editor = cx.new(|cx| {
- MessageEditor::new(
+ let mut editor = MessageEditor::new(
workspace.clone(),
project.clone(),
history_store.clone(),
@@ -177,7 +178,11 @@ impl AcpThreadView {
},
window,
cx,
- )
+ );
+ if let Some(entry) = summarize_thread {
+ editor.insert_thread_summary(entry, window, cx);
+ }
+ editor
});
let list_state = ListState::new(0, gpui::ListAlignment::Bottom, px(2048.0));
@@ -3636,8 +3641,18 @@ impl AcpThreadView {
.child(
Button::new("start-new-thread", "Start New Thread")
.label_size(LabelSize::Small)
- .on_click(cx.listener(|_this, _, _window, _cx| {
- // todo: Once thread summarization is implemented, start a new thread from a summary.
+ .on_click(cx.listener(|this, _, window, cx| {
+ let Some(thread) = this.thread() else {
+ return;
+ };
+ let session_id = thread.read(cx).session_id().clone();
+ window.dispatch_action(
+ crate::NewNativeAgentThreadFromSummary {
+ from_session_id: session_id,
+ }
+ .boxed_clone(),
+ cx,
+ );
})),
)
.when(burn_mode_available, |this| {
@@ -4320,6 +4335,7 @@ pub(crate) mod tests {
AcpThreadView::new(
Rc::new(agent),
None,
+ None,
workspace.downgrade(),
project,
history_store,
@@ -4526,6 +4542,7 @@ pub(crate) mod tests {
AcpThreadView::new(
Rc::new(StubAgentServer::new(connection.as_ref().clone())),
None,
+ None,
workspace.downgrade(),
project.clone(),
history_store.clone(),
@@ -30,7 +30,7 @@ use crate::{
thread_history::{HistoryEntryElement, ThreadHistory},
ui::{AgentOnboardingModal, EndTrialUpsell},
};
-use crate::{ExternalAgent, NewExternalAgentThread};
+use crate::{ExternalAgent, NewExternalAgentThread, NewNativeAgentThreadFromSummary};
use agent::{
Thread, ThreadError, ThreadEvent, ThreadId, ThreadSummary, TokenUsageRatio,
context_store::ContextStore,
@@ -98,6 +98,16 @@ pub fn init(cx: &mut App) {
workspace.focus_panel::<AgentPanel>(window, cx);
}
})
+ .register_action(
+ |workspace, action: &NewNativeAgentThreadFromSummary, window, cx| {
+ if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
+ panel.update(cx, |panel, cx| {
+ panel.new_native_agent_thread_from_summary(action, window, cx)
+ });
+ workspace.focus_panel::<AgentPanel>(window, cx);
+ }
+ },
+ )
.register_action(|workspace, _: &OpenHistory, window, cx| {
if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
workspace.focus_panel::<AgentPanel>(window, cx);
@@ -120,7 +130,7 @@ pub fn init(cx: &mut App) {
if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
workspace.focus_panel::<AgentPanel>(window, cx);
panel.update(cx, |panel, cx| {
- panel.external_thread(action.agent, None, window, cx)
+ panel.external_thread(action.agent, None, None, window, cx)
});
}
})
@@ -670,6 +680,7 @@ impl AgentPanel {
this.external_thread(
Some(crate::ExternalAgent::NativeAgent),
Some(thread.clone()),
+ None,
window,
cx,
);
@@ -974,6 +985,29 @@ impl AgentPanel {
AgentDiff::set_active_thread(&self.workspace, thread.clone(), window, cx);
}
+ fn new_native_agent_thread_from_summary(
+ &mut self,
+ action: &NewNativeAgentThreadFromSummary,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ let Some(thread) = self
+ .acp_history_store
+ .read(cx)
+ .thread_from_session_id(&action.from_session_id)
+ else {
+ return;
+ };
+
+ self.external_thread(
+ Some(ExternalAgent::NativeAgent),
+ None,
+ Some(thread.clone()),
+ window,
+ cx,
+ );
+ }
+
fn new_prompt_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let context = self
.context_store
@@ -1015,6 +1049,7 @@ impl AgentPanel {
&mut self,
agent_choice: Option<crate::ExternalAgent>,
resume_thread: Option<DbThreadMetadata>,
+ summarize_thread: Option<DbThreadMetadata>,
window: &mut Window,
cx: &mut Context<Self>,
) {
@@ -1083,6 +1118,7 @@ impl AgentPanel {
crate::acp::AcpThreadView::new(
server,
resume_thread,
+ summarize_thread,
workspace.clone(),
project,
this.acp_history_store.clone(),
@@ -1754,6 +1790,7 @@ impl AgentPanel {
agent2::HistoryEntry::AcpThread(entry) => this.external_thread(
Some(ExternalAgent::NativeAgent),
Some(entry.clone()),
+ None,
window,
cx,
),
@@ -1823,15 +1860,23 @@ impl AgentPanel {
AgentType::TextThread => {
window.dispatch_action(NewTextThread.boxed_clone(), cx);
}
- AgentType::NativeAgent => {
- self.external_thread(Some(crate::ExternalAgent::NativeAgent), None, window, cx)
- }
+ AgentType::NativeAgent => self.external_thread(
+ Some(crate::ExternalAgent::NativeAgent),
+ None,
+ None,
+ window,
+ cx,
+ ),
AgentType::Gemini => {
- self.external_thread(Some(crate::ExternalAgent::Gemini), None, window, cx)
- }
- AgentType::ClaudeCode => {
- self.external_thread(Some(crate::ExternalAgent::ClaudeCode), None, window, cx)
+ self.external_thread(Some(crate::ExternalAgent::Gemini), None, None, window, cx)
}
+ AgentType::ClaudeCode => self.external_thread(
+ Some(crate::ExternalAgent::ClaudeCode),
+ None,
+ None,
+ window,
+ cx,
+ ),
}
}
@@ -1841,7 +1886,13 @@ impl AgentPanel {
window: &mut Window,
cx: &mut Context<Self>,
) {
- self.external_thread(Some(ExternalAgent::NativeAgent), Some(thread), window, cx);
+ self.external_thread(
+ Some(ExternalAgent::NativeAgent),
+ Some(thread),
+ None,
+ window,
+ cx,
+ );
}
}
@@ -2358,8 +2409,10 @@ impl AgentPanel {
let focus_handle = self.focus_handle(cx);
let active_thread = match &self.active_view {
- ActiveView::Thread { thread, .. } => Some(thread.read(cx).thread().clone()),
- ActiveView::ExternalAgentThread { .. }
+ ActiveView::ExternalAgentThread { thread_view } => {
+ thread_view.read(cx).as_native_thread(cx)
+ }
+ ActiveView::Thread { .. }
| ActiveView::TextThread { .. }
| ActiveView::History
| ActiveView::Configuration => None,
@@ -2396,15 +2449,15 @@ impl AgentPanel {
let thread = active_thread.read(cx);
if !thread.is_empty() {
- let thread_id = thread.id().clone();
+ let session_id = thread.id().clone();
this.item(
ContextMenuEntry::new("New From Summary")
.icon(IconName::ThreadFromSummary)
.icon_color(Color::Muted)
.handler(move |window, cx| {
window.dispatch_action(
- Box::new(NewThread {
- from_thread_id: Some(thread_id.clone()),
+ Box::new(NewNativeAgentThreadFromSummary {
+ from_session_id: session_id.clone(),
}),
cx,
);