Tidy more

This commit is contained in:
Conrad Irwin 2025-08-15 22:59:46 -06:00
parent 1b793331b3
commit eebe425c1d
5 changed files with 73 additions and 35 deletions

View file

@ -6,7 +6,7 @@ use anyhow::{Result, anyhow};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use collections::{HashMap, IndexMap}; use collections::{HashMap, IndexMap};
use futures::{FutureExt, future::Shared}; use futures::{FutureExt, future::Shared};
use gpui::{BackgroundExecutor, Global, ReadGlobal, Task}; use gpui::{BackgroundExecutor, Global, Task};
use indoc::indoc; use indoc::indoc;
use parking_lot::Mutex; use parking_lot::Mutex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -15,7 +15,7 @@ use sqlez::{
connection::Connection, connection::Connection,
statement::Statement, statement::Statement,
}; };
use std::{path::PathBuf, sync::Arc}; use std::sync::Arc;
use ui::{App, SharedString}; use ui::{App, SharedString};
pub type DbMessage = crate::Message; pub type DbMessage = crate::Message;
@ -221,6 +221,10 @@ pub(crate) struct ThreadsDatabase {
connection: Arc<Mutex<Connection>>, connection: Arc<Mutex<Connection>>,
} }
struct GlobalThreadsDatabase(Shared<Task<Result<Arc<ThreadsDatabase>, Arc<anyhow::Error>>>>);
impl Global for GlobalThreadsDatabase {}
impl ThreadsDatabase { impl ThreadsDatabase {
fn connection(&self) -> Arc<Mutex<Connection>> { fn connection(&self) -> Arc<Mutex<Connection>> {
self.connection.clone() self.connection.clone()
@ -231,8 +235,11 @@ impl ThreadsDatabase {
impl ThreadsDatabase { impl ThreadsDatabase {
pub fn connect(cx: &mut App) -> Shared<Task<Result<Arc<ThreadsDatabase>, Arc<anyhow::Error>>>> { pub fn connect(cx: &mut App) -> Shared<Task<Result<Arc<ThreadsDatabase>, Arc<anyhow::Error>>>> {
if cx.has_global::<GlobalThreadsDatabase>() {
return cx.global::<GlobalThreadsDatabase>().0.clone();
}
let executor = cx.background_executor().clone(); let executor = cx.background_executor().clone();
executor let task = executor
.spawn({ .spawn({
let executor = executor.clone(); let executor = executor.clone();
async move { async move {
@ -242,7 +249,10 @@ impl ThreadsDatabase {
} }
} }
}) })
.shared() .shared();
cx.set_global(GlobalThreadsDatabase(task.clone()));
task
} }
pub fn new(executor: BackgroundExecutor) -> Result<Self> { pub fn new(executor: BackgroundExecutor) -> Result<Self> {

View file

@ -8,5 +8,5 @@ mod thread_view;
pub use model_selector::AcpModelSelector; pub use model_selector::AcpModelSelector;
pub use model_selector_popover::AcpModelSelectorPopover; pub use model_selector_popover::AcpModelSelectorPopover;
pub use thread_history::AcpThreadHistory; pub use thread_history::{AcpThreadHistory, ThreadHistoryEvent};
pub use thread_view::AcpThreadView; pub use thread_view::AcpThreadView;

View file

@ -8,7 +8,7 @@ use chrono::{Datelike as _, Local, NaiveDate, TimeDelta};
use editor::{Editor, EditorEvent}; use editor::{Editor, EditorEvent};
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
App, Empty, Entity, FocusHandle, Focusable, ScrollStrategy, Stateful, Task, App, Empty, Entity, EventEmitter, FocusHandle, Focusable, ScrollStrategy, Stateful, Task,
UniformListScrollHandle, WeakEntity, Window, uniform_list, UniformListScrollHandle, WeakEntity, Window, uniform_list,
}; };
use project::Project; use project::Project;
@ -61,9 +61,14 @@ enum ListItemType {
}, },
} }
pub enum ThreadHistoryEvent {
Open(HistoryEntry),
}
impl EventEmitter<ThreadHistoryEvent> for AcpThreadHistory {}
impl AcpThreadHistory { impl AcpThreadHistory {
pub(crate) fn new( pub(crate) fn new(
agent_panel: WeakEntity<AgentPanel>,
project: &Entity<Project>, project: &Entity<Project>,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
@ -117,7 +122,6 @@ impl AcpThreadHistory {
let scrollbar_state = ScrollbarState::new(scroll_handle.clone()); let scrollbar_state = ScrollbarState::new(scroll_handle.clone());
let mut this = Self { let mut this = Self {
agent_panel,
history_store, history_store,
scroll_handle, scroll_handle,
selected_index: 0, selected_index: 0,
@ -429,28 +433,29 @@ impl AcpThreadHistory {
) )
} }
fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) { fn confirm(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context<Self>) {
self.confirm_entry(self.selected_index, window, cx); self.confirm_entry(self.selected_index, cx);
} }
fn confirm_entry(&mut self, ix: usize, window: &mut Window, cx: &mut Context<Self>) { fn confirm_entry(&mut self, ix: usize, cx: &mut Context<Self>) {
let Some(entry) = self.get_match(ix) else { let Some(entry) = self.get_match(ix) else {
return; return;
}; };
let task_result = match entry { cx.emit(ThreadHistoryEvent::Open(entry.clone()));
HistoryEntry::Thread(thread) => { // let task_result = match entry {
self.agent_panel.update(cx, move |agent_panel, cx| todo!()) // HistoryEntry::Thread(thread) => {
} // self.agent_panel.update(cx, move |agent_panel, cx| todo!())
HistoryEntry::Context(context) => { // }
self.agent_panel.update(cx, move |agent_panel, cx| { // HistoryEntry::Context(context) => {
agent_panel.open_saved_prompt_editor(context.path.clone(), window, cx) // self.agent_panel.update(cx, move |agent_panel, cx| {
}) // agent_panel.open_saved_prompt_editor(context.path.clone(), window, cx)
} // })
}; // }
// };
if let Some(task) = task_result.log_err() { // if let Some(task) = task_result.log_err() {
task.detach_and_log_err(cx); // task.detach_and_log_err(cx);
}; // };
cx.notify(); cx.notify();
} }
@ -606,9 +611,9 @@ impl AcpThreadHistory {
} else { } else {
None None
}) })
.on_click(cx.listener(move |this, _, window, cx| { .on_click(
this.confirm_entry(list_entry_ix, window, cx) cx.listener(move |this, _, _, cx| this.confirm_entry(list_entry_ix, cx)),
})), ),
) )
.into_any_element() .into_any_element()
} }

