mirror of
https://github.com/openai/codex.git
synced 2026-10-20 00:18:49 +00:00
Use the managed daemon for eligible remote-control launches (#50803)
## What changed Make plain `codex remote-control` start or reuse the managed daemon and enable remote control when daemon auto-start is enabled and the environment is eligible. Fall back to the foreground server when no managed backend is available or Windows restricts detached launch. Add `codex remote-control --no-daemon` to explicitly run the foreground server, and honor the top-level `--no-daemon` flag. Reject this flag with `start`, `stop`, or `pair`. Keep `--json` and launches with configuration overrides or unsupported environments on the foreground path. GitOrigin-RevId: cb28ae3f6074993b748660972c3cb7cbf6612c2f
This commit is contained in:
@@ -169,9 +169,10 @@ so the new setting takes effect immediately.
|
||||
|
||||
Top-level `codex remote-control start` enables and persists remote control for
|
||||
the managed daemon, overriding a saved disabled value. It starts or bootstraps
|
||||
the daemon as needed. Plain `codex remote-control` runs a separate foreground
|
||||
server and does not change daemon settings; `codex remote-control stop` stops
|
||||
the managed daemon without clearing its saved remote-control preference.
|
||||
the daemon as needed. Plain `codex remote-control` uses the managed daemon when
|
||||
eligible; `codex remote-control --no-daemon` runs a separate foreground server.
|
||||
`codex remote-control stop` stops the managed daemon without clearing its saved
|
||||
remote-control preference.
|
||||
`daemon start` and `daemon restart` use that saved preference. `daemon bootstrap`
|
||||
sets it according to `--remote-control` (disabled when omitted).
|
||||
|
||||
|
||||
@@ -1429,7 +1429,8 @@ async fn cli_main(
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Subcommand::RemoteControl(remote_control_cli)) => {
|
||||
Some(Subcommand::RemoteControl(mut remote_control_cli)) => {
|
||||
remote_control_cli.no_daemon |= interactive.no_daemon;
|
||||
let subcommand_name = remote_control_cli.subcommand_name();
|
||||
reject_remote_mode_for_subcommand(
|
||||
root_remote.as_deref(),
|
||||
|
||||
@@ -15,6 +15,8 @@ use codex_app_server_protocol::RemoteControlConnectionStatus;
|
||||
use codex_app_server_protocol::RemoteControlPairingStartResponse;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_config::LoaderOverrides;
|
||||
use codex_core::config::ConfigBuilder;
|
||||
use codex_features::Feature;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_cli::CliConfigOverrides;
|
||||
@@ -34,8 +36,12 @@ pub(crate) struct RemoteControlCommand {
|
||||
#[arg(long = "json", global = true)]
|
||||
json: bool,
|
||||
|
||||
/// Run an embedded app-server in the foreground until Ctrl-C.
|
||||
#[arg(long = "no-daemon")]
|
||||
pub(super) no_daemon: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
subcommand: Option<RemoteControlSubcommand>,
|
||||
pub(super) subcommand: Option<RemoteControlSubcommand>,
|
||||
}
|
||||
|
||||
impl RemoteControlCommand {
|
||||
@@ -50,7 +56,7 @@ impl RemoteControlCommand {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, clap::Subcommand)]
|
||||
enum RemoteControlSubcommand {
|
||||
pub(super) enum RemoteControlSubcommand {
|
||||
/// Start the app-server daemon with remote control enabled.
|
||||
Start,
|
||||
|
||||
@@ -66,14 +72,57 @@ pub(crate) async fn run(
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
root_config_overrides: CliConfigOverrides,
|
||||
) -> anyhow::Result<()> {
|
||||
match command.subcommand {
|
||||
None => {
|
||||
if command.no_daemon && command.subcommand.is_some() {
|
||||
anyhow::bail!("`--no-daemon` cannot be used with a remote-control subcommand");
|
||||
}
|
||||
|
||||
if command.subcommand.is_none() {
|
||||
if command.no_daemon || command.json || !daemon_eligible(&root_config_overrides).await? {
|
||||
run_foreground_remote_control(command.json, arg0_paths, root_config_overrides).await?;
|
||||
} else {
|
||||
print_remote_control_progress(
|
||||
command.json,
|
||||
"Starting app-server with remote control enabled...",
|
||||
"Starting app-server daemon with remote control enabled...",
|
||||
)?;
|
||||
run_foreground_remote_control(command.json, arg0_paths, root_config_overrides).await?;
|
||||
let daemon = match codex_app_server_daemon::start_with_features(&Default::default())
|
||||
.await
|
||||
{
|
||||
Ok(daemon) => daemon,
|
||||
#[cfg(windows)]
|
||||
Err(error) if error.is::<codex_app_server_daemon::DetachedLaunchRestricted>() => {
|
||||
return run_foreground_remote_control(
|
||||
command.json,
|
||||
arg0_paths,
|
||||
root_config_overrides,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
if daemon.backend.is_none() {
|
||||
return run_foreground_remote_control(
|
||||
command.json,
|
||||
arg0_paths,
|
||||
root_config_overrides,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
let remote_control = codex_app_server_daemon::enable_remote_control_on_socket(
|
||||
&daemon.socket_path,
|
||||
FOREGROUND_SOCKET_CONNECT_TIMEOUT,
|
||||
FOREGROUND_SOCKET_CONNECT_RETRY_DELAY,
|
||||
)
|
||||
.await?;
|
||||
let output = AppServerRemoteControlReadyOutput {
|
||||
daemon: AppServerRemoteControlStartOutput::Start(daemon),
|
||||
remote_control,
|
||||
};
|
||||
print_remote_control_start_output(&output, command.json)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match command.subcommand {
|
||||
Some(RemoteControlSubcommand::Start) => {
|
||||
print_remote_control_progress(
|
||||
command.json,
|
||||
@@ -91,10 +140,31 @@ pub(crate) async fn run(
|
||||
let output = codex_app_server_daemon::start_remote_control_pairing().await?;
|
||||
print_remote_control_pairing_output(&output, command.json)?;
|
||||
}
|
||||
None => unreachable!("bare remote-control returned before explicit subcommand dispatch"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn daemon_eligible(root_config_overrides: &CliConfigOverrides) -> anyhow::Result<bool> {
|
||||
if !root_config_overrides.raw_overrides.is_empty()
|
||||
|| codex_login::is_workload_identity_selected()
|
||||
|| std::env::var_os(codex_exec_server::CODEX_EXEC_SERVER_URL_ENV_VAR).is_some()
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
if codex_app_server_daemon::is_elevated()? {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let Ok(config) = ConfigBuilder::default().build().await else {
|
||||
return Ok(false);
|
||||
};
|
||||
Ok(config.features.enabled(Feature::DaemonAutoStart)
|
||||
&& !codex_tui::uses_wsl_drvfs(&config.codex_home))
|
||||
}
|
||||
|
||||
fn print_remote_control_progress(json: bool, message: &str) -> anyhow::Result<()> {
|
||||
if json {
|
||||
return Ok(());
|
||||
@@ -112,6 +182,7 @@ async fn run_foreground_remote_control(
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
root_config_overrides: CliConfigOverrides,
|
||||
) -> anyhow::Result<()> {
|
||||
print_remote_control_progress(json, "Starting app-server with remote control enabled...")?;
|
||||
#[cfg(not(windows))]
|
||||
let socket_dir = tempfile::Builder::new()
|
||||
.prefix("codex-rc-")
|
||||
|
||||
@@ -17,7 +17,8 @@ const SERVER_FEATURES: [Feature; 4] = [
|
||||
pub(super) const FAILURE_HINT: &str = "To work without the background server, rerun the same command with --no-daemon (including resume or fork and its arguments).";
|
||||
pub(super) const WSL_DRVFS_EXCLUSION: &str = "a Windows-mounted WSL CODEX_HOME (DrvFS/9p)";
|
||||
|
||||
pub(super) fn uses_wsl_drvfs(codex_home: &std::path::Path) -> bool {
|
||||
/// Returns whether `codex_home` is on a Windows-mounted WSL filesystem.
|
||||
pub fn uses_wsl_drvfs(codex_home: &std::path::Path) -> bool {
|
||||
// The managed daemon writes an executable and Unix-style state beneath CODEX_HOME.
|
||||
// DrvFS does not reliably support the required permission semantics, so starting it
|
||||
// there can fail before the TUI opens.
|
||||
|
||||
@@ -75,6 +75,7 @@ use codex_utils_oss::get_default_model_for_oss_provider;
|
||||
use color_eyre::eyre::WrapErr;
|
||||
use crossterm::SynchronizedUpdate;
|
||||
use cwd_prompt::CwdPromptAction;
|
||||
pub use daemon_startup::uses_wsl_drvfs;
|
||||
pub use session_archive_commands::DeleteConfirmation;
|
||||
pub use session_archive_commands::SessionArchiveAction;
|
||||
pub use session_archive_commands::SessionArchiveCommandOptions;
|
||||
|
||||
Reference in New Issue
Block a user