//! Test-only helpers exposed for cross-crate integration tests. //! //! Production code should not depend on this module. //! We prefer this to using a crate feature to avoid building multiple //! permutations of the crate. use std::path::PathBuf; use std::sync::Arc; use codex_exec_server::EnvironmentManager; use codex_extension_api::LoadUserInstructionsFuture; use codex_extension_api::LoadedUserInstructions; use codex_extension_api::UserInstructionsProvider; use codex_login::AuthManager; use codex_login::CodexAuth; use codex_model_provider::create_model_provider; use codex_model_provider_info::ModelProviderInfo; use codex_models_manager::bundled_models_response; use codex_models_manager::collaboration_mode_presets; use codex_models_manager::manager::SharedModelsManager; use codex_models_manager::test_support::construct_model_info_offline_for_tests; use codex_models_manager::test_support::get_model_offline_for_tests; use codex_protocol::ThreadId; use codex_protocol::config_types::CollaborationModeMask; use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ModelPreset; use codex_protocol::protocol::SessionSource; use once_cell::sync::Lazy; use crate::ThreadManager; use crate::config::Config; use crate::responses_metadata::CodexResponsesMetadata; use crate::responses_metadata::CodexResponsesRequestKind; use crate::responses_metadata::subagent_header_value; use crate::responses_metadata::subagent_metadata_kind; use crate::thread_manager; use crate::unified_exec; static TEST_MODEL_PRESETS: Lazy> = Lazy::new(|| { let mut response = bundled_models_response() .unwrap_or_else(|err| panic!("bundled models.json should parse: {err}")); response.models.sort_by_key(|model| model.priority); let mut presets: Vec = response.models.into_iter().map(Into::into).collect(); ModelPreset::mark_default_by_picker_visibility(&mut presets); presets }); /// Test-only provider that supplies no user instructions. #[derive(Debug, Default)] pub struct EmptyUserInstructionsProvider; impl UserInstructionsProvider for EmptyUserInstructionsProvider { fn load_user_instructions(&self) -> LoadUserInstructionsFuture<'_> { Box::pin(async { LoadedUserInstructions::default() }) } } pub fn set_thread_manager_test_mode(enabled: bool) { thread_manager::set_thread_manager_test_mode_for_tests(enabled); } pub fn set_deterministic_process_ids(enabled: bool) { unified_exec::set_deterministic_process_ids_for_tests(enabled); } pub fn auth_manager_from_auth(auth: CodexAuth) -> Arc { AuthManager::from_auth_for_testing(auth) } pub fn auth_manager_from_auth_with_home(auth: CodexAuth, codex_home: PathBuf) -> Arc { AuthManager::from_auth_for_testing_with_home(auth, codex_home) } pub fn thread_manager_with_models_provider( auth: CodexAuth, provider: ModelProviderInfo, ) -> ThreadManager { ThreadManager::with_models_provider_for_tests(auth, provider) } pub fn thread_manager_with_models_provider_and_home( auth: CodexAuth, provider: ModelProviderInfo, codex_home: PathBuf, environment_manager: Arc, ) -> ThreadManager { ThreadManager::with_models_provider_and_home_for_tests( auth, provider, codex_home, environment_manager, ) } pub fn thread_manager_with_models_provider_home_and_state( auth: CodexAuth, provider: ModelProviderInfo, codex_home: PathBuf, environment_manager: Arc, state_db: Option, ) -> ThreadManager { ThreadManager::with_models_provider_home_and_state_for_tests( auth, provider, codex_home, environment_manager, state_db, ) } pub async fn start_thread_with_user_shell_override( thread_manager: &ThreadManager, config: Config, user_shell_override: crate::shell::Shell, supports_openai_form_elicitation: bool, ) -> codex_protocol::error::Result { thread_manager .start_thread_with_user_shell_override_for_tests( config, user_shell_override, supports_openai_form_elicitation, ) .await } pub async fn resume_thread_from_rollout_with_user_shell_override( thread_manager: &ThreadManager, config: Config, rollout_path: PathBuf, auth_manager: Arc, user_shell_override: crate::shell::Shell, supports_openai_form_elicitation: bool, ) -> codex_protocol::error::Result { thread_manager .resume_thread_from_rollout_with_user_shell_override_for_tests( config, rollout_path, auth_manager, user_shell_override, supports_openai_form_elicitation, ) .await } pub fn models_manager_with_provider( codex_home: PathBuf, auth_manager: Arc, provider: ModelProviderInfo, ) -> SharedModelsManager { let provider = create_model_provider(provider, Some(auth_manager)); provider.models_manager(codex_home, /*config_model_catalog*/ None) } pub fn get_model_offline(model: Option<&str>) -> String { get_model_offline_for_tests(model) } pub fn construct_model_info_offline(model: &str, config: &Config) -> ModelInfo { construct_model_info_offline_for_tests(model, &config.to_models_manager_config()) } #[derive(Clone, Copy)] pub enum TestCodexResponsesRequestKind { Turn, Prewarm, WebsocketConnection, } #[allow(clippy::too_many_arguments)] pub fn responses_metadata( installation_id: &str, session_id: &str, thread_id: &str, turn_id: Option<&str>, window_id: String, session_source: &SessionSource, parent_thread_id: Option, request_kind: TestCodexResponsesRequestKind, ) -> CodexResponsesMetadata { let request_kind = match request_kind { TestCodexResponsesRequestKind::Turn => Some(CodexResponsesRequestKind::Turn), TestCodexResponsesRequestKind::Prewarm => Some(CodexResponsesRequestKind::Prewarm), TestCodexResponsesRequestKind::WebsocketConnection => None, }; CodexResponsesMetadata { turn_id: request_kind.and(turn_id.map(ToString::to_string)), request_kind, parent_thread_id, subagent_header: subagent_header_value(session_source), subagent_kind: request_kind.and_then(|_| subagent_metadata_kind(session_source)), ..CodexResponsesMetadata::new( installation_id.to_string(), session_id.to_string(), thread_id.to_string(), window_id, ) } } pub fn all_model_presets() -> &'static Vec { &TEST_MODEL_PRESETS } pub fn builtin_collaboration_mode_presets() -> Vec { collaboration_mode_presets::builtin_collaboration_mode_presets() }