1use project::Project;
2use settings::SettingsStore;
3use std::path::Path;
4use std::rc::Rc;
5
6use anyhow::Result;
7use gpui::{App, Entity, Task};
8
9use crate::acp_connection::AcpConnection;
10use crate::{AgentServer, AgentServerCommand, AllAgentServersSettings};
11use acp_thread::AgentConnection;
12
13#[derive(Clone)]
14pub struct Gemini;
15
16impl AgentServer for Gemini {
17 fn name(&self) -> &'static str {
18 "Gemini"
19 }
20
21 fn empty_state_headline(&self) -> &'static str {
22 "Welcome to Gemini"
23 }
24
25 fn empty_state_message(&self) -> &'static str {
26 "Ask questions, edit files, run commands.\nBe specific for the best results."
27 }
28
29 fn logo(&self) -> ui::IconName {
30 ui::IconName::AiGemini
31 }
32
33 fn connect(
34 &self,
35 _root_dir: &Path,
36 project: &Entity<Project>,
37 cx: &mut App,
38 ) -> Task<Result<Rc<dyn AgentConnection>>> {
39 let project = project.clone();
40 let server_name = self.name();
41 cx.spawn(async move |cx| {
42 let settings = cx.read_global(|settings: &SettingsStore, _| {
43 settings.get::<AllAgentServersSettings>(None).gemini.clone()
44 })?;
45
46 let Some(command) = AgentServerCommand::resolve(
47 "gemini",
48 &["--experimental-mcp"],
49 settings,
50 &project,
51 cx,
52 )
53 .await
54 else {
55 anyhow::bail!("Failed to find gemini binary");
56 };
57
58 let conn = AcpConnection::stdio(server_name, command, cx).await?;
59 Ok(Rc::new(conn) as _)
60 })
61 }
62}
63
64#[cfg(test)]
65pub(crate) mod tests {
66 use super::*;
67 use crate::AgentServerCommand;
68 use std::path::Path;
69
70 crate::common_e2e_tests!(Gemini, allow_option_id = "allow");
71
72 pub fn local_command() -> AgentServerCommand {
73 let cli_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../gemini/packages/cli");
74
75 AgentServerCommand {
76 path: "node".into(),
77 args: vec![cli_path.to_string_lossy().to_string()],
78 env: None,
79 }
80 }
81}