use std::{any::Any, path::Path, rc::Rc, sync::Arc}; use agent_servers::AgentServer; use anyhow::Result; use fs::Fs; use gpui::{App, Entity, SharedString, Task}; use project::Project; use prompt_store::PromptStore; use crate::{HistoryStore, NativeAgent, NativeAgentConnection, templates::Templates}; #[derive(Clone)] pub struct NativeAgentServer { fs: Arc, history: Entity, } impl NativeAgentServer { pub fn new(fs: Arc, history: Entity) -> Self { Self { fs, history } } } impl AgentServer for NativeAgentServer { fn telemetry_id(&self) -> &'static str { "zed" } fn name(&self) -> SharedString { "Zed Agent".into() } fn empty_state_headline(&self) -> SharedString { self.name() } fn empty_state_message(&self) -> SharedString { "".into() } fn logo(&self) -> ui::IconName { ui::IconName::ZedAgent } fn connect( &self, _root_dir: &Path, project: &Entity, cx: &mut App, ) -> Task>> { log::debug!( "NativeAgentServer::connect called for path: {:?}", _root_dir ); let project = project.clone(); let fs = self.fs.clone(); let history = self.history.clone(); let prompt_store = PromptStore::global(cx); cx.spawn(async move |cx| { log::debug!("Creating templates for native agent"); let templates = Templates::new(); let prompt_store = prompt_store.await?; log::debug!("Creating native agent entity"); let agent = NativeAgent::new(project, history, templates, Some(prompt_store), fs, cx).await?; // Create the connection wrapper let connection = NativeAgentConnection(agent); log::debug!("NativeAgentServer connection established successfully"); Ok(Rc::new(connection) as Rc) }) } fn into_any(self: Rc) -> Rc { self } } #[cfg(test)] mod tests { use super::*; use assistant_context::ContextStore; use gpui::AppContext; agent_servers::e2e_tests::common_e2e_tests!( async |fs, project, cx| { let auth = cx.update(|cx| { prompt_store::init(cx); terminal::init(cx); let registry = language_model::LanguageModelRegistry::read_global(cx); let auth = registry .provider(&language_model::ANTHROPIC_PROVIDER_ID) .unwrap() .authenticate(cx); cx.spawn(async move |_| auth.await) }); auth.await.unwrap(); cx.update(|cx| { let registry = language_model::LanguageModelRegistry::global(cx); registry.update(cx, |registry, cx| { registry.select_default_model( Some(&language_model::SelectedModel { provider: language_model::ANTHROPIC_PROVIDER_ID, model: language_model::LanguageModelId("claude-sonnet-4-latest".into()), }), cx, ); }); }); let history = cx.update(|cx| { let context_store = cx.new(move |cx| ContextStore::fake(project.clone(), cx)); cx.new(move |cx| HistoryStore::new(context_store, cx)) }); NativeAgentServer::new(fs.clone(), history) }, allow_option_id = "allow" ); }