Move installation ID resolution out of core startup (#21182)

## Summary

- resolve or inject the installation ID before core startup and pass it
through `ThreadManager`, `CodexSpawnArgs`, and `Session` as a plain
`String`
- keep child sessions on the parent installation ID instead of
rediscovering it inside core
- propagate installation ID startup failures in `mcp-server` instead of
panicking

## Why

Core was still touching the filesystem on the session startup path to
discover `installation_id`. This moves that work to the outer host
boundary so core no longer depends on `codex_home` reads during session
construction.

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
jif-oai
2026-05-06 12:48:54 +02:00
committed by GitHub
parent 5d6f23a27b
commit 8f3bb355f4
20 changed files with 128 additions and 11 deletions

View File

@@ -83,6 +83,7 @@ use codex_config::LoaderOverrides;
use codex_config::ThreadConfigLoader;
use codex_core::config::Config;
use codex_core::init_state_db_from_config;
use codex_core::resolve_installation_id;
use codex_exec_server::EnvironmentManager;
use codex_feedback::CodexFeedback;
use codex_login::AuthManager;
@@ -345,7 +346,7 @@ impl InProcessClientHandle {
/// the runtime is shut down and an `InvalidData` error is returned.
pub async fn start(args: InProcessStartArgs) -> IoResult<InProcessClientHandle> {
let initialize = args.initialize.clone();
let client = start_uninitialized(args).await;
let client = start_uninitialized(args).await?;
let initialize_response = client
.request(ClientRequest::Initialize {
@@ -365,12 +366,13 @@ pub async fn start(args: InProcessStartArgs) -> IoResult<InProcessClientHandle>
Ok(client)
}
async fn start_uninitialized(args: InProcessStartArgs) -> InProcessClientHandle {
async fn start_uninitialized(args: InProcessStartArgs) -> IoResult<InProcessClientHandle> {
let channel_capacity = args.channel_capacity.max(1);
let state_db = match args.state_db.clone() {
Some(state_db) => Some(state_db),
None => init_state_db_from_config(args.config.as_ref()).await,
};
let installation_id = resolve_installation_id(&args.config.codex_home).await?;
let (client_tx, mut client_rx) = mpsc::channel::<InProcessClientMessage>(channel_capacity);
let (event_tx, event_rx) = mpsc::channel::<InProcessServerEvent>(channel_capacity);
@@ -438,6 +440,7 @@ async fn start_uninitialized(args: InProcessStartArgs) -> InProcessClientHandle
config_warnings: args.config_warnings,
session_source: args.session_source,
auth_manager,
installation_id,
rpc_transport: AppServerRpcTransport::InProcess,
remote_control_handle: None,
plugin_startup_tasks: crate::PluginStartupTasks::Start,
@@ -718,13 +721,13 @@ async fn start_uninitialized(args: InProcessStartArgs) -> InProcessClientHandle
}
});
InProcessClientHandle {
Ok(InProcessClientHandle {
client: InProcessClientSender { client_tx },
event_rx,
runtime_handle,
#[cfg(test)]
_test_codex_home: None,
}
})
}
#[cfg(test)]

View File

@@ -7,6 +7,7 @@ use codex_config::NoopThreadConfigLoader;
use codex_config::RemoteThreadConfigLoader;
use codex_config::ThreadConfigLoader;
use codex_core::config::Config;
use codex_core::resolve_installation_id;
use codex_exec_server::EnvironmentManagerArgs;
use codex_features::Feature;
use codex_login::AuthManager;
@@ -621,6 +622,7 @@ pub async fn run_main_with_transport_options(
None => error!("{}", warning.summary),
}
}
let installation_id = resolve_installation_id(&config.codex_home).await?;
let transport_shutdown_token = CancellationToken::new();
let mut transport_accept_handles = Vec::<JoinHandle<()>>::new();
@@ -764,6 +766,7 @@ pub async fn run_main_with_transport_options(
config_warnings,
session_source,
auth_manager,
installation_id,
rpc_transport: analytics_rpc_transport(&transport),
remote_control_handle: Some(remote_control_handle.clone()),
plugin_startup_tasks: runtime_options.plugin_startup_tasks,

View File

@@ -189,6 +189,7 @@ mod tests {
state_db,
thread_store,
agent_graph_store,
"11111111-1111-4111-8111-111111111111".to_string(),
));
thread_manager.start_thread(good_config).await?;
thread_manager.start_thread(bad_config).await?;

View File

@@ -259,6 +259,7 @@ pub(crate) struct MessageProcessorArgs {
pub(crate) config_warnings: Vec<ConfigWarningNotification>,
pub(crate) session_source: SessionSource,
pub(crate) auth_manager: Arc<AuthManager>,
pub(crate) installation_id: String,
pub(crate) rpc_transport: AppServerRpcTransport,
pub(crate) remote_control_handle: Option<RemoteControlHandle>,
pub(crate) plugin_startup_tasks: crate::PluginStartupTasks,
@@ -281,6 +282,7 @@ impl MessageProcessor {
config_warnings,
session_source,
auth_manager,
installation_id,
rpc_transport,
remote_control_handle,
plugin_startup_tasks,
@@ -302,6 +304,7 @@ impl MessageProcessor {
state_db.clone(),
Arc::clone(&thread_store),
agent_graph_store.clone(),
installation_id,
));
thread_manager
.plugins_manager()

View File

@@ -298,6 +298,7 @@ async fn build_test_processor(
config_warnings: Vec::new(),
session_source: SessionSource::VSCode,
auth_manager,
installation_id: "11111111-1111-4111-8111-111111111111".to_string(),
rpc_transport: AppServerRpcTransport::Stdio,
remote_control_handle: None,
plugin_startup_tasks: crate::PluginStartupTasks::Start,