diff --git a/crates/project/src/agent_server_store.rs b/crates/project/src/agent_server_store.rs index 4618ea049dc08bb29749dd7bd77a7bd07fa87eaa..0e81be84cbc1d9809b17394a3748d74a9a945027 100644 --- a/crates/project/src/agent_server_store.rs +++ b/crates/project/src/agent_server_store.rs @@ -8,7 +8,6 @@ use std::{ }; use anyhow::{Context as _, Result, bail}; -use client::Client; use collections::HashMap; use feature_flags::FeatureFlagAppExt as _; use fs::{Fs, RemoveOptions, RenameOptions}; @@ -16,7 +15,7 @@ use futures::StreamExt as _; use gpui::{ AppContext as _, AsyncApp, Context, Entity, EventEmitter, SharedString, Subscription, Task, }; -use http_client::github::AssetKind; +use http_client::{HttpClient, github::AssetKind}; use node_runtime::NodeRuntime; use remote::RemoteClient; use rpc::{AnyProtoClient, TypedEnvelope, proto}; @@ -114,6 +113,7 @@ enum AgentServerStoreState { project_environment: Entity, downstream_client: Option<(u64, AnyProtoClient)>, settings: Option, + http_client: Arc, _subscriptions: [Subscription; 1], }, Remote { @@ -174,6 +174,7 @@ impl AgentServerStore { project_environment, downstream_client, settings: old_settings, + http_client, .. } = &mut self.state else { @@ -227,6 +228,8 @@ impl AgentServerStore { .codex .clone() .and_then(|settings| settings.custom_command()), + http_client: http_client.clone(), + is_remote: downstream_client.is_some(), }), ); } @@ -253,7 +256,6 @@ impl AgentServerStore { names: self .external_agents .keys() - .filter(|name| name.0 != CODEX_NAME) .map(|name| name.to_string()) .collect(), }) @@ -266,6 +268,7 @@ impl AgentServerStore { node_runtime: NodeRuntime, fs: Arc, project_environment: Entity, + http_client: Arc, cx: &mut Context, ) -> Self { let subscription = cx.observe_global::(|this, cx| { @@ -283,6 +286,7 @@ impl AgentServerStore { node_runtime, fs, project_environment, + http_client, downstream_client: None, settings: None, _subscriptions: [subscription], @@ -297,12 +301,12 @@ impl AgentServerStore { pub(crate) fn remote( project_id: u64, upstream_client: Entity, - _cx: &mut Context, + cx: &mut Context, ) -> Self { // Set up the builtin agents here so they're immediately available in // remote projects--we know that the HeadlessProject on the other end // will have them. - let external_agents = [ + let mut external_agents = [ ( GEMINI_NAME.into(), Box::new(RemoteExternalAgentServer { @@ -325,7 +329,21 @@ impl AgentServerStore { ), ] .into_iter() - .collect(); + .collect::>>(); + + use feature_flags::FeatureFlagAppExt as _; + if cx.has_flag::() { + external_agents.insert( + CODEX_NAME.into(), + Box::new(RemoteExternalAgentServer { + project_id, + upstream_client: upstream_client.clone(), + name: CODEX_NAME.into(), + status_tx: None, + new_version_available_tx: None, + }) as Box, + ); + } Self { state: AgentServerStoreState::Remote { @@ -1003,7 +1021,9 @@ impl ExternalAgentServer for LocalClaudeCode { struct LocalCodex { fs: Arc, project_environment: Entity, + http_client: Arc, custom_command: Option, + is_remote: bool, } impl ExternalAgentServer for LocalCodex { @@ -1017,11 +1037,13 @@ impl ExternalAgentServer for LocalCodex { ) -> Task)>> { let fs = self.fs.clone(); let project_environment = self.project_environment.downgrade(); + let http = self.http_client.clone(); let custom_command = self.custom_command.clone(); let root_dir: Arc = root_dir .map(|root_dir| Path::new(root_dir)) .unwrap_or(paths::home_dir()) .into(); + let is_remote = self.is_remote; cx.spawn(async move |cx| { let mut env = project_environment @@ -1030,6 +1052,9 @@ impl ExternalAgentServer for LocalCodex { })? .await .unwrap_or_default(); + if is_remote { + env.insert("NO_BROWSER".to_owned(), "1".to_owned()); + } let mut command = if let Some(mut custom_command) = custom_command { env.extend(custom_command.env.unwrap_or_default()); @@ -1040,7 +1065,6 @@ impl ExternalAgentServer for LocalCodex { fs.create_dir(&dir).await?; // Find or install the latest Codex release (no update checks for now). - let http = cx.update(|cx| Client::global(cx).http_client())?; let release = ::http_client::github::latest_github_release( CODEX_ACP_REPO, true, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 7367bd7f04450a6d26d8f4b87d5de7e1a4c84954..b303cae1ea0aa5e6215f871963af3154640b13a3 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1155,7 +1155,13 @@ impl Project { }); let agent_server_store = cx.new(|cx| { - AgentServerStore::local(node.clone(), fs.clone(), environment.clone(), cx) + AgentServerStore::local( + node.clone(), + fs.clone(), + environment.clone(), + client.http_client(), + cx, + ) }); cx.subscribe(&lsp_store, Self::on_lsp_store_event).detach(); diff --git a/crates/remote_server/src/headless_project.rs b/crates/remote_server/src/headless_project.rs index 5a767275003726da499b2ad8acf805ed41201395..be9dbca50c709accfc48dc9c33ae2cd9371b4efa 100644 --- a/crates/remote_server/src/headless_project.rs +++ b/crates/remote_server/src/headless_project.rs @@ -196,8 +196,13 @@ impl HeadlessProject { }); let agent_server_store = cx.new(|cx| { - let mut agent_server_store = - AgentServerStore::local(node_runtime.clone(), fs.clone(), environment, cx); + let mut agent_server_store = AgentServerStore::local( + node_runtime.clone(), + fs.clone(), + environment, + http_client.clone(), + cx, + ); agent_server_store.shared(REMOTE_SERVER_PROJECT_ID, session.clone(), cx); agent_server_store }); diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index 7527e3f139cecc315a90add08674d6745829d225..bd13598e3efda2f8addf3ff1685125b839c60f88 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -1792,7 +1792,7 @@ async fn test_remote_external_agent_server( .map(|name| name.to_string()) .collect::>() }); - pretty_assertions::assert_eq!(names, ["gemini", "claude"]); + pretty_assertions::assert_eq!(names, ["gemini", "codex", "claude"]); server_cx.update_global::(|settings_store, cx| { settings_store .set_server_settings( @@ -1822,7 +1822,7 @@ async fn test_remote_external_agent_server( .map(|name| name.to_string()) .collect::>() }); - pretty_assertions::assert_eq!(names, ["gemini", "foo", "claude"]); + pretty_assertions::assert_eq!(names, ["gemini", "codex", "claude", "foo"]); let (command, root, login) = project .update(cx, |project, cx| { project.agent_server_store().update(cx, |store, cx| {