diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 32b41c022..d00aa4545 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1664,6 +1664,7 @@ dependencies = [ "codex-rmcp-client", "codex-state", "codex-stdio-to-uds", + "codex-terminal-detection", "codex-tui", "codex-tui-app-server", "codex-utils-cargo-bin", @@ -1858,6 +1859,7 @@ dependencies = [ "codex-shell-escalation", "codex-skills", "codex-state", + "codex-terminal-detection", "codex-test-macros", "codex-utils-absolute-path", "codex-utils-cache", @@ -2507,6 +2509,14 @@ dependencies = [ "uds_windows", ] +[[package]] +name = "codex-terminal-detection" +version = "0.0.0" +dependencies = [ + "pretty_assertions", + "tracing", +] + [[package]] name = "codex-test-macros" version = "0.0.0" @@ -2542,6 +2552,7 @@ dependencies = [ "codex-protocol", "codex-shell-command", "codex-state", + "codex-terminal-detection", "codex-tui-app-server", "codex-utils-absolute-path", "codex-utils-approval-presets", @@ -2633,6 +2644,7 @@ dependencies = [ "codex-protocol", "codex-shell-command", "codex-state", + "codex-terminal-detection", "codex-utils-absolute-path", "codex-utils-approval-presets", "codex-utils-cargo-bin", @@ -5815,6 +5827,7 @@ dependencies = [ "anyhow", "codex-core", "codex-mcp-server", + "codex-terminal-detection", "codex-utils-cargo-bin", "core_test_support", "os_info", diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index edcd98fbb..961c4ef9f 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -66,6 +66,7 @@ members = [ "codex-client", "codex-api", "state", + "terminal-detection", "codex-experimental-api-macros", "test-macros", "package-manager", @@ -131,6 +132,7 @@ codex-skills = { path = "skills" } codex-state = { path = "state" } codex-stdio-to-uds = { path = "stdio-to-uds" } codex-test-macros = { path = "test-macros" } +codex-terminal-detection = { path = "terminal-detection" } codex-tui = { path = "tui" } codex-tui-app-server = { path = "tui_app_server" } codex-utils-absolute-path = { path = "utils/absolute-path" } diff --git a/codex-rs/cli/Cargo.toml b/codex-rs/cli/Cargo.toml index a7e88cd1b..affc5ef8c 100644 --- a/codex-rs/cli/Cargo.toml +++ b/codex-rs/cli/Cargo.toml @@ -37,6 +37,7 @@ codex-responses-api-proxy = { workspace = true } codex-rmcp-client = { workspace = true } codex-state = { workspace = true } codex-stdio-to-uds = { workspace = true } +codex-terminal-detection = { workspace = true } codex-tui = { workspace = true } codex-tui-app-server = { workspace = true } libc = { workspace = true } diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 938639828..e9f4d6f68 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -50,7 +50,7 @@ use codex_core::config::edit::ConfigEditsBuilder; use codex_core::config::find_codex_home; use codex_core::features::Stage; use codex_core::features::is_known_feature_key; -use codex_core::terminal::TerminalName; +use codex_terminal_detection::TerminalName; /// Codex CLI /// @@ -1049,7 +1049,7 @@ async fn run_interactive_tui( interactive.prompt = Some(prompt.replace("\r\n", "\n").replace('\r', "\n")); } - let terminal_info = codex_core::terminal::terminal_info(); + let terminal_info = codex_terminal_detection::terminal_info(); if terminal_info.name == TerminalName::Dumb { if !(std::io::stdin().is_terminal() && std::io::stderr().is_terminal()) { return Ok(AppExitInfo::fatal( diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index a44da5e11..869f9dd9f 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -48,6 +48,7 @@ codex-artifacts = { workspace = true } codex-protocol = { workspace = true } codex-rmcp-client = { workspace = true } codex-state = { workspace = true } +codex-terminal-detection = { workspace = true } codex-utils-absolute-path = { workspace = true } codex-utils-cache = { workspace = true } codex-utils-image = { workspace = true } diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 83fb05626..505d25439 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -49,7 +49,6 @@ use crate::stream_events_utils::handle_output_item_done; use crate::stream_events_utils::last_assistant_message_from_item; use crate::stream_events_utils::raw_assistant_output_text_from_item; use crate::stream_events_utils::record_completed_response_item; -use crate::terminal; use crate::truncate::TruncationPolicy; use crate::turn_metadata::TurnMetadataState; use crate::util::error_or_panic; @@ -117,6 +116,7 @@ use codex_protocol::request_user_input::RequestUserInputArgs; use codex_protocol::request_user_input::RequestUserInputResponse; use codex_rmcp_client::ElicitationResponse; use codex_rmcp_client::OAuthCredentialsStoreMode; +use codex_terminal_detection::user_agent; use codex_utils_stream_parser::AssistantTextChunk; use codex_utils_stream_parser::AssistantTextStreamParser; use codex_utils_stream_parser::ProposedPlanSegment; @@ -1581,7 +1581,7 @@ impl Session { let account_id = auth.and_then(CodexAuth::get_account_id); let account_email = auth.and_then(CodexAuth::get_account_email); let originator = crate::default_client::originator().value; - let terminal_type = terminal::user_agent(); + let terminal_type = user_agent(); let session_model = session_configuration.collaboration_mode.model().to_string(); let auth_env_telemetry = collect_auth_env_telemetry( &session_configuration.provider, diff --git a/codex-rs/core/src/default_client.rs b/codex-rs/core/src/default_client.rs index 3ca653ba4..59c7bd2fb 100644 --- a/codex-rs/core/src/default_client.rs +++ b/codex-rs/core/src/default_client.rs @@ -4,6 +4,7 @@ use codex_client::BuildCustomCaTransportError; use codex_client::CodexHttpClient; pub use codex_client::CodexRequestBuilder; use codex_client::build_reqwest_client_with_custom_ca; +use codex_terminal_detection::user_agent; use reqwest::header::HeaderMap; use reqwest::header::HeaderValue; use std::sync::LazyLock; @@ -130,7 +131,7 @@ pub fn get_codex_user_agent() -> String { os_info.os_type(), os_info.version(), os_info.architecture().unwrap_or("unknown"), - crate::terminal::user_agent() + user_agent() ); let suffix = USER_AGENT_SUFFIX .lock() diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index 10a51b23e..6d519f488 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -120,7 +120,6 @@ pub mod shell_snapshot; pub mod skills; pub mod spawn; pub mod state_db; -pub mod terminal; mod tools; pub mod turn_diff_tracker; mod turn_metadata; diff --git a/codex-rs/exec-server/src/server/filesystem.rs b/codex-rs/exec-server/src/server/filesystem.rs index bc3d22a4d..a263bb1fe 100644 --- a/codex-rs/exec-server/src/server/filesystem.rs +++ b/codex-rs/exec-server/src/server/filesystem.rs @@ -36,7 +36,7 @@ pub(crate) struct ExecServerFileSystem { impl Default for ExecServerFileSystem { fn default() -> Self { Self { - file_system: Arc::new(Environment.get_filesystem()), + file_system: Arc::new(Environment::default().get_filesystem()), } } } diff --git a/codex-rs/mcp-server/tests/common/Cargo.toml b/codex-rs/mcp-server/tests/common/Cargo.toml index 1dec2d09a..83f2c5369 100644 --- a/codex-rs/mcp-server/tests/common/Cargo.toml +++ b/codex-rs/mcp-server/tests/common/Cargo.toml @@ -11,6 +11,7 @@ path = "lib.rs" anyhow = { workspace = true } codex-core = { workspace = true } codex-mcp-server = { workspace = true } +codex-terminal-detection = { workspace = true } codex-utils-cargo-bin = { workspace = true } rmcp = { workspace = true } os_info = { workspace = true } diff --git a/codex-rs/mcp-server/tests/common/mcp_process.rs b/codex-rs/mcp-server/tests/common/mcp_process.rs index 92b5caa65..53925ca39 100644 --- a/codex-rs/mcp-server/tests/common/mcp_process.rs +++ b/codex-rs/mcp-server/tests/common/mcp_process.rs @@ -11,6 +11,7 @@ use tokio::process::ChildStdout; use anyhow::Context; use codex_mcp_server::CodexToolCallParam; +use codex_terminal_detection::user_agent; use pretty_assertions::assert_eq; use rmcp::model::CallToolRequestParams; @@ -156,7 +157,7 @@ impl McpProcess { os_info.os_type(), os_info.version(), os_info.architecture().unwrap_or("unknown"), - codex_core::terminal::user_agent() + user_agent() ); let JsonRpcMessage::Response(JsonRpcResponse { jsonrpc, diff --git a/codex-rs/terminal-detection/BUILD.bazel b/codex-rs/terminal-detection/BUILD.bazel new file mode 100644 index 000000000..a41a762c1 --- /dev/null +++ b/codex-rs/terminal-detection/BUILD.bazel @@ -0,0 +1,6 @@ +load("//:defs.bzl", "codex_rust_crate") + +codex_rust_crate( + name = "terminal-detection", + crate_name = "codex_terminal_detection", +) diff --git a/codex-rs/terminal-detection/Cargo.toml b/codex-rs/terminal-detection/Cargo.toml new file mode 100644 index 000000000..f75e649d3 --- /dev/null +++ b/codex-rs/terminal-detection/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "codex-terminal-detection" +version.workspace = true +edition.workspace = true +license.workspace = true + +[lib] +name = "codex_terminal_detection" +path = "src/lib.rs" + +[lints] +workspace = true + +[dependencies] +tracing = { workspace = true } + +[dev-dependencies] +pretty_assertions = { workspace = true } diff --git a/codex-rs/core/src/terminal.rs b/codex-rs/terminal-detection/src/lib.rs similarity index 100% rename from codex-rs/core/src/terminal.rs rename to codex-rs/terminal-detection/src/lib.rs diff --git a/codex-rs/core/src/terminal_tests.rs b/codex-rs/terminal-detection/src/terminal_tests.rs similarity index 100% rename from codex-rs/core/src/terminal_tests.rs rename to codex-rs/terminal-detection/src/terminal_tests.rs diff --git a/codex-rs/tui/Cargo.toml b/codex-rs/tui/Cargo.toml index 03c3a03dd..d4b6f25f0 100644 --- a/codex-rs/tui/Cargo.toml +++ b/codex-rs/tui/Cargo.toml @@ -43,6 +43,7 @@ codex-otel = { workspace = true } codex-protocol = { workspace = true } codex-shell-command = { workspace = true } codex-state = { workspace = true } +codex-terminal-detection = { workspace = true } codex-tui-app-server = { workspace = true } codex-utils-approval-presets = { workspace = true } codex-utils-absolute-path = { workspace = true } diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 09776f0f7..50b663162 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -80,6 +80,7 @@ use codex_protocol::protocol::SessionConfiguredEvent; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SkillErrorInfo; use codex_protocol::protocol::TokenUsage; +use codex_terminal_detection::user_agent; use codex_utils_absolute_path::AbsolutePathBuf; use color_eyre::eyre::Result; use color_eyre::eyre::WrapErr; @@ -2079,7 +2080,7 @@ impl App { auth_mode, codex_core::default_client::originator().value, config.otel.log_user_prompt, - codex_core::terminal::user_agent(), + user_agent(), SessionSource::Cli, ); if config diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index a1736171c..897ec389e 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -76,8 +76,6 @@ use codex_core::models_manager::manager::ModelsManager; use codex_core::plugins::PluginsManager; use codex_core::project_doc::DEFAULT_PROJECT_DOC_FILENAME; use codex_core::skills::model::SkillMetadata; -use codex_core::terminal::TerminalName; -use codex_core::terminal::terminal_info; #[cfg(target_os = "windows")] use codex_core::windows_sandbox::WindowsSandboxLevelExt; use codex_otel::RuntimeMetricsSummary; @@ -155,6 +153,8 @@ use codex_protocol::request_permissions::RequestPermissionsEvent; use codex_protocol::request_user_input::RequestUserInputEvent; use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; +use codex_terminal_detection::TerminalName; +use codex_terminal_detection::terminal_info; use codex_utils_sleep_inhibitor::SleepInhibitor; use crossterm::event::KeyCode; use crossterm::event::KeyEvent; diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 05adf3d30..97cdf7eee 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -38,7 +38,6 @@ use codex_core::features::Feature; use codex_core::models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_core::models_manager::manager::ModelsManager; use codex_core::skills::model::SkillMetadata; -use codex_core::terminal::TerminalName; use codex_otel::RuntimeMetricsSummary; use codex_otel::SessionTelemetry; use codex_protocol::ThreadId; @@ -121,6 +120,7 @@ use codex_protocol::request_user_input::RequestUserInputQuestion; use codex_protocol::request_user_input::RequestUserInputQuestionOption; use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; +use codex_terminal_detection::TerminalName; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_approval_presets::builtin_approval_presets; use crossterm::event::KeyCode; diff --git a/codex-rs/tui/src/diff_render.rs b/codex-rs/tui/src/diff_render.rs index dd3990165..684d76b1e 100644 --- a/codex-rs/tui/src/diff_render.rs +++ b/codex-rs/tui/src/diff_render.rs @@ -93,9 +93,9 @@ use crate::terminal_palette::indexed_color; use crate::terminal_palette::rgb_color; use crate::terminal_palette::stdout_color_level; use codex_core::git_info::get_git_repo_root; -use codex_core::terminal::TerminalName; -use codex_core::terminal::terminal_info; use codex_protocol::protocol::FileChange; +use codex_terminal_detection::TerminalName; +use codex_terminal_detection::terminal_info; /// Classifies a diff line for gutter sign rendering and style selection. /// diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index b4841a779..8f015981c 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -33,7 +33,6 @@ use codex_core::format_exec_policy_error_with_source; use codex_core::path_utils; use codex_core::read_session_meta_line; use codex_core::state_db::get_state_db; -use codex_core::terminal::Multiplexer; use codex_core::windows_sandbox::WindowsSandboxLevelExt; use codex_protocol::ThreadId; use codex_protocol::config_types::AltScreenMode; @@ -43,6 +42,8 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; use codex_state::log_db; +use codex_terminal_detection::Multiplexer; +use codex_terminal_detection::terminal_info; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_oss::ensure_oss_provider_ready; use codex_utils_oss::get_default_model_for_oss_provider; @@ -1138,7 +1139,7 @@ fn determine_alt_screen_mode(no_alt_screen: bool, tui_alternate_screen: AltScree AltScreenMode::Always => true, AltScreenMode::Never => false, AltScreenMode::Auto => { - let terminal_info = codex_core::terminal::terminal_info(); + let terminal_info = terminal_info(); !matches!(terminal_info.multiplexer, Some(Multiplexer::Zellij { .. })) } } diff --git a/codex-rs/tui_app_server/Cargo.toml b/codex-rs/tui_app_server/Cargo.toml index 9ab33202c..4d9b26889 100644 --- a/codex-rs/tui_app_server/Cargo.toml +++ b/codex-rs/tui_app_server/Cargo.toml @@ -48,6 +48,7 @@ codex-otel = { workspace = true } codex-protocol = { workspace = true } codex-shell-command = { workspace = true } codex-state = { workspace = true } +codex-terminal-detection = { workspace = true } codex-utils-approval-presets = { workspace = true } codex-utils-absolute-path = { workspace = true } codex-utils-cli = { workspace = true } diff --git a/codex-rs/tui_app_server/src/app.rs b/codex-rs/tui_app_server/src/app.rs index 8f8092eac..52b6db48b 100644 --- a/codex-rs/tui_app_server/src/app.rs +++ b/codex-rs/tui_app_server/src/app.rs @@ -96,6 +96,7 @@ use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SkillErrorInfo; use codex_protocol::protocol::TokenUsage; +use codex_terminal_detection::user_agent; use codex_utils_absolute_path::AbsolutePathBuf; use color_eyre::eyre::Result; use color_eyre::eyre::WrapErr; @@ -2965,7 +2966,7 @@ impl App { auth_mode, codex_core::default_client::originator().value, config.otel.log_user_prompt, - codex_core::terminal::user_agent(), + user_agent(), SessionSource::Cli, ); if config diff --git a/codex-rs/tui_app_server/src/chatwidget.rs b/codex-rs/tui_app_server/src/chatwidget.rs index d76751c14..eaf9ca115 100644 --- a/codex-rs/tui_app_server/src/chatwidget.rs +++ b/codex-rs/tui_app_server/src/chatwidget.rs @@ -94,8 +94,6 @@ use codex_core::git_info::local_git_branches; use codex_core::plugins::PluginsManager; use codex_core::project_doc::DEFAULT_PROJECT_DOC_FILENAME; use codex_core::skills::model::SkillMetadata; -use codex_core::terminal::TerminalName; -use codex_core::terminal::terminal_info; #[cfg(target_os = "windows")] use codex_core::windows_sandbox::WindowsSandboxLevelExt; use codex_otel::RuntimeMetricsSummary; @@ -199,6 +197,8 @@ use codex_protocol::request_user_input::RequestUserInputEvent; use codex_protocol::request_user_input::RequestUserInputQuestionOption; use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; +use codex_terminal_detection::TerminalName; +use codex_terminal_detection::terminal_info; use codex_utils_sleep_inhibitor::SleepInhibitor; use crossterm::event::KeyCode; use crossterm::event::KeyEvent; diff --git a/codex-rs/tui_app_server/src/chatwidget/tests.rs b/codex-rs/tui_app_server/src/chatwidget/tests.rs index bae556d51..a08d56da8 100644 --- a/codex-rs/tui_app_server/src/chatwidget/tests.rs +++ b/codex-rs/tui_app_server/src/chatwidget/tests.rs @@ -61,7 +61,6 @@ use codex_core::features::FEATURES; use codex_core::features::Feature; use codex_core::models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_core::skills::model::SkillMetadata; -use codex_core::terminal::TerminalName; use codex_otel::RuntimeMetricsSummary; use codex_otel::SessionTelemetry; use codex_protocol::ThreadId; @@ -144,6 +143,7 @@ use codex_protocol::request_user_input::RequestUserInputQuestion; use codex_protocol::request_user_input::RequestUserInputQuestionOption; use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; +use codex_terminal_detection::TerminalName; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_approval_presets::builtin_approval_presets; use crossterm::event::KeyCode; diff --git a/codex-rs/tui_app_server/src/diff_render.rs b/codex-rs/tui_app_server/src/diff_render.rs index dd3990165..684d76b1e 100644 --- a/codex-rs/tui_app_server/src/diff_render.rs +++ b/codex-rs/tui_app_server/src/diff_render.rs @@ -93,9 +93,9 @@ use crate::terminal_palette::indexed_color; use crate::terminal_palette::rgb_color; use crate::terminal_palette::stdout_color_level; use codex_core::git_info::get_git_repo_root; -use codex_core::terminal::TerminalName; -use codex_core::terminal::terminal_info; use codex_protocol::protocol::FileChange; +use codex_terminal_detection::TerminalName; +use codex_terminal_detection::terminal_info; /// Classifies a diff line for gutter sign rendering and style selection. /// diff --git a/codex-rs/tui_app_server/src/lib.rs b/codex-rs/tui_app_server/src/lib.rs index 19cf079f5..567780657 100644 --- a/codex-rs/tui_app_server/src/lib.rs +++ b/codex-rs/tui_app_server/src/lib.rs @@ -38,7 +38,6 @@ use codex_core::format_exec_policy_error_with_source; use codex_core::path_utils; use codex_core::read_session_meta_line; use codex_core::state_db::get_state_db; -use codex_core::terminal::Multiplexer; use codex_core::windows_sandbox::WindowsSandboxLevelExt; use codex_protocol::ThreadId; use codex_protocol::config_types::AltScreenMode; @@ -49,6 +48,8 @@ use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; use codex_protocol::protocol::TurnContextItem; use codex_state::log_db; +use codex_terminal_detection::Multiplexer; +use codex_terminal_detection::terminal_info; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_oss::ensure_oss_provider_ready; use codex_utils_oss::get_default_model_for_oss_provider; @@ -1485,7 +1486,7 @@ fn determine_alt_screen_mode(no_alt_screen: bool, tui_alternate_screen: AltScree AltScreenMode::Always => true, AltScreenMode::Never => false, AltScreenMode::Auto => { - let terminal_info = codex_core::terminal::terminal_info(); + let terminal_info = terminal_info(); !matches!(terminal_info.multiplexer, Some(Multiplexer::Zellij { .. })) } }