custom.rs

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