1use crate::{AgentServerCommand, AgentServerDelegate};
2use acp_thread::AgentConnection;
3use anyhow::Result;
4use gpui::{App, SharedString, Task};
5use language_models::provider::anthropic::AnthropicLanguageModelProvider;
6use std::{path::Path, rc::Rc};
7use ui::IconName;
8
9/// A generic agent server implementation for custom user-defined agents
10pub struct CustomAgentServer {
11 name: SharedString,
12 command: AgentServerCommand,
13}
14
15impl CustomAgentServer {
16 pub fn new(name: SharedString, command: AgentServerCommand) -> Self {
17 Self { name, command }
18 }
19}
20
21impl crate::AgentServer for CustomAgentServer {
22 fn telemetry_id(&self) -> &'static str {
23 "custom"
24 }
25
26 fn name(&self) -> SharedString {
27 self.name.clone()
28 }
29
30 fn logo(&self) -> IconName {
31 IconName::Terminal
32 }
33
34 fn connect(
35 &self,
36 root_dir: &Path,
37 _delegate: AgentServerDelegate,
38 cx: &mut App,
39 ) -> Task<Result<Rc<dyn AgentConnection>>> {
40 let server_name = self.name();
41 let mut command = self.command.clone();
42 let root_dir = root_dir.to_path_buf();
43
44 // TODO: Remove this once we have Claude properly
45 cx.spawn(async move |mut cx| {
46 if let Some(api_key) = cx
47 .update(AnthropicLanguageModelProvider::api_key)?
48 .await
49 .ok()
50 {
51 command
52 .env
53 .get_or_insert_default()
54 .insert("ANTHROPIC_API_KEY".to_owned(), api_key.key);
55 }
56
57 crate::acp::connect(server_name, command, &root_dir, &mut cx).await
58 })
59 }
60
61 fn into_any(self: Rc<Self>) -> Rc<dyn std::any::Any> {
62 self
63 }
64}