View file

@ -1,6 +1,7 @@
use acp_thread::{ use acp_thread::{
AcpThread, AcpThreadEvent, AgentThreadEntry, AssistantMessage, AssistantMessageChunk, AcpThread, AcpThreadEvent, AcpThreadMetadata, AgentThreadEntry, AssistantMessage,
LoadError, MentionUri, ThreadStatus, ToolCall, ToolCallContent, ToolCallStatus, UserMessageId, AssistantMessageChunk, LoadError, MentionUri, ThreadStatus, ToolCall, ToolCallContent,
ToolCallStatus, UserMessageId,
}; };
use acp_thread::{AgentConnection, Plan}; use acp_thread::{AgentConnection, Plan};
use action_log::ActionLog; use action_log::ActionLog;
@ -136,6 +137,7 @@ impl AcpThreadView {
project: Entity<Project>, project: Entity<Project>,
thread_store: Entity<ThreadStore>, thread_store: Entity<ThreadStore>,
text_thread_store: Entity<TextThreadStore>, text_thread_store: Entity<TextThreadStore>,
restore_thread: Option<AcpThreadMetadata>,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) -> Self { ) -> Self {

View file

@ -4,13 +4,13 @@ use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use acp_thread::AcpThreadMetadata;
use agent_servers::AgentServer; use agent_servers::AgentServer;
use agent2::NativeAgentServer; use agent2::history_store::HistoryEntry;
use db::kvp::{Dismissable, KEY_VALUE_STORE}; use db::kvp::{Dismissable, KEY_VALUE_STORE};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::NewExternalAgentThread; use crate::acp::{AcpThreadHistory, ThreadHistoryEvent};
use crate::acp::AcpThreadHistory;
use crate::agent_diff::AgentDiffThread; use crate::agent_diff::AgentDiffThread;
use crate::{ use crate::{
AddContextServer, AgentDiffPane, ContinueThread, ContinueWithBurnMode, AddContextServer, AgentDiffPane, ContinueThread, ContinueWithBurnMode,
@ -31,6 +31,7 @@ use crate::{
thread_history::{HistoryEntryElement, ThreadHistory}, thread_history::{HistoryEntryElement, ThreadHistory},
ui::{AgentOnboardingModal, EndTrialUpsell}, ui::{AgentOnboardingModal, EndTrialUpsell},
}; };
use crate::{ExternalAgent, NewExternalAgentThread};
use agent::{ use agent::{
Thread, ThreadError, ThreadEvent, ThreadId, ThreadSummary, TokenUsageRatio, Thread, ThreadError, ThreadEvent, ThreadId, ThreadSummary, TokenUsageRatio,
context_store::ContextStore, context_store::ContextStore,
@ -121,7 +122,7 @@ pub fn init(cx: &mut App) {
if let Some(panel) = workspace.panel::<AgentPanel>(cx) { if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
workspace.focus_panel::<AgentPanel>(window, cx); workspace.focus_panel::<AgentPanel>(window, cx);
panel.update(cx, |panel, cx| { panel.update(cx, |panel, cx| {
panel.new_external_thread(action.agent, window, cx) panel.new_external_thread(action.agent, None, window, cx)
}); });
} }
}) })
@ -746,8 +747,26 @@ impl AgentPanel {
) )
}); });
let acp_history = let acp_history = cx.new(|cx| AcpThreadHistory::new(&project, window, cx));
cx.new(|cx| AcpThreadHistory::new(weak_self.clone(), &project, window, cx)); cx.subscribe_in(
&acp_history,
window,
|this, _, event, window, cx| match event {
ThreadHistoryEvent::Open(HistoryEntry::Thread(thread)) => {
let agent_choice = match thread.agent.0.as_ref() {
"Claude Code" => Some(ExternalAgent::ClaudeCode),
"Gemini" => Some(ExternalAgent::Gemini),
"Native Agent" => Some(ExternalAgent::NativeAgent),
_ => None,
};
this.new_external_thread(agent_choice, Some(thread.clone()), window, cx);
}
ThreadHistoryEvent::Open(HistoryEntry::Context(thread)) => {
todo!()
}
},
)
.detach();
Self { Self {
active_view, active_view,
@ -962,6 +981,7 @@ impl AgentPanel {
fn new_external_thread( fn new_external_thread(
&mut self, &mut self,
agent_choice: Option<crate::ExternalAgent>, agent_choice: Option<crate::ExternalAgent>,
restore_thread: Option<AcpThreadMetadata>,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
@ -1019,6 +1039,7 @@ impl AgentPanel {
project, project,
thread_store.clone(), thread_store.clone(),
text_thread_store.clone(), text_thread_store.clone(),
restore_thread,
window, window,
cx, cx,
) )