1use agent_client_protocol as acp;
2use std::rc::Rc;
3use std::{any::Any, path::Path};
4
5use crate::{AgentServer, AgentServerDelegate, load_proxy_env};
6use acp_thread::AgentConnection;
7use anyhow::{Context as _, Result};
8use gpui::{App, SharedString, Task};
9
10#[derive(Clone)]
11pub struct Codex;
12
13impl AgentServer for Codex {
14 fn telemetry_id(&self) -> &'static str {
15 "codex"
16 }
17
18 fn name(&self) -> SharedString {
19 "Codex".into()
20 }
21
22 fn logo(&self) -> ui::IconName {
23 // No dedicated Codex icon yet; use the generic AI icon.
24 ui::IconName::AiOpenAi
25 }
26
27 fn connect(
28 &self,
29 root_dir: Option<&Path>,
30 delegate: AgentServerDelegate,
31 cx: &mut App,
32 ) -> Task<Result<(Rc<dyn AgentConnection>, Option<task::SpawnInTerminal>)>> {
33 let name = self.name();
34 let root_dir = root_dir.map(|root_dir| root_dir.to_string_lossy().into_owned());
35 let is_remote = delegate.project.read(cx).is_via_remote_server();
36 let store = delegate.store.downgrade();
37 let extra_env = load_proxy_env(cx);
38 // No modes for Codex (yet).
39 let default_mode = self.default_mode(cx);
40
41 cx.spawn(async move |cx| {
42 // Look up the external agent registered under the "codex" name.
43 // The AgentServerStore is responsible for:
44 // - Downloading the correct GitHub release tar.gz for the OS/arch
45 // - Extracting the binary
46 // - Returning an AgentServerCommand to launch the binary
47 // - Always reporting "no updates" for now
48 let (command, root_dir, login) = store
49 .update(cx, |store, cx| {
50 let agent = store
51 .get_external_agent(&"codex".into())
52 .context("Codex is not registered")?;
53 anyhow::Ok(agent.get_command(
54 root_dir.as_deref(),
55 extra_env,
56 delegate.status_tx,
57 // For now, Codex should report that there are no updates.
58 // The LocalCodex implementation in AgentServerStore should not send any updates.
59 delegate.new_version_available,
60 &mut cx.to_async(),
61 ))
62 })??
63 .await?;
64
65 let connection = crate::acp::connect(
66 name,
67 command,
68 root_dir.as_ref(),
69 default_mode,
70 is_remote,
71 cx,
72 )
73 .await?;
74 Ok((connection, login))
75 })
76 }
77
78 fn into_any(self: Rc<Self>) -> Rc<dyn Any> {
79 self
80 }
81}