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::agent_server_store::AgentServerStore;
13
14use acp_thread::AgentConnection;
15use anyhow::Result;
16use gpui::{App, AppContext, Entity, SharedString, Task};
17use settings::SettingsStore;
18use std::{any::Any, rc::Rc, sync::Arc};
19
20pub use acp::AcpConnection;
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 name(&self) -> SharedString;
42 fn connect(
43 &self,
44 delegate: AgentServerDelegate,
45 cx: &mut App,
46 ) -> Task<Result<Rc<dyn AgentConnection>>>;
47
48 fn into_any(self: Rc<Self>) -> Rc<dyn Any>;
49
50 fn default_mode(&self, _cx: &App) -> Option<agent_client_protocol::SessionModeId> {
51 None
52 }
53
54 fn set_default_mode(
55 &self,
56 _mode_id: Option<agent_client_protocol::SessionModeId>,
57 _fs: Arc<dyn Fs>,
58 _cx: &mut App,
59 ) {
60 }
61
62 fn default_model(&self, _cx: &App) -> Option<agent_client_protocol::ModelId> {
63 None
64 }
65
66 fn set_default_model(
67 &self,
68 _model_id: Option<agent_client_protocol::ModelId>,
69 _fs: Arc<dyn Fs>,
70 _cx: &mut App,
71 ) {
72 }
73
74 fn favorite_model_ids(&self, _cx: &mut App) -> HashSet<agent_client_protocol::ModelId> {
75 HashSet::default()
76 }
77
78 fn default_config_option(&self, _config_id: &str, _cx: &App) -> Option<String> {
79 None
80 }
81
82 fn set_default_config_option(
83 &self,
84 _config_id: &str,
85 _value_id: Option<&str>,
86 _fs: Arc<dyn Fs>,
87 _cx: &mut App,
88 ) {
89 }
90
91 fn favorite_config_option_value_ids(
92 &self,
93 _config_id: &agent_client_protocol::SessionConfigId,
94 _cx: &mut App,
95 ) -> HashSet<agent_client_protocol::SessionConfigValueId> {
96 HashSet::default()
97 }
98
99 fn toggle_favorite_config_option_value(
100 &self,
101 _config_id: agent_client_protocol::SessionConfigId,
102 _value_id: agent_client_protocol::SessionConfigValueId,
103 _should_be_favorite: bool,
104 _fs: Arc<dyn Fs>,
105 _cx: &App,
106 ) {
107 }
108
109 fn toggle_favorite_model(
110 &self,
111 _model_id: agent_client_protocol::ModelId,
112 _should_be_favorite: bool,
113 _fs: Arc<dyn Fs>,
114 _cx: &App,
115 ) {
116 }
117}
118
119impl dyn AgentServer {
120 pub fn downcast<T: 'static + AgentServer + Sized>(self: Rc<Self>) -> Option<Rc<T>> {
121 self.into_any().downcast().ok()
122 }
123}
124
125/// Load the default proxy environment variables to pass through to the agent
126pub fn load_proxy_env(cx: &mut App) -> HashMap<String, String> {
127 let proxy_url = cx
128 .read_global(|settings: &SettingsStore, _| settings.get::<ProxySettings>(None).proxy_url());
129 let mut env = HashMap::default();
130
131 if let Some(proxy_url) = &proxy_url {
132 let env_var = if proxy_url.scheme() == "https" {
133 "HTTPS_PROXY"
134 } else {
135 "HTTP_PROXY"
136 };
137 env.insert(env_var.to_owned(), proxy_url.to_string());
138 }
139
140 if let Some(no_proxy) = read_no_proxy_from_env() {
141 env.insert("NO_PROXY".to_owned(), no_proxy);
142 } else if proxy_url.is_some() {
143 // We sometimes need local MCP servers that we don't want to proxy
144 env.insert("NO_PROXY".to_owned(), "localhost,127.0.0.1".to_owned());
145 }
146
147 env
148}