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
Unverified
parent 5d6f23a27b
commit 8f3bb355f4
20 changed files with 128 additions and 11 deletions
+7 -4
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)]
+3
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,
+1
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?;
@@ -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()
@@ -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,
+1
View File
@@ -42,6 +42,7 @@ pub use codex_core::config::ThreadStoreConfig;
pub use codex_core::config::find_codex_home;
pub use codex_core::init_state_db;
pub use codex_core::init_state_db_from_config;
pub use codex_core::resolve_installation_id;
pub use codex_core::skills::SkillsManager;
pub use codex_core::thread_store_from_config;
pub use codex_exec_server::EnvironmentManager;
+1
View File
@@ -76,6 +76,7 @@ pub(crate) async fn run_codex_thread_interactive(
let (tx_ops, rx_ops) = async_channel::bounded(SUBMISSION_CHANNEL_CAPACITY);
let CodexSpawnOk { codex, .. } = Box::pin(Codex::spawn(CodexSpawnArgs {
config,
installation_id: parent_session.installation_id.clone(),
auth_manager,
models_manager,
environment_manager: Arc::clone(&parent_session.services.environment_manager),
+3
View File
@@ -13,6 +13,7 @@ use codex_protocol::user_input::UserInput;
use tokio_util::sync::CancellationToken;
use crate::config::Config;
use crate::resolve_installation_id;
use crate::session::session::Session;
use crate::session::turn::build_prompt;
use crate::session::turn::built_tools;
@@ -42,6 +43,7 @@ pub async fn build_prompt_input(
.ok_or_else(|| std::io::Error::other("prompt debug requires state db"))?;
let thread_store = thread_store_from_config(&config, state_db.clone());
let agent_graph_store = agent_graph_store_from_state_db(state_db.clone());
let installation_id = resolve_installation_id(&config.codex_home).await?;
let thread_manager = ThreadManager::new(
&config,
Arc::clone(&auth_manager),
@@ -51,6 +53,7 @@ pub async fn build_prompt_input(
state_db,
thread_store,
agent_graph_store,
installation_id,
);
let thread = thread_manager.start_thread(config).await?;
+3 -1
View File
@@ -32,7 +32,6 @@ use crate::context::PersonalitySpecInstructions;
use crate::default_skill_metadata_budget;
use crate::environment_selection::ResolvedTurnEnvironments;
use crate::exec_policy::ExecPolicyManager;
use crate::installation_id::resolve_installation_id;
use crate::parse_turn_item;
use crate::path_utils::normalize_for_native_workdir;
use crate::realtime_conversation::RealtimeConversationManager;
@@ -384,6 +383,7 @@ pub struct CodexSpawnOk {
pub(crate) struct CodexSpawnArgs {
pub(crate) config: Config,
pub(crate) installation_id: String,
pub(crate) auth_manager: Arc<AuthManager>,
pub(crate) models_manager: SharedModelsManager,
pub(crate) environment_manager: Arc<EnvironmentManager>,
@@ -447,6 +447,7 @@ impl Codex {
async fn spawn_internal(args: CodexSpawnArgs) -> CodexResult<CodexSpawnOk> {
let CodexSpawnArgs {
mut config,
installation_id,
auth_manager,
models_manager,
environment_manager,
@@ -630,6 +631,7 @@ impl Codex {
let session = Session::new(
session_configuration,
config.clone(),
installation_id,
auth_manager.clone(),
models_manager.clone(),
exec_policy,
+4 -2
View File
@@ -12,6 +12,7 @@ use tokio::sync::Semaphore;
/// A session has at most 1 running task at a time, and can be interrupted by user input.
pub(crate) struct Session {
pub(crate) conversation_id: ThreadId,
pub(crate) installation_id: String,
pub(super) tx_event: Sender<Event>,
pub(super) agent_status: watch::Sender<AgentStatus>,
pub(super) out_of_band_elicitation_paused: watch::Sender<bool>,
@@ -344,6 +345,7 @@ impl Session {
pub(crate) async fn new(
mut session_configuration: SessionConfiguration,
config: Arc<Config>,
installation_id: String,
auth_manager: Arc<AuthManager>,
models_manager: SharedModelsManager,
exec_policy: Arc<ExecPolicyManager>,
@@ -789,7 +791,6 @@ impl Session {
});
}
let installation_id = resolve_installation_id(&config.codex_home).await?;
let analytics_events_client = analytics_events_client.unwrap_or_else(|| {
AnalyticsEventsClient::new(
Arc::clone(&auth_manager),
@@ -849,7 +850,7 @@ impl Session {
Some(Arc::clone(&auth_manager)),
session_id,
thread_id,
installation_id,
installation_id.clone(),
session_configuration.provider.clone(),
session_configuration.session_source.clone(),
config.model_verbosity,
@@ -869,6 +870,7 @@ impl Session {
let (mailbox, mailbox_rx) = Mailbox::new();
let sess = Arc::new(Session {
conversation_id: thread_id,
installation_id,
tx_event: tx_event.clone(),
agent_status,
out_of_band_elicitation_paused,
+5
View File
@@ -3566,6 +3566,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_zsh_path() {
let result = Session::new(
session_configuration,
Arc::clone(&config),
"11111111-1111-4111-8111-111111111111".to_string(),
auth_manager,
models_manager,
Arc::new(ExecPolicyManager::default()),
@@ -3799,6 +3800,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
let (mailbox, mailbox_rx) = crate::agent::Mailbox::new();
let session = Session {
conversation_id: thread_id,
installation_id: "11111111-1111-4111-8111-111111111111".to_string(),
tx_event,
agent_status: agent_status_tx,
out_of_band_elicitation_paused: watch::channel(false).0,
@@ -3905,6 +3907,7 @@ async fn make_session_with_config_and_rx(
let session = Session::new(
session_configuration,
Arc::clone(&config),
"11111111-1111-4111-8111-111111111111".to_string(),
auth_manager,
models_manager,
Arc::new(ExecPolicyManager::default()),
@@ -4012,6 +4015,7 @@ async fn make_session_with_history_source_and_agent_control_and_rx(
let session = Session::new(
session_configuration,
Arc::clone(&config),
"11111111-1111-4111-8111-111111111111".to_string(),
auth_manager,
models_manager,
Arc::new(ExecPolicyManager::default()),
@@ -5482,6 +5486,7 @@ where
let (mailbox, mailbox_rx) = crate::agent::Mailbox::new();
let session = Arc::new(Session {
conversation_id: thread_id,
installation_id: "11111111-1111-4111-8111-111111111111".to_string(),
tx_event,
agent_status: agent_status_tx,
out_of_band_elicitation_paused: watch::channel(false).0,
@@ -741,6 +741,7 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() {
let CodexSpawnOk { codex, .. } = Codex::spawn(CodexSpawnArgs {
config,
installation_id: "11111111-1111-4111-8111-111111111111".to_string(),
auth_manager,
models_manager,
environment_manager: Arc::new(EnvironmentManager::default_for_tests()),
+26 -4
View File
@@ -7,6 +7,7 @@ use crate::environment_selection::default_thread_environment_selections;
use crate::environment_selection::resolve_environment_selections;
use crate::file_watcher::FileWatcher;
use crate::mcp::McpManager;
use crate::resolve_installation_id;
use crate::rollout::RolloutRecorder;
use crate::rollout::truncation;
use crate::session::Codex;
@@ -253,6 +254,7 @@ pub(crate) struct ThreadManagerState {
state_db: StateDbHandle,
agent_graph_store: Arc<dyn AgentGraphStore>,
session_source: SessionSource,
installation_id: String,
analytics_events_client: Option<AnalyticsEventsClient>,
// Captures submitted ops for testing purpose when test mode is enabled.
ops_log: Option<SharedCapturedOps>,
@@ -316,6 +318,7 @@ impl ThreadManager {
state_db: StateDbHandle,
thread_store: Arc<dyn ThreadStore>,
agent_graph_store: Arc<dyn AgentGraphStore>,
installation_id: String,
) -> Self {
let codex_home = config.codex_home.clone();
let restriction_product = session_source.restriction_product();
@@ -346,6 +349,7 @@ impl ThreadManager {
agent_graph_store,
auth_manager,
session_source,
installation_id,
analytics_events_client,
ops_log: should_use_test_thread_manager_behavior()
.then(|| Arc::new(std::sync::Mutex::new(Vec::new()))),
@@ -373,12 +377,21 @@ impl ThreadManager {
OPENAI_PROVIDER_ID.to_string(),
)
.await;
let skills_codex_home = match AbsolutePathBuf::from_absolute_path_checked(&codex_home) {
Ok(codex_home) => codex_home,
Err(err) => panic!("test codex_home should be absolute: {err}"),
};
let installation_id = resolve_installation_id(&skills_codex_home)
.await
.unwrap_or_else(|err| panic!("resolve test installation id failed: {err}"));
let mut manager = Self::with_models_provider_and_home_and_state_db_for_tests(
auth,
provider,
codex_home.clone(),
Arc::new(EnvironmentManager::default_for_tests()),
state_db,
skills_codex_home,
installation_id,
);
manager._test_codex_home_guard = Some(TempCodexHomeGuard { path: codex_home });
manager
@@ -398,12 +411,21 @@ impl ThreadManager {
OPENAI_PROVIDER_ID.to_string(),
)
.await;
let skills_codex_home = match AbsolutePathBuf::from_absolute_path_checked(&codex_home) {
Ok(codex_home) => codex_home,
Err(err) => panic!("test codex_home should be absolute: {err}"),
};
let installation_id = resolve_installation_id(&skills_codex_home)
.await
.unwrap_or_else(|err| panic!("resolve test installation id failed: {err}"));
Self::with_models_provider_and_home_and_state_db_for_tests(
auth,
provider,
codex_home,
environment_manager,
state_db,
skills_codex_home,
installation_id,
)
}
@@ -413,13 +435,11 @@ impl ThreadManager {
codex_home: PathBuf,
environment_manager: Arc<EnvironmentManager>,
state_db: StateDbHandle,
skills_codex_home: AbsolutePathBuf,
installation_id: String,
) -> Self {
set_thread_manager_test_mode_for_tests(/*enabled*/ true);
let auth_manager = AuthManager::from_auth_for_testing(auth);
let skills_codex_home = match AbsolutePathBuf::from_absolute_path_checked(&codex_home) {
Ok(codex_home) => codex_home,
Err(err) => panic!("test codex_home should be absolute: {err}"),
};
let (thread_created_tx, _) = broadcast::channel(THREAD_CREATED_CHANNEL_CAPACITY);
let restriction_product = SessionSource::Exec.restriction_product();
let plugins_manager = Arc::new(PluginsManager::new_with_restriction_product(
@@ -459,6 +479,7 @@ impl ThreadManager {
agent_graph_store,
auth_manager,
session_source: SessionSource::Exec,
installation_id,
analytics_events_client: None,
ops_log: should_use_test_thread_manager_behavior()
.then(|| Arc::new(std::sync::Mutex::new(Vec::new()))),
@@ -1199,6 +1220,7 @@ impl ThreadManagerState {
codex, thread_id, ..
} = Codex::spawn(CodexSpawnArgs {
config,
installation_id: self.installation_id.clone(),
auth_manager,
models_manager: Arc::clone(&self.models_manager),
environment_manager: Arc::clone(&self.environment_manager),
+52
View File
@@ -1,5 +1,6 @@
use super::*;
use crate::config::test_config;
use crate::installation_id::INSTALLATION_ID_FILENAME;
use crate::rollout::RolloutRecorder;
use crate::session::session::SessionSettingsUpdate;
use crate::session::tests::make_session_and_context;
@@ -26,6 +27,8 @@ use std::time::Duration;
use tempfile::tempdir;
use wiremock::MockServer;
const TEST_INSTALLATION_ID: &str = "11111111-1111-4111-8111-111111111111";
fn user_msg(text: &str) -> ResponseItem {
ResponseItem::Message {
id: None,
@@ -415,6 +418,7 @@ async fn resume_and_fork_do_not_restore_thread_environments_from_rollout() {
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let selected_cwd =
AbsolutePathBuf::try_from(config.cwd.as_path().join("selected")).expect("absolute path");
@@ -509,6 +513,46 @@ async fn resume_and_fork_do_not_restore_thread_environments_from_rollout() {
);
}
#[tokio::test]
async fn explicit_installation_id_skips_codex_home_file() {
let temp_dir = tempdir().expect("tempdir");
let mut config = test_config().await;
config.codex_home = temp_dir.path().join("codex-home").abs();
config.cwd = config.codex_home.abs();
std::fs::create_dir_all(&config.codex_home).expect("create codex home");
let auth_manager =
AuthManager::from_auth_for_testing(CodexAuth::create_dummy_chatgpt_auth_for_testing());
let installation_id = uuid::Uuid::new_v4().to_string();
let (state_db, thread_store, agent_graph_store) = state_backed_stores(&config).await;
let manager = ThreadManager::new(
&config,
auth_manager,
SessionSource::Exec,
Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()),
/*analytics_events_client*/ None,
state_db,
thread_store,
agent_graph_store,
installation_id.clone(),
);
let thread = manager
.start_thread(config.clone())
.await
.expect("start thread with explicit installation id");
assert!(!config.codex_home.join(INSTALLATION_ID_FILENAME).exists());
assert_eq!(thread.thread.codex.session.installation_id, installation_id);
thread
.thread
.shutdown_and_wait()
.await
.expect("shutdown thread");
let _ = manager.remove_thread(&thread.thread_id).await;
}
#[tokio::test]
async fn resume_active_thread_from_rollout_returns_running_thread() {
let temp_dir = tempdir().expect("tempdir");
@@ -529,6 +573,7 @@ async fn resume_active_thread_from_rollout_returns_running_thread() {
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let source = manager
@@ -585,6 +630,7 @@ async fn resume_stopped_thread_from_rollout_spawns_new_thread() {
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let source = manager
@@ -646,6 +692,7 @@ async fn resume_stopped_thread_from_rollout_preserves_thread_source() {
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let source = manager
@@ -731,6 +778,7 @@ async fn new_uses_active_provider_for_model_refresh() {
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let _ = manager.list_models(RefreshStrategy::Online).await;
@@ -945,6 +993,7 @@ async fn interrupted_fork_snapshot_does_not_synthesize_turn_id_for_legacy_histor
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let source = manager
@@ -1051,6 +1100,7 @@ async fn interrupted_fork_snapshot_preserves_explicit_turn_id() {
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let source = manager
@@ -1146,6 +1196,7 @@ async fn interrupted_fork_snapshot_uses_persisted_mid_turn_history_without_live_
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let source = manager
@@ -1287,6 +1338,7 @@ async fn resumed_thread_keeps_paused_goal_paused() -> anyhow::Result<()> {
state_db,
thread_store,
agent_graph_store,
TEST_INSTALLATION_ID.to_string(),
);
let source = manager
@@ -3171,6 +3171,7 @@ async fn tool_handlers_cascade_close_and_resume_and_keep_explicitly_closed_subtr
state_db.clone(),
thread_store_from_config(&config, state_db.clone()),
agent_graph_store_from_state_db(state_db.clone()),
"11111111-1111-4111-8111-111111111111".to_string(),
);
let parent = manager
+3
View File
@@ -18,6 +18,7 @@ use codex_core::ThreadManager;
use codex_core::agent_graph_store_from_state_db;
use codex_core::config::Config;
use codex_core::init_state_db_from_config;
use codex_core::resolve_installation_id;
use codex_core::shell::Shell;
use codex_core::shell::get_shell_by_model_provided_path;
use codex_core::thread_store_from_config;
@@ -431,6 +432,7 @@ impl TestCodexBuilder {
.expect("test codex requires state db");
let thread_store = thread_store_from_config(&config, state_db.clone());
let agent_graph_store = agent_graph_store_from_state_db(state_db.clone());
let installation_id = resolve_installation_id(&config.codex_home).await?;
ThreadManager::new(
&config,
codex_core::test_support::auth_manager_from_auth(auth.clone()),
@@ -440,6 +442,7 @@ impl TestCodexBuilder {
state_db,
thread_store,
agent_graph_store,
installation_id,
)
} else {
codex_core::test_support::thread_manager_with_models_provider_and_home(
+5
View File
@@ -7,6 +7,7 @@ use codex_core::ResponseEvent;
use codex_core::ThreadManager;
use codex_core::agent_graph_store_from_state_db;
use codex_core::init_state_db_from_config;
use codex_core::resolve_installation_id;
use codex_core::thread_store_from_config;
use codex_features::Feature;
use codex_login::AuthManager;
@@ -1120,6 +1121,9 @@ async fn prefers_apikey_when_config_prefers_apikey_even_with_chatgpt_tokens() {
.expect("client test requires state db");
let thread_store = thread_store_from_config(&config, state_db.clone());
let agent_graph_store = agent_graph_store_from_state_db(state_db.clone());
let installation_id = resolve_installation_id(&config.codex_home)
.await
.expect("resolve installation id");
let thread_manager = ThreadManager::new(
&config,
auth_manager,
@@ -1129,6 +1133,7 @@ async fn prefers_apikey_when_config_prefers_apikey_even_with_chatgpt_tokens() {
state_db,
thread_store,
agent_graph_store,
installation_id,
);
let NewThread { thread: codex, .. } = thread_manager
.start_thread(config.clone())
+3
View File
@@ -7,6 +7,7 @@ use std::sync::Arc;
use codex_arg0::Arg0DispatchPaths;
use codex_core::config::Config;
use codex_core::resolve_installation_id;
use codex_exec_server::EnvironmentManager;
use codex_exec_server::EnvironmentManagerArgs;
use codex_exec_server::ExecServerRuntimePaths;
@@ -112,6 +113,7 @@ pub async fn run_main(
// Set up channels.
let (incoming_tx, mut incoming_rx) = mpsc::channel::<IncomingMessage>(CHANNEL_CAPACITY);
let (outgoing_tx, mut outgoing_rx) = mpsc::unbounded_channel::<OutgoingMessage>();
let installation_id = resolve_installation_id(&config.codex_home).await?;
// Task: read from stdin, push to `incoming_tx`.
let stdin_reader_handle = tokio::spawn({
@@ -144,6 +146,7 @@ pub async fn run_main(
arg0_paths,
Arc::new(config),
environment_manager,
installation_id,
)
.await;
async move {
@@ -55,6 +55,7 @@ impl MessageProcessor {
arg0_paths: Arg0DispatchPaths,
config: Arc<Config>,
environment_manager: Arc<EnvironmentManager>,
installation_id: String,
) -> Option<Self> {
let outgoing = Arc::new(outgoing);
let auth_manager = AuthManager::shared_from_config(
@@ -74,6 +75,7 @@ impl MessageProcessor {
state_db,
thread_store,
agent_graph_store,
installation_id,
));
Some(Self {
outgoing,
@@ -58,6 +58,7 @@ use codex_core_api::built_in_model_providers;
use codex_core_api::find_codex_home;
use codex_core_api::init_state_db_from_config;
use codex_core_api::item_event_to_server_notification;
use codex_core_api::resolve_installation_id;
use codex_core_api::set_default_originator;
use codex_core_api::thread_store_from_config;
@@ -119,6 +120,7 @@ async fn run_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
let agent_graph_store = agent_graph_store_from_state_db(state_db.clone());
let environment_manager =
Arc::new(EnvironmentManager::new(EnvironmentManagerArgs::new(local_runtime_paths)).await);
let installation_id = resolve_installation_id(&config.codex_home).await?;
let thread_manager = ThreadManager::new(
&config,
auth_manager,
@@ -128,6 +130,7 @@ async fn run_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
state_db,
Arc::clone(&thread_store),
agent_graph_store,
installation_id,
);
let NewThread {