1mod acp;
2mod claude;
3mod custom;
4mod gemini;
5
6#[cfg(any(test, feature = "test-support"))]
7pub mod e2e_tests;
8
9pub use claude::*;
10use client::ProxySettings;
11use collections::HashMap;
12pub use custom::*;
13use fs::Fs;
14pub use gemini::*;
15use http_client::read_no_proxy_from_env;
16use project::agent_server_store::AgentServerStore;
17
18use acp_thread::AgentConnection;
19use anyhow::Result;
20use gpui::{App, AppContext, Entity, SharedString, Task};
21use project::Project;
22use settings::SettingsStore;
23use std::{any::Any, path::Path, rc::Rc, sync::Arc};
24
25pub use acp::AcpConnection;
26
27pub struct AgentServerDelegate {
28 store: Entity<AgentServerStore>,
29 project: Entity<Project>,
30 status_tx: Option<watch::Sender<SharedString>>,
31 new_version_available: Option<watch::Sender<Option<String>>>,
32}
33
34impl AgentServerDelegate {
35 pub fn new(
36 store: Entity<AgentServerStore>,
37 project: Entity<Project>,
38 status_tx: Option<watch::Sender<SharedString>>,
39 new_version_tx: Option<watch::Sender<Option<String>>>,
40 ) -> Self {
41 Self {
42 store,
43 project,
44 status_tx,
45 new_version_available: new_version_tx,
46 }
47 }
48
49 pub fn project(&self) -> &Entity<Project> {
50 &self.project
51 }
52}
53
54pub trait AgentServer: Send {
55 fn logo(&self) -> ui::IconName;
56 fn name(&self) -> SharedString;
57 fn telemetry_id(&self) -> &'static str;
58 fn default_mode(&self, _cx: &mut App) -> Option<agent_client_protocol::SessionModeId> {
59 None
60 }
61 fn set_default_mode(
62 &self,
63 _mode_id: Option<agent_client_protocol::SessionModeId>,
64 _fs: Arc<dyn Fs>,
65 _cx: &mut App,
66 ) {
67 }
68
69 fn connect(
70 &self,
71 root_dir: Option<&Path>,
72 delegate: AgentServerDelegate,
73 cx: &mut App,
74 ) -> Task<Result<(Rc<dyn AgentConnection>, Option<task::SpawnInTerminal>)>>;
75
76 fn into_any(self: Rc<Self>) -> Rc<dyn Any>;
77}
78
79impl dyn AgentServer {
80 pub fn downcast<T: 'static + AgentServer + Sized>(self: Rc<Self>) -> Option<Rc<T>> {
81 self.into_any().downcast().ok()
82 }
83}
84
85/// Load the default proxy environment variables to pass through to the agent
86pub fn load_proxy_env(cx: &mut App) -> HashMap<String, String> {
87 let proxy_url = cx
88 .read_global(|settings: &SettingsStore, _| settings.get::<ProxySettings>(None).proxy_url());
89 let mut env = HashMap::default();
90
91 if let Some(proxy_url) = &proxy_url {
92 let env_var = if proxy_url.scheme() == "https" {
93 "HTTPS_PROXY"
94 } else {
95 "HTTP_PROXY"
96 };
97 env.insert(env_var.to_owned(), proxy_url.to_string());
98 }
99
100 if let Some(no_proxy) = read_no_proxy_from_env() {
101 env.insert("NO_PROXY".to_owned(), no_proxy);
102 } else if proxy_url.is_some() {
103 // We sometimes need local MCP servers that we don't want to proxy
104 env.insert("NO_PROXY".to_owned(), "localhost,127.0.0.1".to_owned());
105 }
106
107 env
108}