custom.rs

 1use crate::AgentServerDelegate;
 2use acp_thread::AgentConnection;
 3use anyhow::{Context as _, Result};
 4use gpui::{App, SharedString, Task};
 5use project::agent_server_store::ExternalAgentServerName;
 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}
13
14impl CustomAgentServer {
15    pub fn new(name: SharedString) -> Self {
16        Self { name }
17    }
18}
19
20impl crate::AgentServer for CustomAgentServer {
21    fn telemetry_id(&self) -> &'static str {
22        "custom"
23    }
24
25    fn name(&self) -> SharedString {
26        self.name.clone()
27    }
28
29    fn logo(&self) -> IconName {
30        IconName::Terminal
31    }
32
33    fn connect(
34        &self,
35        root_dir: Option<&Path>,
36        delegate: AgentServerDelegate,
37        cx: &mut App,
38    ) -> Task<Result<(Rc<dyn AgentConnection>, Option<task::SpawnInTerminal>)>> {
39        let name = self.name();
40        let root_dir = root_dir.map(|root_dir| root_dir.to_string_lossy().to_string());
41        let is_remote = delegate.project.read(cx).is_via_remote_server();
42        let store = delegate.store.downgrade();
43
44        cx.spawn(async move |cx| {
45            let (command, root_dir, login) = store
46                .update(cx, |store, cx| {
47                    let agent = store
48                        .get_external_agent(&ExternalAgentServerName(name.clone()))
49                        .with_context(|| {
50                            format!("Custom agent server `{}` is not registered", name)
51                        })?;
52                    anyhow::Ok(agent.get_command(
53                        root_dir.as_deref(),
54                        Default::default(),
55                        delegate.status_tx,
56                        delegate.new_version_available,
57                        &mut cx.to_async(),
58                    ))
59                })??
60                .await?;
61            let connection =
62                crate::acp::connect(name, command, root_dir.as_ref(), is_remote, cx).await?;
63            Ok((connection, login))
64        })
65    }
66
67    fn into_any(self: Rc<Self>) -> Rc<dyn std::any::Any> {
68        self
69    }
70}