Skip to content

Commit 4788fb1

Browse files
authored
feat: add resume logs when doing /new (openai#6660)
<img width="769" height="803" alt="Screenshot 2025-11-14 at 10 25 49" src="https://github.com/user-attachments/assets/12fbc21e-cab9-4d0a-a484-1aeb60219f96" />
1 parent 6c384eb commit 4788fb1

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

codex-rs/tui/src/app.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use codex_core::ConversationManager;
2424
use codex_core::config::Config;
2525
use codex_core::config::edit::ConfigEditsBuilder;
2626
use codex_core::model_family::find_family_for_model;
27+
use codex_core::protocol::FinalOutput;
2728
use codex_core::protocol::SessionSource;
2829
use codex_core::protocol::TokenUsage;
2930
use codex_core::protocol_config_types::ReasoningEffort as ReasoningEffortConfig;
@@ -54,6 +55,29 @@ pub struct AppExitInfo {
5455
pub update_action: Option<UpdateAction>,
5556
}
5657

58+
fn session_summary(
59+
token_usage: TokenUsage,
60+
conversation_id: Option<ConversationId>,
61+
) -> Option<SessionSummary> {
62+
if token_usage.is_zero() {
63+
return None;
64+
}
65+
66+
let usage_line = FinalOutput::from(token_usage).to_string();
67+
let resume_command =
68+
conversation_id.map(|conversation_id| format!("codex resume {conversation_id}"));
69+
Some(SessionSummary {
70+
usage_line,
71+
resume_command,
72+
})
73+
}
74+
75+
#[derive(Debug, Clone, PartialEq, Eq)]
76+
struct SessionSummary {
77+
usage_line: String,
78+
resume_command: Option<String>,
79+
}
80+
5781
fn should_show_model_migration_prompt(
5882
current_model: &str,
5983
target_model: &str,
@@ -365,6 +389,10 @@ impl App {
365389
async fn handle_event(&mut self, tui: &mut tui::Tui, event: AppEvent) -> Result<bool> {
366390
match event {
367391
AppEvent::NewSession => {
392+
let summary = session_summary(
393+
self.chat_widget.token_usage(),
394+
self.chat_widget.conversation_id(),
395+
);
368396
let init = crate::chatwidget::ChatWidgetInit {
369397
config: self.config.clone(),
370398
frame_requester: tui.frame_requester(),
@@ -376,6 +404,14 @@ impl App {
376404
feedback: self.feedback.clone(),
377405
};
378406
self.chat_widget = ChatWidget::new(init, self.server.clone());
407+
if let Some(summary) = summary {
408+
let mut lines: Vec<Line<'static>> = vec![summary.usage_line.clone().into()];
409+
if let Some(command) = summary.resume_command {
410+
let spans = vec!["To continue this session, run ".into(), command.cyan()];
411+
lines.push(spans.into());
412+
}
413+
self.chat_widget.add_plain_history_lines(lines);
414+
}
379415
tui.frame_requester().schedule_frame();
380416
}
381417
AppEvent::InsertHistoryCell(cell) => {
@@ -970,4 +1006,31 @@ mod tests {
9701006
assert_eq!(nth, 1);
9711007
assert_eq!(prefill, "follow-up (edited)");
9721008
}
1009+
1010+
#[test]
1011+
fn session_summary_skip_zero_usage() {
1012+
assert!(session_summary(TokenUsage::default(), None).is_none());
1013+
}
1014+
1015+
#[test]
1016+
fn session_summary_includes_resume_hint() {
1017+
let usage = TokenUsage {
1018+
input_tokens: 10,
1019+
output_tokens: 2,
1020+
total_tokens: 12,
1021+
..Default::default()
1022+
};
1023+
let conversation =
1024+
ConversationId::from_string("123e4567-e89b-12d3-a456-426614174000").unwrap();
1025+
1026+
let summary = session_summary(usage, Some(conversation)).expect("summary");
1027+
assert_eq!(
1028+
summary.usage_line,
1029+
"Token usage: total=12 input=10 output=2"
1030+
);
1031+
assert_eq!(
1032+
summary.resume_command,
1033+
Some("codex resume 123e4567-e89b-12d3-a456-426614174000".to_string())
1034+
);
1035+
}
9731036
}

codex-rs/tui/src/chatwidget.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ use crate::history_cell;
8585
use crate::history_cell::AgentMessageCell;
8686
use crate::history_cell::HistoryCell;
8787
use crate::history_cell::McpToolCallCell;
88+
use crate::history_cell::PlainHistoryCell;
8889
use crate::markdown::append_markdown;
8990
#[cfg(target_os = "windows")]
9091
use crate::onboarding::WSL_INSTRUCTIONS;
@@ -2462,6 +2463,11 @@ impl ChatWidget {
24622463
self.request_redraw();
24632464
}
24642465

2466+
pub(crate) fn add_plain_history_lines(&mut self, lines: Vec<Line<'static>>) {
2467+
self.add_boxed_history(Box::new(PlainHistoryCell::new(lines)));
2468+
self.request_redraw();
2469+
}
2470+
24652471
pub(crate) fn add_error_message(&mut self, message: String) {
24662472
self.add_to_history(history_cell::new_error_event(message));
24672473
self.request_redraw();

0 commit comments

Comments
 (0)