Provide codex as an option on remote sessions (#39774)
Release Notes: - N/A --------- Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
co-authored by
Cole Miller
parent
f1d17fcfbe
commit
dd5da592f0
@@ -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<ProjectEnvironment>,
|
||||
downstream_client: Option<(u64, AnyProtoClient)>,
|
||||
settings: Option<AllAgentServersSettings>,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
_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<dyn Fs>,
|
||||
project_environment: Entity<ProjectEnvironment>,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let subscription = cx.observe_global::<SettingsStore>(|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<RemoteClient>,
|
||||
_cx: &mut Context<Self>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> 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::<HashMap<ExternalAgentServerName, Box<dyn ExternalAgentServer>>>();
|
||||
|
||||
use feature_flags::FeatureFlagAppExt as _;
|
||||
if cx.has_flag::<feature_flags::CodexAcpFeatureFlag>() {
|
||||
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<dyn ExternalAgentServer>,
|
||||
);
|
||||
}
|
||||
|
||||
Self {
|
||||
state: AgentServerStoreState::Remote {
|
||||
@@ -1003,7 +1021,9 @@ impl ExternalAgentServer for LocalClaudeCode {
|
||||
struct LocalCodex {
|
||||
fs: Arc<dyn Fs>,
|
||||
project_environment: Entity<ProjectEnvironment>,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
custom_command: Option<AgentServerCommand>,
|
||||
is_remote: bool,
|
||||
}
|
||||
|
||||
impl ExternalAgentServer for LocalCodex {
|
||||
@@ -1017,11 +1037,13 @@ impl ExternalAgentServer for LocalCodex {
|
||||
) -> Task<Result<(AgentServerCommand, String, Option<task::SpawnInTerminal>)>> {
|
||||
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<Path> = 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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -1792,7 +1792,7 @@ async fn test_remote_external_agent_server(
|
||||
.map(|name| name.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
pretty_assertions::assert_eq!(names, ["gemini", "claude"]);
|
||||
pretty_assertions::assert_eq!(names, ["gemini", "codex", "claude"]);
|
||||
server_cx.update_global::<SettingsStore, _>(|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::<Vec<_>>()
|
||||
});
|
||||
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| {
|
||||
|
||||
Reference in New Issue
Block a user