hide CoT by default; show headers in status indicator (#2316)
Plan is for full CoT summaries to be visible in a "transcript view" when we implement that, but for now they're hidden. https://github.com/user-attachments/assets/e8a1b0ef-8f2a-48ff-9625-9c3c67d92cdb
This commit is contained in:
@@ -1,10 +1,6 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests.rs
|
||||
assertion_line: 886
|
||||
expression: combined
|
||||
---
|
||||
thinking
|
||||
I will first analyze the request.
|
||||
|
||||
codex
|
||||
Here is the result.
|
||||
|
||||
@@ -2,8 +2,5 @@
|
||||
source: tui/src/chatwidget/tests.rs
|
||||
expression: combined
|
||||
---
|
||||
thinking
|
||||
I will first analyze the request.
|
||||
|
||||
codex
|
||||
Here is the result.
|
||||
|
||||
@@ -144,12 +144,12 @@ fn make_chatwidget_manual() -> (
|
||||
total_token_usage: TokenUsage::default(),
|
||||
last_token_usage: TokenUsage::default(),
|
||||
stream: StreamController::new(cfg),
|
||||
last_stream_kind: None,
|
||||
running_commands: HashMap::new(),
|
||||
pending_exec_completions: Vec::new(),
|
||||
task_complete_pending: false,
|
||||
interrupts: InterruptManager::new(),
|
||||
needs_redraw: false,
|
||||
reasoning_buffer: String::new(),
|
||||
session_id: None,
|
||||
frame_requester: crate::tui::FrameRequester::test_dummy(),
|
||||
};
|
||||
@@ -375,6 +375,11 @@ async fn binary_size_transcript_matches_ideal_fixture() {
|
||||
.expect("read ideal-binary-response.txt");
|
||||
// Normalize line endings for Windows vs. Unix checkouts
|
||||
let ideal = ideal.replace("\r\n", "\n");
|
||||
let ideal_first_line = ideal
|
||||
.lines()
|
||||
.find(|l| !l.trim().is_empty())
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
|
||||
// Build the final VT100 visual by parsing the ANSI stream. Trim trailing spaces per line
|
||||
// and drop trailing empty lines so the shape matches the ideal fixture exactly.
|
||||
@@ -400,22 +405,68 @@ async fn binary_size_transcript_matches_ideal_fixture() {
|
||||
while lines.last().is_some_and(|l| l.is_empty()) {
|
||||
lines.pop();
|
||||
}
|
||||
// Compare only after the last session banner marker, and start at the next 'thinking' line.
|
||||
// Compare only after the last session banner marker. Skip the transient
|
||||
// 'thinking' header if present, and start from the first non-empty line
|
||||
// of content that follows.
|
||||
const MARKER_PREFIX: &str = ">_ You are using OpenAI Codex in ";
|
||||
let last_marker_line_idx = lines
|
||||
.iter()
|
||||
.rposition(|l| l.starts_with(MARKER_PREFIX))
|
||||
.expect("marker not found in visible output");
|
||||
let thinking_line_idx = (last_marker_line_idx + 1..lines.len())
|
||||
.find(|&idx| lines[idx].trim_start() == "thinking")
|
||||
.expect("no 'thinking' line found after marker");
|
||||
// Anchor to the first ideal line if present; otherwise use heuristics.
|
||||
let start_idx = (last_marker_line_idx + 1..lines.len())
|
||||
.find(|&idx| lines[idx].trim_start() == ideal_first_line)
|
||||
.or_else(|| {
|
||||
// Prefer the first assistant content line (blockquote '>' prefix) after the marker.
|
||||
(last_marker_line_idx + 1..lines.len())
|
||||
.find(|&idx| lines[idx].trim_start().starts_with('>'))
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
// Fallback: first non-empty, non-'thinking' line
|
||||
(last_marker_line_idx + 1..lines.len())
|
||||
.find(|&idx| {
|
||||
let t = lines[idx].trim_start();
|
||||
!t.is_empty() && t != "thinking"
|
||||
})
|
||||
.expect("no content line found after marker")
|
||||
});
|
||||
|
||||
let mut compare_lines: Vec<String> = Vec::new();
|
||||
// Ensure the first line is exactly 'thinking' without leading spaces to match the fixture
|
||||
compare_lines.push(lines[thinking_line_idx].trim_start().to_string());
|
||||
compare_lines.extend(lines[(thinking_line_idx + 1)..].iter().cloned());
|
||||
// Ensure the first line is trimmed-left to match the fixture shape.
|
||||
compare_lines.push(lines[start_idx].trim_start().to_string());
|
||||
compare_lines.extend(lines[(start_idx + 1)..].iter().cloned());
|
||||
let visible_after = compare_lines.join("\n");
|
||||
|
||||
// Normalize: drop a leading 'thinking' line if present in either side to
|
||||
// avoid coupling to whether the reasoning header is rendered in history.
|
||||
fn drop_leading_thinking(s: &str) -> String {
|
||||
let mut it = s.lines();
|
||||
let first = it.next();
|
||||
let rest = it.collect::<Vec<_>>().join("\n");
|
||||
if first.is_some_and(|l| l.trim() == "thinking") {
|
||||
rest
|
||||
} else {
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
let visible_after = drop_leading_thinking(&visible_after);
|
||||
let ideal = drop_leading_thinking(&ideal);
|
||||
|
||||
// Normalize: strip leading Markdown blockquote markers ('>' or '> ') which
|
||||
// may be present in rendered transcript lines but not in the ideal text.
|
||||
fn strip_blockquotes(s: &str) -> String {
|
||||
s.lines()
|
||||
.map(|l| {
|
||||
l.strip_prefix("> ")
|
||||
.or_else(|| l.strip_prefix('>'))
|
||||
.unwrap_or(l)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
let visible_after = strip_blockquotes(&visible_after);
|
||||
let ideal = strip_blockquotes(&ideal);
|
||||
|
||||
// Optionally update the fixture when env var is set
|
||||
if std::env::var("UPDATE_IDEAL").as_deref() == Ok("1") {
|
||||
let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
@@ -746,7 +797,7 @@ fn plan_update_renders_history_cell() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn headers_emitted_on_stream_begin_for_answer_and_reasoning() {
|
||||
fn headers_emitted_on_stream_begin_for_answer_and_not_for_reasoning() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual();
|
||||
|
||||
// Answer: no header until a newline commit
|
||||
@@ -804,7 +855,7 @@ fn headers_emitted_on_stream_begin_for_answer_and_reasoning() {
|
||||
"expected 'codex' header to be emitted after first newline commit"
|
||||
);
|
||||
|
||||
// Reasoning: header immediately
|
||||
// Reasoning: do NOT emit a history header; status text is updated instead
|
||||
let (mut chat2, mut rx2, _op_rx2) = make_chatwidget_manual();
|
||||
chat2.handle_codex_event(Event {
|
||||
id: "sub-b".into(),
|
||||
@@ -828,8 +879,8 @@ fn headers_emitted_on_stream_begin_for_answer_and_reasoning() {
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
saw_thinking,
|
||||
"expected 'thinking' header to be emitted at stream start"
|
||||
!saw_thinking,
|
||||
"reasoning deltas should not emit history headers"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user