From ef7208359f20f20a38781b14c9c13b31c20c67f4 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Wed, 21 May 2025 22:53:02 -0700 Subject: [PATCH] feat: show Config overview at start of exec (#1073) Now the `exec` output starts with something like: ``` -------- workdir: /Users/mbolin/code/codex/codex-rs model: o3 provider: openai approval: Never sandbox: SandboxPolicy { permissions: [DiskFullReadAccess, DiskWritePlatformUserTempFolder, DiskWritePlatformGlobalTempFolder, DiskWriteCwd, DiskWriteFolder { folder: "/Users/mbolin/.pyenv/shims" }] } -------- ``` which makes it easier to reason about when looking at logs. --- codex-rs/exec/src/event_processor.rs | 52 +++++++++++++++++++++------- codex-rs/exec/src/lib.rs | 3 ++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/codex-rs/exec/src/event_processor.rs b/codex-rs/exec/src/event_processor.rs index 65f2204d..676b47d6 100644 --- a/codex-rs/exec/src/event_processor.rs +++ b/codex-rs/exec/src/event_processor.rs @@ -1,5 +1,6 @@ use chrono::Utc; use codex_common::elapsed::format_elapsed; +use codex_core::config::Config; use codex_core::protocol::AgentMessageEvent; use codex_core::protocol::BackgroundEventEvent; use codex_core::protocol::ErrorEvent; @@ -13,7 +14,6 @@ use codex_core::protocol::McpToolCallEndEvent; use codex_core::protocol::PatchApplyBeginEvent; use codex_core::protocol::PatchApplyEndEvent; use codex_core::protocol::SessionConfiguredEvent; -use codex_core::protocol::TaskCompleteEvent; use owo_colors::OwoColorize; use owo_colors::Style; use shlex::try_join; @@ -103,9 +103,36 @@ macro_rules! ts_println { }}; } +/// Print a concise summary of the effective configuration that will be used +/// for the session. This mirrors the information shown in the TUI welcome +/// screen. +pub(crate) fn print_config_summary(config: &Config, with_ansi: bool) { + let bold = if with_ansi { + Style::new().bold() + } else { + Style::new() + }; + + ts_println!("OpenAI Codex (research preview)\n--------"); + + let entries = vec![ + ("workdir", config.cwd.display().to_string()), + ("model", config.model.clone()), + ("provider", config.model_provider_id.clone()), + ("approval", format!("{:?}", config.approval_policy)), + ("sandbox", format!("{:?}", config.sandbox_policy)), + ]; + + for (key, value) in entries { + println!("{} {}", format!("{key}: ").style(bold), value); + } + + println!("--------\n"); +} + impl EventProcessor { pub(crate) fn process_event(&mut self, event: Event) { - let Event { id, msg } = event; + let Event { id: _, msg } = event; match msg { EventMsg::Error(ErrorEvent { message }) => { let prefix = "ERROR:".style(self.red); @@ -114,15 +141,8 @@ impl EventProcessor { EventMsg::BackgroundEvent(BackgroundEventEvent { message }) => { ts_println!("{}", message.style(self.dimmed)); } - EventMsg::TaskStarted => { - let msg = format!("Task started: {id}"); - ts_println!("{}", msg.style(self.dimmed)); - } - EventMsg::TaskComplete(TaskCompleteEvent { - last_agent_message: _, - }) => { - let msg = format!("Task complete: {id}"); - ts_println!("{}", msg.style(self.bold)); + EventMsg::TaskStarted | EventMsg::TaskComplete(_) => { + // Ignore. } EventMsg::AgentMessage(AgentMessageEvent { message }) => { let prefix = "Agent message:".style(self.bold); @@ -385,7 +405,15 @@ impl EventProcessor { history_log_id: _, history_entry_count: _, } = session_configured_event; - println!("session {session_id} with model {model}"); + + ts_println!( + "{} {}", + "codex session".style(self.magenta).style(self.bold), + session_id.to_string().style(self.dimmed) + ); + + ts_println!("model: {}", model); + println!(); } EventMsg::GetHistoryEntryResponse(_) => { // Currently ignored in exec output. diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index d405a2d2..e615de79 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -18,6 +18,7 @@ use codex_core::protocol::SandboxPolicy; use codex_core::protocol::TaskCompleteEvent; use codex_core::util::is_inside_git_repo; use event_processor::EventProcessor; +use event_processor::print_config_summary; use tracing::debug; use tracing::error; use tracing::info; @@ -70,6 +71,8 @@ pub async fn run_main(cli: Cli) -> anyhow::Result<()> { model_provider: None, }; let config = Config::load_with_overrides(overrides)?; + // Print the effective configuration so users can see what Codex is using. + print_config_summary(&config, stdout_with_ansi); if !skip_git_repo_check && !is_inside_git_repo(&config) { eprintln!("Not inside a Git repo and --skip-git-repo-check was not specified.");