mirror of
https://github.com/openai/codex.git
synced 2026-11-05 16:29:31 +00:00
Preserve terminal turn errors in replayed history (#35524)
## Why When rebuilding a thread from rollout events, errors embedded in turn completion events were ignored. Failed retries could therefore be restored as completed turns, causing warnings such as model-overload errors to disappear from the TUI transcript. ## What changed - Mark turns with terminal completion errors as failed and retain their message and structured error information. - Apply late completion errors to their matching historical turn without interrupting the active turn. ## Testing Added history-builder coverage for current and late completion errors, plus a TUI replay snapshot covering repeated overload failures. GitOrigin-RevId: 5c474baa0fd5c73368b444d79fb850cbd4c8023a
This commit is contained in:
1 parent
5a3808b77d
commit
9ca6df68da
3 files changed
+242
-5
No files matched your search
@@ -75,6 +75,54 @@ async fn resumed_initial_messages_render_history() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn replayed_failed_turns_preserve_overload_warnings_between_retries() {
|
||||
let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
let prompt = "The workspace also looks super confusing with its separator.";
|
||||
let error_message = "Selected model is at capacity. Please try a different model.";
|
||||
let failed_turn = |turn_id: &str, item_id: &str| AppServerTurn {
|
||||
items: vec![AppServerThreadItem::UserMessage {
|
||||
id: item_id.to_string(),
|
||||
client_id: None,
|
||||
content: vec![AppServerUserInput::Text {
|
||||
text: prompt.to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
}],
|
||||
..app_server_turn(
|
||||
turn_id,
|
||||
AppServerTurnStatus::Failed,
|
||||
/*duration_ms*/ None,
|
||||
/*error*/
|
||||
Some(AppServerTurnError {
|
||||
message: error_message.to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::ServerOverloaded),
|
||||
additional_details: None,
|
||||
}),
|
||||
)
|
||||
};
|
||||
|
||||
chat.replay_thread_turns(
|
||||
vec![
|
||||
failed_turn("turn-1", "user-1"),
|
||||
failed_turn("turn-2", "user-2"),
|
||||
],
|
||||
ReplayKind::ResumeInitialMessages,
|
||||
);
|
||||
|
||||
let rendered = drain_insert_history(&mut rx)
|
||||
.into_iter()
|
||||
.map(|lines| lines_to_single_string(&lines))
|
||||
.collect::<String>();
|
||||
|
||||
assert_eq!(rendered.matches(prompt).count(), 2);
|
||||
assert_eq!(rendered.matches(error_message).count(), 2);
|
||||
insta::assert_snapshot!(
|
||||
"replayed_failed_turns_preserve_overload_warnings_between_retries",
|
||||
rendered
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn restored_conversation_ultra_remains_selected_after_switching_to_plan() {
|
||||
let (mut chat, _rx, _ops) = make_chatwidget_manual(Some("gpt-5.4")).await;
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests/history_replay.rs
|
||||
expression: rendered
|
||||
---
|
||||
|
||||
› The workspace also looks super confusing with its separator.
|
||||
|
||||
|
||||
⚠ Selected model is at capacity. Please try a different model.
|
||||
|
||||
|
||||
› The workspace also looks super confusing with its separator.
|
||||
|
||||
|
||||
⚠ Selected model is at capacity. Please try a different model.
|
||||
Reference in new issue
Block a user