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 Codex;
15
16impl AgentServer for Codex {
17 fn name(&self) -> &'static str {
18 "Codex"
19 }
20
21 fn empty_state_headline(&self) -> &'static str {
22 "Welcome to Codex"
23 }
24
25 fn empty_state_message(&self) -> &'static str {
26 "What can I help with?"
27 }
28
29 fn logo(&self) -> ui::IconName {
30 ui::IconName::AiOpenAi
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 let working_directory = project.read(cx).active_project_directory(cx);
42 cx.spawn(async move |cx| {
43 let settings = cx.read_global(|settings: &SettingsStore, _| {
44 settings.get::<AllAgentServersSettings>(None).codex.clone()
45 })?;
46
47 let Some(command) =
48 AgentServerCommand::resolve("codex", &["mcp"], settings, &project, cx).await
49 else {
50 anyhow::bail!("Failed to find codex binary");
51 };
52 // todo! check supported version
53
54 let conn = AcpConnection::stdio(server_name, command, working_directory, cx).await?;
55 Ok(Rc::new(conn) as _)
56 })
57 }
58}
59
60#[cfg(test)]
61pub(crate) mod tests {
62 use super::*;
63 use crate::AgentServerCommand;
64 use std::path::Path;
65
66 crate::common_e2e_tests!(Codex, allow_option_id = "approve");
67
68 pub fn local_command() -> AgentServerCommand {
69 let cli_path = Path::new(env!("CARGO_MANIFEST_DIR"))
70 .join("../../../codex/codex-rs/target/debug/codex");
71
72 AgentServerCommand {
73 path: cli_path,
74 args: vec![],
75 env: None,
76 }
77 }
78}