fix codex resume message at end of session (#3957)
This was only being printed when running the codex-tui executable directly, not via the codex-cli wrapper.
This commit is contained in:
3
codex-rs/Cargo.lock
generated
3
codex-rs/Cargo.lock
generated
@@ -638,9 +638,11 @@ dependencies = [
|
|||||||
"codex-protocol",
|
"codex-protocol",
|
||||||
"codex-protocol-ts",
|
"codex-protocol-ts",
|
||||||
"codex-tui",
|
"codex-tui",
|
||||||
|
"owo-colors",
|
||||||
"predicates",
|
"predicates",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"supports-color",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -931,7 +933,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"mcp-types",
|
"mcp-types",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"owo-colors",
|
|
||||||
"path-clean",
|
"path-clean",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
|
|||||||
@@ -26,8 +26,11 @@ codex-exec = { workspace = true }
|
|||||||
codex-login = { workspace = true }
|
codex-login = { workspace = true }
|
||||||
codex-mcp-server = { workspace = true }
|
codex-mcp-server = { workspace = true }
|
||||||
codex-protocol = { workspace = true }
|
codex-protocol = { workspace = true }
|
||||||
|
codex-protocol-ts = { workspace = true }
|
||||||
codex-tui = { workspace = true }
|
codex-tui = { workspace = true }
|
||||||
|
owo-colors = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
supports-color = { workspace = true }
|
||||||
tokio = { workspace = true, features = [
|
tokio = { workspace = true, features = [
|
||||||
"io-std",
|
"io-std",
|
||||||
"macros",
|
"macros",
|
||||||
@@ -37,7 +40,6 @@ tokio = { workspace = true, features = [
|
|||||||
] }
|
] }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
codex-protocol-ts = { workspace = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_cmd = { workspace = true }
|
assert_cmd = { workspace = true }
|
||||||
|
|||||||
@@ -14,8 +14,11 @@ use codex_cli::login::run_logout;
|
|||||||
use codex_cli::proto;
|
use codex_cli::proto;
|
||||||
use codex_common::CliConfigOverrides;
|
use codex_common::CliConfigOverrides;
|
||||||
use codex_exec::Cli as ExecCli;
|
use codex_exec::Cli as ExecCli;
|
||||||
|
use codex_tui::AppExitInfo;
|
||||||
use codex_tui::Cli as TuiCli;
|
use codex_tui::Cli as TuiCli;
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use supports_color::Stream;
|
||||||
|
|
||||||
mod mcp_cmd;
|
mod mcp_cmd;
|
||||||
|
|
||||||
@@ -156,6 +159,41 @@ struct GenerateTsCommand {
|
|||||||
prettier: Option<PathBuf>,
|
prettier: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn format_exit_messages(exit_info: AppExitInfo, color_enabled: bool) -> Vec<String> {
|
||||||
|
let AppExitInfo {
|
||||||
|
token_usage,
|
||||||
|
conversation_id,
|
||||||
|
} = exit_info;
|
||||||
|
|
||||||
|
if token_usage.is_zero() {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut lines = vec![format!(
|
||||||
|
"{}",
|
||||||
|
codex_core::protocol::FinalOutput::from(token_usage)
|
||||||
|
)];
|
||||||
|
|
||||||
|
if let Some(session_id) = conversation_id {
|
||||||
|
let resume_cmd = format!("codex resume {session_id}");
|
||||||
|
let command = if color_enabled {
|
||||||
|
resume_cmd.cyan().to_string()
|
||||||
|
} else {
|
||||||
|
resume_cmd
|
||||||
|
};
|
||||||
|
lines.push(format!("To continue this session, run {command}."));
|
||||||
|
}
|
||||||
|
|
||||||
|
lines
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_exit_messages(exit_info: AppExitInfo) {
|
||||||
|
let color_enabled = supports_color::on(Stream::Stdout).is_some();
|
||||||
|
for line in format_exit_messages(exit_info, color_enabled) {
|
||||||
|
println!("{line}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
|
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
|
||||||
cli_main(codex_linux_sandbox_exe).await?;
|
cli_main(codex_linux_sandbox_exe).await?;
|
||||||
@@ -176,13 +214,8 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||||||
&mut interactive.config_overrides,
|
&mut interactive.config_overrides,
|
||||||
root_config_overrides.clone(),
|
root_config_overrides.clone(),
|
||||||
);
|
);
|
||||||
let usage = codex_tui::run_main(interactive, codex_linux_sandbox_exe).await?;
|
let exit_info = codex_tui::run_main(interactive, codex_linux_sandbox_exe).await?;
|
||||||
if !usage.token_usage.is_zero() {
|
print_exit_messages(exit_info);
|
||||||
println!(
|
|
||||||
"{}",
|
|
||||||
codex_core::protocol::FinalOutput::from(usage.token_usage)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Some(Subcommand::Exec(mut exec_cli)) => {
|
Some(Subcommand::Exec(mut exec_cli)) => {
|
||||||
prepend_config_flags(
|
prepend_config_flags(
|
||||||
@@ -372,6 +405,8 @@ fn print_completion(cmd: CompletionCommand) {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use codex_core::protocol::TokenUsage;
|
||||||
|
use codex_protocol::mcp_protocol::ConversationId;
|
||||||
|
|
||||||
fn finalize_from_args(args: &[&str]) -> TuiCli {
|
fn finalize_from_args(args: &[&str]) -> TuiCli {
|
||||||
let cli = MultitoolCli::try_parse_from(args).expect("parse");
|
let cli = MultitoolCli::try_parse_from(args).expect("parse");
|
||||||
@@ -393,6 +428,52 @@ mod tests {
|
|||||||
finalize_resume_interactive(interactive, root_overrides, session_id, last, resume_cli)
|
finalize_resume_interactive(interactive, root_overrides, session_id, last, resume_cli)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sample_exit_info(conversation: Option<&str>) -> AppExitInfo {
|
||||||
|
let token_usage = TokenUsage {
|
||||||
|
output_tokens: 2,
|
||||||
|
total_tokens: 2,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
AppExitInfo {
|
||||||
|
token_usage,
|
||||||
|
conversation_id: conversation
|
||||||
|
.map(ConversationId::from_string)
|
||||||
|
.map(Result::unwrap),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_exit_messages_skips_zero_usage() {
|
||||||
|
let exit_info = AppExitInfo {
|
||||||
|
token_usage: TokenUsage::default(),
|
||||||
|
conversation_id: None,
|
||||||
|
};
|
||||||
|
let lines = format_exit_messages(exit_info, false);
|
||||||
|
assert!(lines.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_exit_messages_includes_resume_hint_without_color() {
|
||||||
|
let exit_info = sample_exit_info(Some("123e4567-e89b-12d3-a456-426614174000"));
|
||||||
|
let lines = format_exit_messages(exit_info, false);
|
||||||
|
assert_eq!(
|
||||||
|
lines,
|
||||||
|
vec![
|
||||||
|
"Token usage: total=2 input=0 output=2".to_string(),
|
||||||
|
"To continue this session, run codex resume 123e4567-e89b-12d3-a456-426614174000."
|
||||||
|
.to_string(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_exit_messages_applies_color_when_enabled() {
|
||||||
|
let exit_info = sample_exit_info(Some("123e4567-e89b-12d3-a456-426614174000"));
|
||||||
|
let lines = format_exit_messages(exit_info, true);
|
||||||
|
assert_eq!(lines.len(), 2);
|
||||||
|
assert!(lines[1].contains("\u{1b}[36m"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn resume_model_flag_applies_when_no_root_flags() {
|
fn resume_model_flag_applies_when_no_root_flags() {
|
||||||
let interactive = finalize_from_args(["codex", "resume", "-m", "gpt-5-test"].as_ref());
|
let interactive = finalize_from_args(["codex", "resume", "-m", "gpt-5-test"].as_ref());
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ unicode-segmentation = { workspace = true }
|
|||||||
unicode-width = { workspace = true }
|
unicode-width = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
pathdiff = { workspace = true }
|
pathdiff = { workspace = true }
|
||||||
owo-colors = { workspace = true }
|
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ use codex_arg0::arg0_dispatch_or_else;
|
|||||||
use codex_common::CliConfigOverrides;
|
use codex_common::CliConfigOverrides;
|
||||||
use codex_tui::Cli;
|
use codex_tui::Cli;
|
||||||
use codex_tui::run_main;
|
use codex_tui::run_main;
|
||||||
use owo_colors::OwoColorize;
|
|
||||||
use supports_color::Stream;
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct TopCli {
|
struct TopCli {
|
||||||
@@ -25,19 +23,8 @@ fn main() -> anyhow::Result<()> {
|
|||||||
.splice(0..0, top_cli.config_overrides.raw_overrides);
|
.splice(0..0, top_cli.config_overrides.raw_overrides);
|
||||||
let exit_info = run_main(inner, codex_linux_sandbox_exe).await?;
|
let exit_info = run_main(inner, codex_linux_sandbox_exe).await?;
|
||||||
let token_usage = exit_info.token_usage;
|
let token_usage = exit_info.token_usage;
|
||||||
let conversation_id = exit_info.conversation_id;
|
|
||||||
if !token_usage.is_zero() {
|
if !token_usage.is_zero() {
|
||||||
println!("{}", codex_core::protocol::FinalOutput::from(token_usage),);
|
println!("{}", codex_core::protocol::FinalOutput::from(token_usage),);
|
||||||
if let Some(session_id) = conversation_id {
|
|
||||||
let command = format!("codex resume {session_id}");
|
|
||||||
let prefix = "To continue this session, run ";
|
|
||||||
let suffix = ".";
|
|
||||||
if supports_color::on(Stream::Stdout).is_some() {
|
|
||||||
println!("{}{}{}", prefix, command.cyan(), suffix);
|
|
||||||
} else {
|
|
||||||
println!("{prefix}{command}{suffix}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user