1use std::rc::Rc;
2use std::{any::Any, path::Path};
3
4use crate::{AgentServer, AgentServerDelegate, load_proxy_env};
5use acp_thread::AgentConnection;
6use anyhow::{Context as _, Result};
7use gpui::{App, SharedString, Task};
8use project::agent_server_store::CODEX_NAME;
9
10#[derive(Clone)]
11pub struct Codex;
12
13#[cfg(test)]
14pub(crate) mod tests {
15 use super::*;
16
17 crate::common_e2e_tests!(async |_, _, _| Codex, allow_option_id = "proceed_once");
18}
19
20impl AgentServer for Codex {
21 fn telemetry_id(&self) -> &'static str {
22 "codex"
23 }
24
25 fn name(&self) -> SharedString {
26 "Codex".into()
27 }
28
29 fn logo(&self) -> ui::IconName {
30 ui::IconName::AiOpenAi
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().into_owned());
41 let is_remote = delegate.project.read(cx).is_via_remote_server();
42 let store = delegate.store.downgrade();
43 let extra_env = load_proxy_env(cx);
44 let default_mode = self.default_mode(cx);
45
46 cx.spawn(async move |cx| {
47 let (command, root_dir, login) = store
48 .update(cx, |store, cx| {
49 let agent = store
50 .get_external_agent(&CODEX_NAME.into())
51 .context("Codex is not registered")?;
52 anyhow::Ok(agent.get_command(
53 root_dir.as_deref(),
54 extra_env,
55 delegate.status_tx,
56 // For now, report that there are no updates.
57 // (A future PR will use the GitHub Releases API to fetch them.)
58 delegate.new_version_available,
59 &mut cx.to_async(),
60 ))
61 })??
62 .await?;
63
64 let connection = crate::acp::connect(
65 name,
66 command,
67 root_dir.as_ref(),
68 default_mode,
69 is_remote,
70 cx,
71 )
72 .await?;
73 Ok((connection, login))
74 })
75 }
76
77 fn into_any(self: Rc<Self>) -> Rc<dyn Any> {
78 self
79 }
80}