mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
## What changed Add a `failure_reason` tag to failed TUI auto-start events in `codex.daemon.start`, distinguishing `install`, `spawn`, `early_child_exit`, `readiness_timeout`, and `other` failures. Preserve the original error diagnostics through a classified startup API. Detect managed child exits during process identity recording and distinguish exits before readiness from readiness timeouts. ## Testing Extend daemon tests to assert classification of installation failures, spawn failures, early child exits, and readiness timeouts. GitOrigin-RevId: 7c626f278e9e7f2ecd61b3fd1a90829a113eb232
85 lines
3.5 KiB
Rust
85 lines
3.5 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 crate::telemetry::StartError;
|
|
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> {
|
|
start_with_features_classified(features)
|
|
.await
|
|
.map_err(|err| err.error)
|
|
}
|
|
|
|
/// Starts the daemon and classifies failures for the TUI startup counter.
|
|
pub async fn start_with_features_classified(
|
|
features: &BTreeMap<String, bool>,
|
|
) -> Result<LifecycleOutput, StartError> {
|
|
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.map_err(|err| err.error);
|
|
}
|
|
self.restart_with_settings(settings).await
|
|
}
|
|
}
|