Add one-shot app-server startup configuration discovery (#55300)

## What changed

Add `codex app-server --print-startup-config` to validate local and cloud-backed configuration and emit the app-server version and configuration requirements as JSON without initializing environments, thread storage, or plugins. Configuration failures produce structured JSON errors and a nonzero exit status.

Support `--startup-sign-out` to remove account credentials and reload signed-out requirements, including recovery when cloud policy is unavailable. Reject sign-out for host-owned external authentication. Accept `--startup-client-info` to identify configuration and authentication requests.

Reuse configuration loading and account cleanup logic between startup discovery and the running app server.

## Testing

Add CLI integration coverage for configuration validation, project login restrictions, managed cloud requirements and failures, sign-out recovery, external authentication protection, and independence from locked or invalid history databases.

GitOrigin-RevId: 636ccb095b684b6136cf9e408f3f8613cb776e16
This commit is contained in:
acrognale-oai
2026-10-19 15:13:44 +00:00
committed by copyberry
parent 54f99017f2
commit 1277bcfddc
10 changed files with 628 additions and 83 deletions
+19
View File
@@ -570,6 +570,9 @@ struct LogoutCommand {
#[derive(Debug, Parser)]
struct AppServerCommand {
#[command(flatten)]
startup_config: codex_app_server::StartupConfigArgs,
/// Omit to run the app server; specify a subcommand for tooling.
#[command(subcommand)]
subcommand: Option<AppServerSubcommand>,
@@ -1237,6 +1240,7 @@ async fn cli_main(
}
Some(Subcommand::AppServer(app_server_cli)) => {
let AppServerCommand {
startup_config,
subcommand,
code_mode_host,
strict_config: app_server_strict_config,
@@ -1254,6 +1258,21 @@ async fn cli_main(
root_remote_auth_token_env.as_deref(),
subcommand.as_ref(),
)?;
if startup_config.print_startup_config {
anyhow::ensure!(
subcommand.is_none(),
"--print-startup-config cannot run a subcommand"
);
return codex_app_server::print_startup_config(
arg0_paths,
root_config_overrides,
LoaderOverrides::default(),
strict_config,
startup_config,
)
.await
.map_err(Into::into);
}
match subcommand {
None => {
let transport = if stdio {