codex.rs

  1use crate::stdio_agent_server::{StdioAgentServer, find_bin_in_path};
  2use crate::{AgentServerCommand, AgentServerVersion};
  3use anyhow::{Context as _, Result};
  4use gpui::{AsyncApp, Entity};
  5use project::Project;
  6use settings::SettingsStore;
  7
  8use crate::AllAgentServersSettings;
  9
 10#[derive(Clone)]
 11pub struct Codex;
 12
 13const ACP_ARG: &str = "acp";
 14
 15impl StdioAgentServer for Codex {
 16    fn name(&self) -> &'static str {
 17        "Codex"
 18    }
 19
 20    fn empty_state_headline(&self) -> &'static str {
 21        "Welcome to Codex"
 22    }
 23
 24    fn empty_state_message(&self) -> &'static str {
 25        "Ask questions, edit files, run commands.\nBe specific for the best results."
 26    }
 27
 28    fn logo(&self) -> ui::IconName {
 29        ui::IconName::AiOpenAi
 30    }
 31
 32    async fn command(
 33        &self,
 34        project: &Entity<Project>,
 35        cx: &mut AsyncApp,
 36    ) -> Result<AgentServerCommand> {
 37        let custom_command = cx.read_global(|settings: &SettingsStore, _| {
 38            let settings = settings.get::<AllAgentServersSettings>(None);
 39            settings
 40                .codex
 41                .as_ref()
 42                .map(|codex_settings| AgentServerCommand {
 43                    path: codex_settings.command.path.clone(),
 44                    args: codex_settings
 45                        .command
 46                        .args
 47                        .iter()
 48                        .cloned()
 49                        .chain(std::iter::once(ACP_ARG.into()))
 50                        .collect(),
 51                    env: codex_settings.command.env.clone(),
 52                })
 53        })?;
 54
 55        if let Some(custom_command) = custom_command {
 56            return Ok(custom_command);
 57        }
 58
 59        if let Some(path) = find_bin_in_path("codex", project, cx).await {
 60            return Ok(AgentServerCommand {
 61                path,
 62                args: vec![ACP_ARG.into()],
 63                env: None,
 64            });
 65        }
 66
 67        todo!()
 68        // let (fs, node_runtime) = project.update(cx, |project, _| {
 69        //     (project.fs().clone(), project.node_runtime().cloned())
 70        // })?;
 71        // let node_runtime = node_runtime.context("codex not found on path")?;
 72
 73        // let directory = ::paths::agent_servers_dir().join("codex");
 74        // fs.create_dir(&directory).await?;
 75        // node_runtime
 76        //     .npm_install_packages(&directory, &[("@google/gemini-cli", "latest")])
 77        //     .await?;
 78        // let path = directory.join("node_modules/.bin/gemini");
 79
 80        // Ok(AgentServerCommand {
 81        //     path,
 82        //     args: vec![ACP_ARG.into()],
 83        //     env: None,
 84        // })
 85    }
 86
 87    async fn version(&self, command: &AgentServerCommand) -> Result<AgentServerVersion> {
 88        let version_fut = util::command::new_smol_command(&command.path)
 89            .args(command.args.iter())
 90            .arg("--version")
 91            .kill_on_drop(true)
 92            .output();
 93
 94        let help_fut = util::command::new_smol_command(&command.path)
 95            .args(command.args.iter())
 96            .arg("--help")
 97            .kill_on_drop(true)
 98            .output();
 99
100        let (version_output, help_output) = futures::future::join(version_fut, help_fut).await;
101
102        let current_version = String::from_utf8(version_output?.stdout)?;
103        let supported = String::from_utf8(help_output?.stdout)?.contains(ACP_ARG);
104
105        if supported {
106            Ok(AgentServerVersion::Supported)
107        } else {
108            Ok(AgentServerVersion::Unsupported {
109                error_message: format!(
110                    "Your installed version of Codex {} doesn't support the Agentic Coding Protocol (ACP).",
111                    current_version
112                ).into(),
113                upgrade_message: "Upgrade Codex to Latest".into(),
114                upgrade_command: "npm install -g @openai/codex@latest".into(),
115            })
116        }
117    }
118}