agent_servers.rs

  1mod acp;
  2mod custom;
  3
  4#[cfg(any(test, feature = "test-support"))]
  5pub mod e2e_tests;
  6
  7use client::ProxySettings;
  8use collections::{HashMap, HashSet};
  9pub use custom::*;
 10use fs::Fs;
 11use http_client::read_no_proxy_from_env;
 12use project::{AgentId, Project, agent_server_store::AgentServerStore};
 13
 14use acp_thread::AgentConnection;
 15use anyhow::Result;
 16use gpui::{App, AppContext, Entity, Task};
 17use settings::SettingsStore;
 18use std::{any::Any, rc::Rc, sync::Arc};
 19
 20pub use acp::{AcpConnection, GEMINI_TERMINAL_AUTH_METHOD_ID};
 21
 22pub struct AgentServerDelegate {
 23    store: Entity<AgentServerStore>,
 24    new_version_available: Option<watch::Sender<Option<String>>>,
 25}
 26
 27impl AgentServerDelegate {
 28    pub fn new(
 29        store: Entity<AgentServerStore>,
 30        new_version_tx: Option<watch::Sender<Option<String>>>,
 31    ) -> Self {
 32        Self {
 33            store,
 34            new_version_available: new_version_tx,
 35        }
 36    }
 37}
 38
 39pub trait AgentServer: Send {
 40    fn logo(&self) -> ui::IconName;
 41    fn agent_id(&self) -> AgentId;
 42    fn connect(
 43        &self,
 44        delegate: AgentServerDelegate,
 45        project: Entity<Project>,
 46        cx: &mut App,
 47    ) -> Task<Result<Rc<dyn AgentConnection>>>;
 48
 49    fn into_any(self: Rc<Self>) -> Rc<dyn Any>;
 50
 51    fn default_mode(&self, _cx: &App) -> Option<agent_client_protocol::SessionModeId> {
 52        None
 53    }
 54
 55    fn set_default_mode(
 56        &self,
 57        _mode_id: Option<agent_client_protocol::SessionModeId>,
 58        _fs: Arc<dyn Fs>,
 59        _cx: &mut App,
 60    ) {
 61    }
 62
 63    fn default_model(&self, _cx: &App) -> Option<agent_client_protocol::ModelId> {
 64        None
 65    }
 66
 67    fn set_default_model(
 68        &self,
 69        _model_id: Option<agent_client_protocol::ModelId>,
 70        _fs: Arc<dyn Fs>,
 71        _cx: &mut App,
 72    ) {
 73    }
 74
 75    fn favorite_model_ids(&self, _cx: &mut App) -> HashSet<agent_client_protocol::ModelId> {
 76        HashSet::default()
 77    }
 78
 79    fn default_config_option(&self, _config_id: &str, _cx: &App) -> Option<String> {
 80        None
 81    }
 82
 83    fn set_default_config_option(
 84        &self,
 85        _config_id: &str,
 86        _value_id: Option<&str>,
 87        _fs: Arc<dyn Fs>,
 88        _cx: &mut App,
 89    ) {
 90    }
 91
 92    fn favorite_config_option_value_ids(
 93        &self,
 94        _config_id: &agent_client_protocol::SessionConfigId,
 95        _cx: &mut App,
 96    ) -> HashSet<agent_client_protocol::SessionConfigValueId> {
 97        HashSet::default()
 98    }
 99
100    fn toggle_favorite_config_option_value(
101        &self,
102        _config_id: agent_client_protocol::SessionConfigId,
103        _value_id: agent_client_protocol::SessionConfigValueId,
104        _should_be_favorite: bool,
105        _fs: Arc<dyn Fs>,
106        _cx: &App,
107    ) {
108    }
109
110    fn toggle_favorite_model(
111        &self,
112        _model_id: agent_client_protocol::ModelId,
113        _should_be_favorite: bool,
114        _fs: Arc<dyn Fs>,
115        _cx: &App,
116    ) {
117    }
118}
119
120impl dyn AgentServer {
121    pub fn downcast<T: 'static + AgentServer + Sized>(self: Rc<Self>) -> Option<Rc<T>> {
122        self.into_any().downcast().ok()
123    }
124}
125
126/// Load the default proxy environment variables to pass through to the agent
127pub fn load_proxy_env(cx: &mut App) -> HashMap<String, String> {
128    let proxy_url = cx
129        .read_global(|settings: &SettingsStore, _| settings.get::<ProxySettings>(None).proxy_url());
130    let mut env = HashMap::default();
131
132    if let Some(proxy_url) = &proxy_url {
133        let env_var = if proxy_url.scheme() == "https" {
134            "HTTPS_PROXY"
135        } else {
136            "HTTP_PROXY"
137        };
138        env.insert(env_var.to_owned(), proxy_url.to_string());
139    }
140
141    if let Some(no_proxy) = read_no_proxy_from_env() {
142        env.insert("NO_PROXY".to_owned(), no_proxy);
143    } else if proxy_url.is_some() {
144        // We sometimes need local MCP servers that we don't want to proxy
145        env.insert("NO_PROXY".to_owned(), "localhost,127.0.0.1".to_owned());
146    }
147
148    env
149}