mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
## Why `codex app-server daemon restart` previously reused saved settings without applying feature flags supplied on the command line. ## What changed Apply `--enable`, `--disable`, and boolean `-c features.*` overrides during an explicit restart and persist them for subsequent restarts. Accept nested `enabled` values, normalize feature aliases, and replace conflicting saved aliases while preserving unrelated settings. Reject invalid feature toggles before stopping the daemon or saving settings. ## Testing Add integration coverage for overrides on stopped and running daemons, alias replacement, preservation of saved settings, restarts without flags, and rejection of non-toggle keys without interrupting the running daemon. GitOrigin-RevId: 14a657bc4758b9c248e363f9dac58f8887070a04
75 lines
3.1 KiB
Rust
75 lines
3.1 KiB
Rust
//! Invocation overrides apply on fresh starts or explicitly confirmed managed restarts.
|
|
//! The lifecycle lock serializes persistence against other clients and updates.
|
|
|
|
use crate::Daemon;
|
|
use crate::LifecycleOutput;
|
|
use crate::ensure_supported_platform;
|
|
use anyhow::Result;
|
|
use anyhow::ensure;
|
|
use std::collections::BTreeMap;
|
|
|
|
/// Start a missing daemon with these features, preserving other saved overrides,
|
|
/// or leave a running daemon unchanged.
|
|
/// Callers must check the running server's configuration before using it.
|
|
/// Startup diagnostics go to tracing, so a caller with a live TUI can keep rendering.
|
|
pub async fn start_with_features(features: &BTreeMap<String, bool>) -> Result<LifecycleOutput> {
|
|
ensure_supported_platform()?;
|
|
#[cfg(windows)]
|
|
crate::backend::windows::ensure_not_elevated()?;
|
|
let mut daemon = Daemon::from_environment()?;
|
|
daemon.log_diagnostics = true;
|
|
let _operation_lock = daemon.acquire_operation_lock().await?;
|
|
let selected = daemon.current_installation()?;
|
|
let mut overrides = selected.load_settings().await?.feature_overrides;
|
|
overrides.extend(features.clone());
|
|
Box::pin(selected.start(&overrides)).await
|
|
}
|
|
|
|
/// Apply confirmed feature settings to an existing managed daemon and restart it.
|
|
/// Callers must obtain consent for changes to shared services and interrupted work,
|
|
/// then verify effective server compatibility after this operation completes.
|
|
pub async fn restart_with_features(features: &BTreeMap<String, bool>) -> Result<LifecycleOutput> {
|
|
ensure_supported_platform()?;
|
|
#[cfg(windows)]
|
|
crate::backend::windows::ensure_not_elevated()?;
|
|
let daemon = Daemon::from_environment()?;
|
|
let _operation_lock = daemon.acquire_operation_lock().await?;
|
|
let selected = daemon.current_installation()?;
|
|
Box::pin(selected.restart_with_features_locked(features)).await
|
|
}
|
|
|
|
impl Daemon {
|
|
pub(super) async fn restart(
|
|
&self,
|
|
features: &BTreeMap<String, bool>,
|
|
) -> Result<LifecycleOutput> {
|
|
let mut settings = self.load_settings().await?;
|
|
// Explicit requests replace saved aliases as well as canonical keys.
|
|
settings.feature_overrides.retain(|name, _| {
|
|
let canonical = codex_features::feature_for_key(name)
|
|
.map(codex_features::Feature::key)
|
|
.unwrap_or(name);
|
|
!features.contains_key(canonical)
|
|
});
|
|
settings.feature_overrides.extend(features.clone());
|
|
self.restart_with_settings(settings).await
|
|
}
|
|
|
|
pub(super) async fn restart_with_features_locked(
|
|
&self,
|
|
features: &BTreeMap<String, bool>,
|
|
) -> Result<LifecycleOutput> {
|
|
let mut settings = self.load_settings().await?;
|
|
ensure!(
|
|
self.running_backend_instance(&settings).await?.is_some(),
|
|
"no running managed daemon; rerun the command to check the current server"
|
|
);
|
|
let previous = settings.feature_overrides.clone();
|
|
settings.feature_overrides.extend(features.clone());
|
|
if settings.feature_overrides == previous {
|
|
return self.start(&previous).await;
|
|
}
|
|
self.restart_with_settings(settings).await
|
|
}
|
|
}
|