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};
8
9#[derive(Clone)]
10pub struct Codex;
11
12impl AgentServer for Codex {
13 fn telemetry_id(&self) -> &'static str {
14 "codex"
15 }
16
17 fn name(&self) -> SharedString {
18 "Codex".into()
19 }
20
21 fn logo(&self) -> ui::IconName {
22 // No dedicated Codex icon yet; use the generic AI icon.
23 ui::IconName::AiOpenAi
24 }
25
26 fn connect(
27 &self,
28 root_dir: Option<&Path>,
29 delegate: AgentServerDelegate,
30 cx: &mut App,
31 ) -> Task<Result<(Rc<dyn AgentConnection>, Option<task::SpawnInTerminal>)>> {
32 let name = self.name();
33 let root_dir = root_dir.map(|root_dir| root_dir.to_string_lossy().into_owned());
34 let is_remote = delegate.project.read(cx).is_via_remote_server();
35 let store = delegate.store.downgrade();
36 let extra_env = load_proxy_env(cx);
37 // No modes for Codex (yet).
38 let default_mode = self.default_mode(cx);
39
40 cx.spawn(async move |cx| {
41 // Look up the external agent registered under the "codex" name.
42 // The AgentServerStore is responsible for:
43 // - Downloading the correct GitHub release tar.gz for the OS/arch
44 // - Extracting the binary
45 // - Returning an AgentServerCommand to launch the binary
46 // - Always reporting "no updates" for now
47 let (command, root_dir, login) = store
48 .update(cx, |store, cx| {
49 let agent = store
50 .get_external_agent(&"codex".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, Codex should report that there are no updates.
57 // The LocalCodex implementation in AgentServerStore should not send any updates.
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}