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.
This commit is contained in:
Michael Bolin
2025-05-21 22:53:02 -07:00
committed by GitHub
parent 5746561428
commit ef7208359f
2 changed files with 43 additions and 12 deletions

View File

@@ -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.

View File

@@ -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.");