Show streaming reasoning summaries in the TUI status row (#43921)

## What changed

- Update the status heading from the latest usable reasoning line and retain it through tool activity and empty reasoning items. Keep completed reasoning in the expanded transcript only.
- Restore active reasoning after resume, thread switches, and session refreshes, including when earlier events have left the replay buffer.
- Default new embedded TUI threads to `model_reasoning_summary = "detailed"`, honoring explicit summary settings. Keep `concurrent_reasoning_summaries` opt-in and disable it when summaries are `none`.
- Persist the request's captured reasoning summary setting in context updates and local and remote compaction checkpoints.
- Animate status text with a smooth, grapheme-aware shimmer that respects terminal colors and reduced motion.

## Testing

Add regression coverage for reasoning status updates, transcript visibility, resume and buffered replay, outbound summary configuration, and summary settings across all three compaction modes. Add shimmer snapshots and checks for smooth brightness changes and Unicode grapheme preservation.

GitOrigin-RevId: 725c7de20f23166d7a3da6daeca617add5cbc600
This commit is contained in:
Felipe Coury authored and copyberry committed 2026-09-08 21:41:02 +00:00
1 parent 78932f4493
commit 9ec33e1926
45 files changed
+1798 -90

No files matched your search

+2 -2
View File
@@ -4297,7 +4297,7 @@ impl Session {
.map(ResponseItemEnvelope::new)
.chain(retained_client_developer_messages)
.collect();
let turn_context_item = turn_context.to_turn_context_item();
let turn_context_item = step_context.to_turn_context_item();
self.replace_compacted_history(
context_items,
Some(turn_context_item),
@@ -4343,7 +4343,7 @@ impl Session {
let state = self.state.lock().await;
state.reference_context_item()
};
let turn_context_item = turn_context.to_turn_context_item();
let turn_context_item = step_context.to_turn_context_item();
let turn_context_changed = reference_context_item.as_ref() != Some(&turn_context_item);
let should_inject_full_context = reference_context_item.is_none();
let world_state = Arc::new(self.build_world_state_for_step(step_context).await?);
@@ -433,6 +433,27 @@ async fn submitted_sparse_updates_preserve_captured_steps_and_ordering() {
]
);
assert!(Arc::ptr_eq(&before.turn, &after.turn));
assert_eq!(
turn.to_turn_context_item().summary,
ReasoningSummary::Concise
);
// Even after the live update, an already-captured request retains its own
// summary setting in the durable context.
for step in [&before, &during, &after] {
let world_state = session
.record_context_updates_and_set_reference_context_item(step)
.await
.expect("record captured settings");
assert_eq!(
session.reference_context_item().await.unwrap().summary,
step.settings.reasoning_summary,
);
session.start_new_context_window(step, world_state).await;
assert_eq!(
session.reference_context_item().await.unwrap().summary,
step.settings.reasoning_summary,
);
}
assert_eq!(after.settings.model_info.as_ref(), &expected_destination);
let initial_budget = turn
.config
+12
View File
@@ -1,3 +1,5 @@
//! Request-scoped settings and capabilities, including the durable context snapshot.
use std::sync::Arc;
use crate::agents_md::LoadedAgentsMd;
@@ -10,6 +12,7 @@ use codex_exec_server::ExecutorCapabilityDiscoverySnapshot;
use codex_exec_server::ResolvedSelectedCapabilityRoot;
use codex_mcp::McpBinding;
use codex_otel::SessionTelemetry;
use codex_protocol::protocol::TurnContextItem;
/// Request-scoped state that may change between model sampling requests.
pub(crate) struct StepContext {
@@ -32,3 +35,12 @@ pub(crate) struct StepContext {
/// The canonical AGENTS.md value observed with this environment snapshot.
pub(crate) loaded_agents_md: Option<Arc<LoadedAgentsMd>>,
}
impl StepContext {
/// Persist the summary captured for this request, even after a live settings update.
pub(crate) fn to_turn_context_item(&self) -> TurnContextItem {
let mut item = self.turn.to_turn_context_item();
item.summary = self.settings.reasoning_summary;
item
}
}
+1 -1
View File
@@ -639,7 +639,7 @@ impl TurnContext {
realtime_active: Some(self.realtime_active),
cyber_access_program: self.cyber_access_program,
effort: self.reasoning_effort().cloned(),
summary: ReasoningSummaryConfig::Auto,
summary: self.reasoning_summary(),
}
}