diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 82dd05dab4..70592d4649 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1858,7 +1858,6 @@ dependencies = [ "codex-git", "codex-hooks", "codex-keyring-store", - "codex-login", "codex-network-proxy", "codex-otel", "codex-protocol", @@ -2181,27 +2180,19 @@ name = "codex-login" version = "0.0.0" dependencies = [ "anyhow", - "async-trait", "base64 0.22.1", "chrono", "codex-app-server-protocol", "codex-client", - "codex-keyring-store", - "codex-otel", - "codex-protocol", + "codex-core", "core_test_support", - "keyring", - "once_cell", "pretty_assertions", "rand 0.9.2", "reqwest", - "schemars 0.8.22", "serde", "serde_json", - "serial_test", "sha2", "tempfile", - "thiserror 2.0.18", "tiny_http", "tokio", "tracing", diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index 92c1a0bff0..fc8283eda0 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -35,7 +35,6 @@ codex-client = { workspace = true } codex-connectors = { workspace = true } codex-config = { workspace = true } codex-exec-server = { workspace = true } -codex-login = { workspace = true } codex-shell-command = { workspace = true } codex-skills = { workspace = true } codex-execpolicy = { workspace = true } diff --git a/codex-rs/login/src/auth/auth.rs b/codex-rs/core/src/auth.rs similarity index 97% rename from codex-rs/login/src/auth/auth.rs rename to codex-rs/core/src/auth.rs index 6d2e201965..90f0dcfdaf 100644 --- a/codex-rs/login/src/auth/auth.rs +++ b/codex-rs/core/src/auth.rs @@ -1,3 +1,5 @@ +mod storage; + use async_trait::async_trait; use chrono::Utc; use reqwest::StatusCode; @@ -17,17 +19,18 @@ use codex_app_server_protocol::AuthMode as ApiAuthMode; use codex_otel::TelemetryAuthMode; use codex_protocol::config_types::ForcedLoginMethod; -use crate::auth::error::RefreshTokenFailedError; -use crate::auth::error::RefreshTokenFailedReason; pub use crate::auth::storage::AuthCredentialsStoreMode; pub use crate::auth::storage::AuthDotJson; use crate::auth::storage::AuthStorageBackend; use crate::auth::storage::create_auth_storage; -use crate::auth::util::try_parse_error_message; +use crate::config::Config; +use crate::error::RefreshTokenFailedError; +use crate::error::RefreshTokenFailedReason; use crate::token_data::KnownPlan as InternalKnownPlan; use crate::token_data::PlanType as InternalPlanType; use crate::token_data::TokenData; use crate::token_data::parse_chatgpt_jwt_claims; +use crate::util::try_parse_error_message; use codex_client::CodexHttpClient; use codex_protocol::account::PlanType as AccountPlanType; use serde_json::Value; @@ -158,14 +161,14 @@ impl CodexAuth { codex_home: &Path, auth_dot_json: AuthDotJson, auth_credentials_store_mode: AuthCredentialsStoreMode, + client: CodexHttpClient, ) -> std::io::Result { let auth_mode = auth_dot_json.resolved_mode(); - let client = codex_client::create_client(); if auth_mode == ApiAuthMode::ApiKey { let Some(api_key) = auth_dot_json.openai_api_key.as_deref() else { return Err(std::io::Error::other("API key auth is missing a key.")); }; - return Ok(CodexAuth::from_api_key(api_key)); + return Ok(CodexAuth::from_api_key_with_client(api_key, client)); } let storage_mode = auth_dot_json.storage_mode(auth_credentials_store_mode); @@ -186,6 +189,7 @@ impl CodexAuth { } } + /// Loads the available auth information from auth storage. pub fn from_auth_storage( codex_home: &Path, auth_credentials_store_mode: AuthCredentialsStoreMode, @@ -331,7 +335,7 @@ impl CodexAuth { last_refresh: Some(Utc::now()), }; - let client = codex_client::create_client(); + let client = crate::default_client::create_client(); let state = ChatgptAuthState { auth_dot_json: Arc::new(Mutex::new(Some(auth_dot_json))), client, @@ -340,11 +344,15 @@ impl CodexAuth { Self::Chatgpt(ChatgptAuth { state, storage }) } - pub fn from_api_key(api_key: &str) -> Self { + fn from_api_key_with_client(api_key: &str, _client: CodexHttpClient) -> Self { Self::ApiKey(ApiKeyAuth { api_key: api_key.to_owned(), }) } + + pub fn from_api_key(api_key: &str) -> Self { + Self::from_api_key_with_client(api_key, crate::default_client::create_client()) + } } impl ChatgptAuth { @@ -450,19 +458,11 @@ pub fn load_auth_dot_json( storage.load() } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct AuthConfig { - pub codex_home: PathBuf, - pub auth_credentials_store_mode: AuthCredentialsStoreMode, - pub forced_login_method: Option, - pub forced_chatgpt_workspace_id: Option, -} - -pub fn enforce_login_restrictions(config: &AuthConfig) -> std::io::Result<()> { +pub fn enforce_login_restrictions(config: &Config) -> std::io::Result<()> { let Some(auth) = load_auth( &config.codex_home, /*enable_codex_api_key_env*/ true, - config.auth_credentials_store_mode, + config.cli_auth_credentials_store_mode, )? else { return Ok(()); @@ -486,7 +486,7 @@ pub fn enforce_login_restrictions(config: &AuthConfig) -> std::io::Result<()> { return logout_with_message( &config.codex_home, message, - config.auth_credentials_store_mode, + config.cli_auth_credentials_store_mode, ); } } @@ -504,7 +504,7 @@ pub fn enforce_login_restrictions(config: &AuthConfig) -> std::io::Result<()> { format!( "Failed to load ChatGPT credentials while enforcing workspace restrictions: {err}. Logging out." ), - config.auth_credentials_store_mode, + config.cli_auth_credentials_store_mode, ); } }; @@ -523,7 +523,7 @@ pub fn enforce_login_restrictions(config: &AuthConfig) -> std::io::Result<()> { return logout_with_message( &config.codex_home, message, - config.auth_credentials_store_mode, + config.cli_auth_credentials_store_mode, ); } } @@ -564,12 +564,17 @@ fn load_auth( auth_credentials_store_mode: AuthCredentialsStoreMode, ) -> std::io::Result> { let build_auth = |auth_dot_json: AuthDotJson, storage_mode| { - CodexAuth::from_auth_dot_json(codex_home, auth_dot_json, storage_mode) + let client = crate::default_client::create_client(); + CodexAuth::from_auth_dot_json(codex_home, auth_dot_json, storage_mode, client) }; // API key via env var takes precedence over any other auth method. if enable_codex_api_key_env && let Some(api_key) = read_codex_api_key_from_env() { - return Ok(Some(CodexAuth::from_api_key(api_key.as_str()))); + let client = crate::default_client::create_client(); + return Ok(Some(CodexAuth::from_api_key_with_client( + api_key.as_str(), + client, + ))); } // External ChatGPT auth tokens live in the in-memory (ephemeral) store. Always check this @@ -1072,7 +1077,7 @@ impl AuthManager { } /// Create an AuthManager with a specific CodexAuth, for testing only. - pub fn from_auth_for_testing(auth: CodexAuth) -> Arc { + pub(crate) fn from_auth_for_testing(auth: CodexAuth) -> Arc { let cached = CachedAuth { auth: Some(auth), external_refresher: None, @@ -1088,7 +1093,10 @@ impl AuthManager { } /// Create an AuthManager with a specific CodexAuth and codex home, for testing only. - pub fn from_auth_for_testing_with_home(auth: CodexAuth, codex_home: PathBuf) -> Arc { + pub(crate) fn from_auth_for_testing_with_home( + auth: CodexAuth, + codex_home: PathBuf, + ) -> Arc { let cached = CachedAuth { auth: Some(auth), external_refresher: None, diff --git a/codex-rs/login/src/auth/storage.rs b/codex-rs/core/src/auth/storage.rs similarity index 100% rename from codex-rs/login/src/auth/storage.rs rename to codex-rs/core/src/auth/storage.rs diff --git a/codex-rs/login/src/auth/storage_tests.rs b/codex-rs/core/src/auth/storage_tests.rs similarity index 100% rename from codex-rs/login/src/auth/storage_tests.rs rename to codex-rs/core/src/auth/storage_tests.rs diff --git a/codex-rs/login/src/auth/auth_tests.rs b/codex-rs/core/src/auth_tests.rs similarity index 97% rename from codex-rs/login/src/auth/auth_tests.rs rename to codex-rs/core/src/auth_tests.rs index c39e92ab39..3bc5eb6c78 100644 --- a/codex-rs/login/src/auth/auth_tests.rs +++ b/codex-rs/core/src/auth_tests.rs @@ -1,6 +1,8 @@ use super::*; use crate::auth::storage::FileAuthStorage; use crate::auth::storage::get_auth_file; +use crate::config::Config; +use crate::config::ConfigBuilder; use crate::token_data::IdTokenInfo; use crate::token_data::KnownPlan as InternalKnownPlan; use crate::token_data::PlanType as InternalPlanType; @@ -258,13 +260,15 @@ async fn build_config( codex_home: &Path, forced_login_method: Option, forced_chatgpt_workspace_id: Option, -) -> AuthConfig { - AuthConfig { - codex_home: codex_home.to_path_buf(), - auth_credentials_store_mode: AuthCredentialsStoreMode::File, - forced_login_method, - forced_chatgpt_workspace_id, - } +) -> Config { + let mut config = ConfigBuilder::default() + .codex_home(codex_home.to_path_buf()) + .build() + .await + .expect("config should load"); + config.forced_login_method = forced_login_method; + config.forced_chatgpt_workspace_id = forced_chatgpt_workspace_id; + config } /// Use sparingly. diff --git a/codex-rs/core/src/error.rs b/codex-rs/core/src/error.rs index 80d60619dd..e8e86defc2 100644 --- a/codex-rs/core/src/error.rs +++ b/codex-rs/core/src/error.rs @@ -9,8 +9,6 @@ use chrono::Datelike; use chrono::Local; use chrono::Utc; use codex_async_utils::CancelErr; -pub use codex_login::auth::RefreshTokenFailedError; -pub use codex_login::auth::RefreshTokenFailedReason; use codex_protocol::ThreadId; use codex_protocol::protocol::CodexErrorInfo; use codex_protocol::protocol::ErrorEvent; @@ -263,6 +261,30 @@ impl std::fmt::Display for ResponseStreamFailed { } } +#[derive(Debug, Clone, PartialEq, Eq, Error)] +#[error("{message}")] +pub struct RefreshTokenFailedError { + pub reason: RefreshTokenFailedReason, + pub message: String, +} + +impl RefreshTokenFailedError { + pub fn new(reason: RefreshTokenFailedReason, message: impl Into) -> Self { + Self { + reason, + message: message.into(), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RefreshTokenFailedReason { + Expired, + Exhausted, + Revoked, + Other, +} + #[derive(Debug)] pub struct UnexpectedResponseError { pub status: StatusCode, diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index 6d3816a417..882120f7c3 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -10,7 +10,7 @@ pub mod api_bridge; mod apply_patch; mod apps; mod arc_monitor; -pub use codex_login as auth; +pub mod auth; mod auth_env_telemetry; mod client; mod client_common; @@ -76,7 +76,7 @@ mod shell_detect; mod stream_events_utils; pub mod test_support; mod text_encoding; -pub use codex_login::token_data; +pub mod token_data; mod truncate; mod unified_exec; pub mod windows_sandbox; diff --git a/codex-rs/login/src/token_data.rs b/codex-rs/core/src/token_data.rs similarity index 96% rename from codex-rs/login/src/token_data.rs rename to codex-rs/core/src/token_data.rs index 304bf765f4..5952d5940d 100644 --- a/codex-rs/login/src/token_data.rs +++ b/codex-rs/core/src/token_data.rs @@ -27,7 +27,7 @@ pub struct IdTokenInfo { /// The ChatGPT subscription plan type /// (e.g., "free", "plus", "pro", "business", "enterprise", "edu"). /// (Note: values may vary by backend.) - pub chatgpt_plan_type: Option, + pub(crate) chatgpt_plan_type: Option, /// ChatGPT user identifier associated with the token, if present. pub chatgpt_user_id: Option, /// Organization/workspace identifier associated with the token, if present. @@ -55,13 +55,13 @@ impl IdTokenInfo { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(untagged)] -pub enum PlanType { +pub(crate) enum PlanType { Known(KnownPlan), Unknown(String), } impl PlanType { - pub fn from_raw_value(raw: &str) -> Self { + pub(crate) fn from_raw_value(raw: &str) -> Self { match raw.to_ascii_lowercase().as_str() { "free" => Self::Known(KnownPlan::Free), "go" => Self::Known(KnownPlan::Go), @@ -78,7 +78,7 @@ impl PlanType { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] -pub enum KnownPlan { +pub(crate) enum KnownPlan { Free, Go, Plus, diff --git a/codex-rs/login/src/token_data_tests.rs b/codex-rs/core/src/token_data_tests.rs similarity index 100% rename from codex-rs/login/src/token_data_tests.rs rename to codex-rs/core/src/token_data_tests.rs diff --git a/codex-rs/core/src/util.rs b/codex-rs/core/src/util.rs index 09892cca57..1dbd6a84fc 100644 --- a/codex-rs/core/src/util.rs +++ b/codex-rs/core/src/util.rs @@ -217,6 +217,21 @@ pub(crate) fn error_or_panic(message: impl std::string::ToString) { } } +pub(crate) fn try_parse_error_message(text: &str) -> String { + debug!("Parsing server error response: {}", text); + let json = serde_json::from_str::(text).unwrap_or_default(); + if let Some(error) = json.get("error") + && let Some(message) = error.get("message") + && let Some(message_str) = message.as_str() + { + return message_str.to_string(); + } + if text.is_empty() { + return "Unknown error".to_string(); + } + text.to_string() +} + pub fn resolve_path(base: &Path, path: &PathBuf) -> PathBuf { if path.is_absolute() { path.clone() diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index 96a5171fbc..c7ee33b9b5 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -41,11 +41,12 @@ use codex_app_server_protocol::TurnInterruptResponse; use codex_app_server_protocol::TurnStartParams; use codex_app_server_protocol::TurnStartResponse; use codex_arg0::Arg0DispatchPaths; +use codex_client::set_default_client_residency_requirement; +use codex_client::set_default_originator; use codex_cloud_requirements::cloud_requirements_loader; use codex_core::AuthManager; use codex_core::LMSTUDIO_OSS_PROVIDER_ID; use codex_core::OLLAMA_OSS_PROVIDER_ID; -use codex_core::auth::AuthConfig; use codex_core::auth::enforce_login_restrictions; use codex_core::check_execpolicy_for_warnings; use codex_core::config::Config; @@ -99,8 +100,6 @@ use uuid::Uuid; use crate::cli::Command as ExecCommand; use crate::event_processor::CodexStatus; use crate::event_processor::EventProcessor; -use codex_client::set_default_client_residency_requirement; -use codex_client::set_default_originator; use codex_core::find_thread_path_by_id_str; use codex_core::find_thread_path_by_name_str; @@ -382,12 +381,7 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result set_default_client_residency_requirement(config.enforce_residency.value()); - if let Err(err) = enforce_login_restrictions(&AuthConfig { - codex_home: config.codex_home.clone(), - auth_credentials_store_mode: config.cli_auth_credentials_store_mode, - forced_login_method: config.forced_login_method, - forced_chatgpt_workspace_id: config.forced_chatgpt_workspace_id.clone(), - }) { + if let Err(err) = enforce_login_restrictions(&config) { eprintln!("{err}"); std::process::exit(1); } diff --git a/codex-rs/login/Cargo.toml b/codex-rs/login/Cargo.toml index 306d2f3445..5524fec7c1 100644 --- a/codex-rs/login/Cargo.toml +++ b/codex-rs/login/Cargo.toml @@ -8,22 +8,16 @@ license.workspace = true workspace = true [dependencies] -async-trait = { workspace = true } base64 = { workspace = true } chrono = { workspace = true, features = ["serde"] } -codex-app-server-protocol = { workspace = true } codex-client = { workspace = true } -codex-keyring-store = { workspace = true } -codex-otel = { workspace = true } -codex-protocol = { workspace = true } -once_cell = { workspace = true } +codex-core = { workspace = true } +codex-app-server-protocol = { workspace = true } rand = { workspace = true } reqwest = { workspace = true, features = ["json", "blocking"] } -schemars = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } sha2 = { workspace = true } -thiserror = { workspace = true } tiny_http = { workspace = true } tokio = { workspace = true, features = [ "io-std", @@ -40,8 +34,6 @@ webbrowser = { workspace = true } [dev-dependencies] anyhow = { workspace = true } core_test_support = { workspace = true } -keyring = { workspace = true } pretty_assertions = { workspace = true } -serial_test = { workspace = true } tempfile = { workspace = true } wiremock = { workspace = true } diff --git a/codex-rs/login/src/auth/error.rs b/codex-rs/login/src/auth/error.rs deleted file mode 100644 index fcbd4c7093..0000000000 --- a/codex-rs/login/src/auth/error.rs +++ /dev/null @@ -1,25 +0,0 @@ -use thiserror::Error; - -#[derive(Debug, Clone, PartialEq, Eq, Error)] -#[error("{message}")] -pub struct RefreshTokenFailedError { - pub reason: RefreshTokenFailedReason, - pub message: String, -} - -impl RefreshTokenFailedError { - pub fn new(reason: RefreshTokenFailedReason, message: impl Into) -> Self { - Self { - reason, - message: message.into(), - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum RefreshTokenFailedReason { - Expired, - Exhausted, - Revoked, - Other, -} diff --git a/codex-rs/login/src/auth/mod.rs b/codex-rs/login/src/auth/mod.rs deleted file mode 100644 index ce7968bf0c..0000000000 --- a/codex-rs/login/src/auth/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod error; -mod storage; -mod util; - -mod auth; - -pub use auth::*; -pub use error::RefreshTokenFailedError; -pub use error::RefreshTokenFailedReason; diff --git a/codex-rs/login/src/auth/util.rs b/codex-rs/login/src/auth/util.rs deleted file mode 100644 index 18592f9fb7..0000000000 --- a/codex-rs/login/src/auth/util.rs +++ /dev/null @@ -1,16 +0,0 @@ -use tracing::debug; - -pub(crate) fn try_parse_error_message(text: &str) -> String { - debug!("Parsing server error response: {}", text); - let json = serde_json::from_str::(text).unwrap_or_default(); - if let Some(error) = json.get("error") - && let Some(message) = error.get("message") - && let Some(message_str) = message.as_str() - { - return message_str.to_string(); - } - if text.is_empty() { - return "Unknown error".to_string(); - } - text.to_string() -} diff --git a/codex-rs/login/src/lib.rs b/codex-rs/login/src/lib.rs index 5b3cf17984..60b0c57f28 100644 --- a/codex-rs/login/src/lib.rs +++ b/codex-rs/login/src/lib.rs @@ -1,6 +1,3 @@ -pub mod auth; -pub mod token_data; - mod device_code_auth; mod pkce; mod server; @@ -15,14 +12,15 @@ pub use server::ServerOptions; pub use server::ShutdownHandle; pub use server::run_login_server; -pub use auth::AuthDotJson; -pub use auth::AuthManager; -pub use auth::CLIENT_ID; -pub use auth::CODEX_API_KEY_ENV_VAR; -pub use auth::CodexAuth; -pub use auth::OPENAI_API_KEY_ENV_VAR; -pub use auth::login_with_api_key; -pub use auth::logout; -pub use auth::save_auth; +// Re-export commonly used auth types and helpers from codex-core for compatibility pub use codex_app_server_protocol::AuthMode; -pub use token_data::TokenData; +pub use codex_core::AuthManager; +pub use codex_core::CodexAuth; +pub use codex_core::auth::AuthDotJson; +pub use codex_core::auth::CLIENT_ID; +pub use codex_core::auth::CODEX_API_KEY_ENV_VAR; +pub use codex_core::auth::OPENAI_API_KEY_ENV_VAR; +pub use codex_core::auth::login_with_api_key; +pub use codex_core::auth::logout; +pub use codex_core::auth::save_auth; +pub use codex_core::token_data::TokenData; diff --git a/codex-rs/login/src/server.rs b/codex-rs/login/src/server.rs index b12fbb8ed4..96b3759078 100644 --- a/codex-rs/login/src/server.rs +++ b/codex-rs/login/src/server.rs @@ -23,18 +23,18 @@ use std::sync::Arc; use std::thread; use std::time::Duration; -use crate::auth::AuthCredentialsStoreMode; -use crate::auth::AuthDotJson; -use crate::auth::save_auth; use crate::pkce::PkceCodes; use crate::pkce::generate_pkce; -use crate::token_data::TokenData; -use crate::token_data::parse_chatgpt_jwt_claims; use base64::Engine; use chrono::Utc; use codex_app_server_protocol::AuthMode; use codex_client::build_reqwest_client_with_custom_ca; use codex_client::originator; +use codex_core::auth::AuthCredentialsStoreMode; +use codex_core::auth::AuthDotJson; +use codex_core::auth::save_auth; +use codex_core::token_data::TokenData; +use codex_core::token_data::parse_chatgpt_jwt_claims; use rand::RngCore; use serde_json::Value as JsonValue; use tiny_http::Header; diff --git a/codex-rs/login/tests/suite/device_code_login.rs b/codex-rs/login/tests/suite/device_code_login.rs index a879986976..266930e419 100644 --- a/codex-rs/login/tests/suite/device_code_login.rs +++ b/codex-rs/login/tests/suite/device_code_login.rs @@ -3,9 +3,9 @@ use anyhow::Context; use base64::Engine; use base64::engine::general_purpose::URL_SAFE_NO_PAD; +use codex_core::auth::AuthCredentialsStoreMode; +use codex_core::auth::load_auth_dot_json; use codex_login::ServerOptions; -use codex_login::auth::AuthCredentialsStoreMode; -use codex_login::auth::load_auth_dot_json; use codex_login::run_device_code_login; use serde_json::json; use std::sync::Arc; diff --git a/codex-rs/login/tests/suite/login_server_e2e.rs b/codex-rs/login/tests/suite/login_server_e2e.rs index 5b0ddd9b72..cdd4019f77 100644 --- a/codex-rs/login/tests/suite/login_server_e2e.rs +++ b/codex-rs/login/tests/suite/login_server_e2e.rs @@ -7,8 +7,8 @@ use std::time::Duration; use anyhow::Result; use base64::Engine; +use codex_core::auth::AuthCredentialsStoreMode; use codex_login::ServerOptions; -use codex_login::auth::AuthCredentialsStoreMode; use codex_login::run_login_server; use core_test_support::skip_if_no_network; use tempfile::tempdir; diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index 5655229f73..f8f2d491ef 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -14,7 +14,6 @@ use codex_core::CodexAuth; use codex_core::INTERACTIVE_SESSION_SOURCES; use codex_core::RolloutRecorder; use codex_core::ThreadSortKey; -use codex_core::auth::AuthConfig; use codex_core::auth::AuthMode; use codex_core::auth::enforce_login_restrictions; use codex_core::check_execpolicy_for_warnings; @@ -455,12 +454,7 @@ pub async fn run_main( } #[allow(clippy::print_stderr)] - if let Err(err) = enforce_login_restrictions(&AuthConfig { - codex_home: config.codex_home.clone(), - auth_credentials_store_mode: config.cli_auth_credentials_store_mode, - forced_login_method: config.forced_login_method, - forced_chatgpt_workspace_id: config.forced_chatgpt_workspace_id.clone(), - }) { + if let Err(err) = enforce_login_restrictions(&config) { eprintln!("{err}"); std::process::exit(1); } diff --git a/codex-rs/tui_app_server/src/lib.rs b/codex-rs/tui_app_server/src/lib.rs index e892795a48..4ed94a2b22 100644 --- a/codex-rs/tui_app_server/src/lib.rs +++ b/codex-rs/tui_app_server/src/lib.rs @@ -22,7 +22,6 @@ use codex_app_server_protocol::ThreadSortKey as AppServerThreadSortKey; use codex_app_server_protocol::ThreadSourceKind; use codex_client::set_default_client_residency_requirement; use codex_cloud_requirements::cloud_requirements_loader_for_storage; -use codex_core::auth::AuthConfig; use codex_core::auth::enforce_login_restrictions; use codex_core::check_execpolicy_for_warnings; use codex_core::config::Config; @@ -778,12 +777,7 @@ pub async fn run_main( if matches!(app_server_target, AppServerTarget::Embedded) { #[allow(clippy::print_stderr)] - if let Err(err) = enforce_login_restrictions(&AuthConfig { - codex_home: config.codex_home.clone(), - auth_credentials_store_mode: config.cli_auth_credentials_store_mode, - forced_login_method: config.forced_login_method, - forced_chatgpt_workspace_id: config.forced_chatgpt_workspace_id.clone(), - }) { + if let Err(err) = enforce_login_restrictions(&config) { eprintln!("{err}"); std::process::exit(1); }