simplify further

This commit is contained in:
jif-oai
2026-03-30 19:20:22 +02:00
parent 0257728856
commit 9e6edbb1bc
19 changed files with 361 additions and 203 deletions
@@ -1386,7 +1386,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: turn_id.to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
];
@@ -1457,7 +1459,9 @@ mod tests {
})),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-image".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
];
@@ -1772,7 +1776,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
];
@@ -2071,7 +2077,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-b".into(),
@@ -2105,7 +2113,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-b".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
];
@@ -2154,7 +2164,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-b".into(),
@@ -2188,7 +2200,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-b".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
];
@@ -2357,7 +2371,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-b".into(),
@@ -2372,7 +2388,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
EventMsg::AgentMessage(AgentMessageEvent {
message: "still in b".into(),
@@ -2381,7 +2399,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-b".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
];
@@ -2412,7 +2432,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-b".into(),
@@ -2462,7 +2484,9 @@ mod tests {
}),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-compact".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
];
@@ -2701,7 +2725,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
EventMsg::Error(ErrorEvent {
message: "request-level failure".into(),
@@ -2754,7 +2780,9 @@ mod tests {
}),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
];
@@ -2802,7 +2830,9 @@ mod tests {
RolloutItem::ResponseItem(hook_prompt),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
];
@@ -2847,7 +2877,9 @@ mod tests {
}),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-a".into(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
];
@@ -300,8 +300,9 @@ pub(crate) async fn apply_bespoke_event_handling(
outgoing.abort_pending_server_requests().await;
let turn_failed = thread_state.lock().await.turn_summary.last_error.is_some()
|| matches!(
_ev.error(),
Some(error) if error.affects_turn_status()
&_ev.outcome,
codex_protocol::protocol::TurnOutcome::Failed { error }
if error.affects_turn_status()
);
thread_watch_manager
.note_turn_completed(&conversation_id.to_string(), turn_failed)
@@ -2120,15 +2121,19 @@ async fn handle_turn_complete(
let (status, error) = match turn_summary.last_error {
Some(error) => (TurnStatus::Failed, Some(error)),
None => match event.error() {
Some(error) if error.affects_turn_status() => (
TurnStatus::Failed,
Some(TurnError {
message: error.message.clone(),
codex_error_info: error.codex_error_info.clone().map(Into::into),
additional_details: None,
}),
),
None => match &event.outcome {
codex_protocol::protocol::TurnOutcome::Failed { error }
if error.affects_turn_status() =>
{
(
TurnStatus::Failed,
Some(TurnError {
message: error.message.clone(),
codex_error_info: error.codex_error_info.clone().map(Into::into),
additional_details: None,
}),
)
}
_ => (TurnStatus::Completed, None),
},
};
+9 -3
View File
@@ -250,7 +250,9 @@ async fn on_event_updates_status_from_task_started() {
async fn on_event_updates_status_from_task_complete() {
let status = agent_status_from_event(&EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("done".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("done".to_string()),
},
}));
let expected = AgentStatus::Completed(Some("done".to_string()));
assert_eq!(status, Some(expected));
@@ -1133,7 +1135,9 @@ async fn multi_agent_v2_completion_ignores_dead_direct_parent() {
tester_turn.as_ref(),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: tester_turn.sub_id.clone(),
last_agent_message: Some("done".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("done".to_string()),
},
}),
)
.await;
@@ -1228,7 +1232,9 @@ async fn multi_agent_v2_completion_queues_message_for_direct_parent() {
tester_turn.as_ref(),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: tester_turn.sub_id.clone(),
last_agent_message: Some("done".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("done".to_string()),
},
}),
)
.await;
+33 -15
View File
@@ -315,6 +315,7 @@ use crate::protocol::TokenCountEvent;
use crate::protocol::TokenUsage;
use crate::protocol::TokenUsageInfo;
use crate::protocol::TurnDiffEvent;
use crate::protocol::TurnOutcome;
use crate::protocol::WarningEvent;
use crate::resolve_skill_dependencies_for_turn;
use crate::rollout::RolloutRecorder;
@@ -335,7 +336,6 @@ use crate::tasks::GhostSnapshotTask;
use crate::tasks::ReviewTask;
use crate::tasks::SessionTask;
use crate::tasks::SessionTaskContext;
use crate::tasks::TaskCompletion;
use crate::tools::ToolRouter;
use crate::tools::context::SharedTurnDiffTracker;
use crate::tools::js_repl::JsReplHandle;
@@ -5597,9 +5597,11 @@ pub(crate) async fn run_turn(
input: Vec<UserInput>,
prewarmed_client_session: Option<ModelClientSession>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
if input.is_empty() && !sess.has_pending_input().await {
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
let model_info = turn_context.model_info.clone();
@@ -5613,7 +5615,9 @@ pub(crate) async fn run_turn(
.is_err()
{
error!("Failed to run pre-sampling compact");
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
let skills_outcome = Some(turn_context.turn_skills.outcome.as_ref());
@@ -5643,7 +5647,11 @@ pub(crate) async fn run_turn(
.await
{
Ok(mcp_tools) => mcp_tools,
Err(_) if turn_context.apps_enabled() => return TaskCompletion::Completed(None),
Err(_) if turn_context.apps_enabled() => {
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
Err(_) => HashMap::new(),
}
} else {
@@ -5741,7 +5749,9 @@ pub(crate) async fn run_turn(
.collect::<Vec<_>>();
if run_pending_session_start_hooks(&sess, &turn_context).await {
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
let additional_contexts = if input.is_empty() {
Vec::new()
@@ -5761,7 +5771,9 @@ pub(crate) async fn run_turn(
user_prompt_submit_outcome.additional_contexts,
)
.await;
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
sess.record_user_prompt_and_emit_turn_item(turn_context.as_ref(), &input, response_item)
.await;
@@ -5924,7 +5936,9 @@ pub(crate) async fn run_turn(
.await
.is_err()
{
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
continue;
}
@@ -6036,10 +6050,12 @@ pub(crate) async fn run_turn(
}
}
if let Some(message) = abort_message {
return TaskCompletion::Failed(ErrorEvent {
message,
codex_error_info: None,
});
return TurnOutcome::Failed {
error: ErrorEvent {
message,
codex_error_info: None,
},
};
}
break;
}
@@ -6062,16 +6078,18 @@ pub(crate) async fn run_turn(
.to_string(),
codex_error_info: Some(CodexErrorInfo::BadRequest),
};
return TaskCompletion::Failed(error);
return TurnOutcome::Failed { error };
}
Err(e) => {
info!("Turn error: {e:#}");
return TaskCompletion::Failed(e.to_error_event(/*message_prefix*/ None));
return TurnOutcome::Failed {
error: e.to_error_event(/*message_prefix*/ None),
};
}
}
}
TaskCompletion::Completed(last_agent_message)
TurnOutcome::Succeeded { last_agent_message }
}
async fn run_pre_sampling_compact(
@@ -208,7 +208,9 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: first_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -232,7 +234,9 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: rolled_back_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
@@ -298,7 +302,9 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_inc
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: first_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -383,7 +389,9 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: first_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -406,7 +414,9 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: second_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -420,7 +430,9 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: standalone_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
@@ -489,7 +501,9 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: first_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -505,7 +519,9 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: assistant_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
@@ -569,7 +585,9 @@ async fn reconstruct_history_rollback_clears_history_and_metadata_when_exceeding
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: only_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
@@ -615,7 +633,9 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: user_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
// Standalone task turn (no UserMessage) should not consume rollback skips.
@@ -629,7 +649,9 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: standalone_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
@@ -679,7 +701,9 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: previous_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -831,7 +855,9 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: current_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
];
@@ -897,7 +923,9 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: previous_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
];
@@ -995,7 +1023,9 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: previous_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -1096,7 +1126,9 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: previous_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -1124,7 +1156,9 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: current_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
];
@@ -1203,7 +1237,9 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: previous_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
@@ -1348,7 +1384,9 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
turn_id: previous_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
},
)),
RolloutItem::EventMsg(EventMsg::TurnStarted(
+43 -19
View File
@@ -46,6 +46,7 @@ use crate::protocol::TokenCountEvent;
use crate::protocol::TokenUsage;
use crate::protocol::TokenUsageInfo;
use crate::protocol::TurnCompleteEvent;
use crate::protocol::TurnOutcome;
use crate::protocol::TurnStartedEvent;
use crate::protocol::UserMessageEvent;
use crate::rollout::policy::EventPersistenceMode;
@@ -54,7 +55,6 @@ use crate::rollout::recorder::RolloutRecorderParams;
use crate::state::TaskKind;
use crate::tasks::SessionTask;
use crate::tasks::SessionTaskContext;
use crate::tasks::TaskCompletion;
use crate::tools::ToolRouter;
use crate::tools::context::FunctionToolOutput;
use crate::tools::context::ToolInvocation;
@@ -1486,7 +1486,9 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
RolloutItem::ResponseItem(turn_one_assistant.clone()),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: first_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
@@ -1508,7 +1510,9 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
RolloutItem::ResponseItem(turn_two_assistant),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: rolled_back_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
])
.await;
@@ -1582,7 +1586,9 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
RolloutItem::ResponseItem(assistant_message("turn 1 assistant")),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: first_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
@@ -1597,7 +1603,9 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
}),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: compact_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
@@ -1621,7 +1629,9 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
RolloutItem::ResponseItem(assistant_message("turn 2 assistant")),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: rolled_back_turn_id,
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
])
.await;
@@ -1664,7 +1674,9 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
RolloutItem::ResponseItem(assistant_message("turn 1 assistant")),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
@@ -1684,7 +1696,9 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
RolloutItem::ResponseItem(assistant_message("turn 2 assistant")),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-2".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
@@ -1704,7 +1718,9 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
RolloutItem::ResponseItem(assistant_message("turn 3 assistant")),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-3".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
})),
])
.await;
@@ -3140,13 +3156,15 @@ async fn spawn_task_turn_span_inherits_dispatch_trace_context() {
_ctx: Arc<TurnContext>,
_input: Vec<UserInput>,
_cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
let mut trace = self
.captured_trace
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
*trace = current_span_w3c_trace_context();
TaskCompletion::Completed(None)
TurnOutcome::Succeeded {
last_agent_message: None,
}
}
}
@@ -4401,10 +4419,12 @@ impl SessionTask for NeverEndingTask {
_ctx: Arc<TurnContext>,
_input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
if self.listen_to_cancellation_token {
cancellation_token.cancelled().await;
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
loop {
sleep(Duration::from_secs(60)).await;
@@ -4428,11 +4448,13 @@ impl SessionTask for FailingTask {
_ctx: Arc<TurnContext>,
_input: Vec<UserInput>,
_cancellation_token: CancellationToken,
) -> TaskCompletion {
TaskCompletion::Failed(ErrorEvent {
message: "boom".to_string(),
codex_error_info: None,
})
) -> TurnOutcome {
TurnOutcome::Failed {
error: ErrorEvent {
message: "boom".to_string(),
codex_error_info: None,
},
}
}
}
@@ -4557,7 +4579,9 @@ async fn task_finish_emits_turn_item_lifecycle_for_leftover_pending_user_input()
sess.on_task_finished(
Arc::clone(&tc),
TaskCompletion::Completed(/*last_agent_message*/ None),
TurnOutcome::Succeeded {
last_agent_message: None,
},
)
.await;
+5 -3
View File
@@ -2,8 +2,8 @@ use std::sync::Arc;
use super::SessionTask;
use super::SessionTaskContext;
use super::TaskCompletion;
use crate::codex::TurnContext;
use crate::protocol::TurnOutcome;
use crate::state::TaskKind;
use async_trait::async_trait;
use codex_protocol::user_input::UserInput;
@@ -28,7 +28,7 @@ impl SessionTask for CompactTask {
ctx: Arc<TurnContext>,
input: Vec<UserInput>,
_cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
let session = session.clone_session();
let _ = if crate::compact::should_use_remote_compact_task(&ctx.provider) {
let _ = session.services.session_telemetry.counter(
@@ -45,6 +45,8 @@ impl SessionTask for CompactTask {
);
crate::compact::run_compact_task(session.clone(), ctx, input).await
};
TaskCompletion::Completed(None)
TurnOutcome::Succeeded {
last_agent_message: None,
}
}
}
+5 -3
View File
@@ -1,10 +1,10 @@
use crate::codex::TurnContext;
use crate::protocol::EventMsg;
use crate::protocol::TurnOutcome;
use crate::protocol::WarningEvent;
use crate::state::TaskKind;
use crate::tasks::SessionTask;
use crate::tasks::SessionTaskContext;
use crate::tasks::TaskCompletion;
use async_trait::async_trait;
use codex_git_utils::CreateGhostCommitOptions;
use codex_git_utils::GhostSnapshotReport;
@@ -43,7 +43,7 @@ impl SessionTask for GhostSnapshotTask {
ctx: Arc<TurnContext>,
_input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
tokio::task::spawn(async move {
let token = self.token;
let warnings_enabled = !ctx.ghost_snapshot.disable_warnings;
@@ -157,7 +157,9 @@ impl SessionTask for GhostSnapshotTask {
Err(err) => warn!("failed to mark ghost snapshot ready: {err}"),
}
});
TaskCompletion::Completed(None)
TurnOutcome::Succeeded {
last_agent_message: None,
}
}
}
+8 -18
View File
@@ -29,11 +29,11 @@ use crate::hook_runtime::inspect_pending_input;
use crate::hook_runtime::record_additional_contexts;
use crate::hook_runtime::record_pending_input;
use crate::models_manager::manager::ModelsManager;
use crate::protocol::ErrorEvent;
use crate::protocol::EventMsg;
use crate::protocol::TurnAbortReason;
use crate::protocol::TurnAbortedEvent;
use crate::protocol::TurnCompleteEvent;
use crate::protocol::TurnOutcome;
use crate::state::ActiveTurn;
use crate::state::RunningTask;
use crate::state::TaskKind;
@@ -100,11 +100,6 @@ pub(crate) struct SessionTaskContext {
session: Arc<Session>,
}
pub(crate) enum TaskCompletion {
Completed(Option<String>),
Failed(ErrorEvent),
}
impl SessionTaskContext {
pub(crate) fn new(session: Arc<Session>) -> Self {
Self { session }
@@ -146,7 +141,7 @@ pub(crate) trait SessionTask: Send + Sync + 'static {
/// `ctx`, returning an optional final agent message when finished. The
/// provided `cancellation_token` is cancelled when the session requests an
/// abort; implementers should watch for it and terminate quickly once it
/// fires. The returned [`TaskCompletion`] determines the single terminal
/// fires. The returned [`TurnOutcome`] determines the single terminal
/// event emitted by [`Session::on_task_finished`].
async fn run(
self: Arc<Self>,
@@ -154,7 +149,7 @@ pub(crate) trait SessionTask: Send + Sync + 'static {
ctx: Arc<TurnContext>,
input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion;
) -> TurnOutcome;
/// Gives the task a chance to perform cleanup after an abort.
///
@@ -320,7 +315,7 @@ impl Session {
pub async fn on_task_finished(
self: &Arc<Self>,
turn_context: Arc<TurnContext>,
completion: TaskCompletion,
outcome: TurnOutcome,
) {
turn_context
.turn_metadata_state
@@ -437,15 +432,10 @@ impl Session {
&[("token_type", "reasoning_output"), tmp_mem],
);
}
let event = match completion {
TaskCompletion::Completed(last_agent_message) => EventMsg::TurnComplete(
TurnCompleteEvent::succeeded(turn_context.sub_id.clone(), last_agent_message),
),
TaskCompletion::Failed(error) => EventMsg::TurnComplete(TurnCompleteEvent::failed(
turn_context.sub_id.clone(),
error,
)),
};
let event = EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: turn_context.sub_id.clone(),
outcome,
});
self.send_event(turn_context.as_ref(), event).await;
}
+5 -3
View File
@@ -7,6 +7,7 @@ use crate::codex::TurnContext;
use crate::codex::run_turn;
use crate::protocol::EventMsg;
use crate::protocol::TurnStartedEvent;
use crate::protocol::TurnOutcome;
use crate::session_startup_prewarm::SessionStartupPrewarmResolution;
use crate::state::TaskKind;
use codex_protocol::user_input::UserInput;
@@ -15,7 +16,6 @@ use tracing::trace_span;
use super::SessionTask;
use super::SessionTaskContext;
use super::TaskCompletion;
#[derive(Default)]
pub(crate) struct RegularTask;
@@ -42,7 +42,7 @@ impl SessionTask for RegularTask {
ctx: Arc<TurnContext>,
input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
let sess = session.clone_session();
let run_turn_span = trace_span!("run_turn");
// Regular turns emit `TurnStarted` inline so first-turn lifecycle does
@@ -59,7 +59,9 @@ impl SessionTask for RegularTask {
.await
{
SessionStartupPrewarmResolution::Cancelled => {
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
SessionStartupPrewarmResolution::Unavailable { .. } => None,
SessionStartupPrewarmResolution::Ready(prewarmed_client_session) => {
+4 -3
View File
@@ -32,7 +32,6 @@ use std::sync::LazyLock;
use super::SessionTask;
use super::SessionTaskContext;
use super::TaskCompletion;
static REVIEW_EXIT_SUCCESS_TEMPLATE: LazyLock<Template> = LazyLock::new(|| {
let normalized =
@@ -66,7 +65,7 @@ impl SessionTask for ReviewTask {
ctx: Arc<TurnContext>,
input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
let _ = session.session.services.session_telemetry.counter(
"codex.task.review",
/*inc*/ 1,
@@ -88,7 +87,9 @@ impl SessionTask for ReviewTask {
if !cancellation_token.is_cancelled() {
exit_review_mode(session.clone_session(), output.clone(), ctx.clone()).await;
}
TaskCompletion::Completed(None)
TurnOutcome::Succeeded {
last_agent_message: None,
}
}
async fn abort(&self, session: Arc<SessionTaskContext>, ctx: Arc<TurnContext>) {
+11 -5
View File
@@ -4,10 +4,10 @@ use crate::codex::TurnContext;
use crate::protocol::EventMsg;
use crate::protocol::UndoCompletedEvent;
use crate::protocol::UndoStartedEvent;
use crate::protocol::TurnOutcome;
use crate::state::TaskKind;
use crate::tasks::SessionTask;
use crate::tasks::SessionTaskContext;
use crate::tasks::TaskCompletion;
use async_trait::async_trait;
use codex_git_utils::RestoreGhostCommitOptions;
use codex_git_utils::restore_ghost_commit_with_options;
@@ -42,7 +42,7 @@ impl SessionTask for UndoTask {
ctx: Arc<TurnContext>,
_input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
let _ = session.session.services.session_telemetry.counter(
"codex.task.undo",
/*inc*/ 1,
@@ -66,7 +66,9 @@ impl SessionTask for UndoTask {
}),
)
.await;
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
}
let history = sess.clone_history().await;
@@ -91,7 +93,9 @@ impl SessionTask for UndoTask {
completed.message = Some("No ghost snapshot available to undo.".to_string());
sess.send_event(ctx.as_ref(), EventMsg::UndoCompleted(completed))
.await;
return TaskCompletion::Completed(None);
return TurnOutcome::Succeeded {
last_agent_message: None,
};
};
let commit_id = ghost_commit.id().to_string();
@@ -127,6 +131,8 @@ impl SessionTask for UndoTask {
sess.send_event(ctx.as_ref(), EventMsg::UndoCompleted(completed))
.await;
TaskCompletion::Completed(None)
TurnOutcome::Succeeded {
last_agent_message: None,
}
}
}
+5 -3
View File
@@ -24,6 +24,7 @@ use crate::protocol::ExecCommandSource;
use crate::protocol::ExecCommandStatus;
use crate::protocol::SandboxPolicy;
use crate::protocol::TurnStartedEvent;
use crate::protocol::TurnOutcome;
use crate::sandboxing::ExecRequest;
use crate::state::TaskKind;
use crate::tools::format_exec_output_str;
@@ -33,7 +34,6 @@ use codex_sandboxing::SandboxType;
use super::SessionTask;
use super::SessionTaskContext;
use super::TaskCompletion;
use crate::codex::Session;
use codex_protocol::models::ResponseInputItem;
use codex_protocol::models::ResponseItem;
@@ -79,7 +79,7 @@ impl SessionTask for UserShellCommandTask {
turn_context: Arc<TurnContext>,
_input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
execute_user_shell_command(
session.clone_session(),
turn_context,
@@ -88,7 +88,9 @@ impl SessionTask for UserShellCommandTask {
UserShellCommandMode::StandaloneTurn,
)
.await;
TaskCompletion::Completed(None)
TurnOutcome::Succeeded {
last_agent_message: None,
}
}
}
@@ -18,10 +18,10 @@ use crate::protocol::SandboxPolicy;
use crate::protocol::SessionSource;
use crate::protocol::SubAgentSource;
use crate::protocol::TurnCompleteEvent;
use crate::protocol::TurnOutcome;
use crate::state::TaskKind;
use crate::tasks::SessionTask;
use crate::tasks::SessionTaskContext;
use crate::tasks::TaskCompletion;
use crate::tools::context::ToolOutput;
use crate::tools::handlers::multi_agents_v2::AssignTaskHandler as AssignTaskHandlerV2;
use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2;
@@ -133,9 +133,11 @@ impl SessionTask for NeverEndingTask {
_ctx: Arc<TurnContext>,
_input: Vec<UserInput>,
cancellation_token: CancellationToken,
) -> TaskCompletion {
) -> TurnOutcome {
cancellation_token.cancelled().await;
TaskCompletion::Completed(None)
TurnOutcome::Succeeded {
last_agent_message: None,
}
}
}
@@ -155,11 +157,13 @@ impl SessionTask for FailingTask {
_ctx: Arc<TurnContext>,
_input: Vec<UserInput>,
_cancellation_token: CancellationToken,
) -> TaskCompletion {
TaskCompletion::Failed(ErrorEvent {
message: "boom".to_string(),
codex_error_info: None,
})
) -> TurnOutcome {
TurnOutcome::Failed {
error: ErrorEvent {
message: "boom".to_string(),
codex_error_info: None,
},
}
}
}
@@ -630,7 +634,9 @@ async fn multi_agent_v2_list_agents_returns_completed_status_and_last_task_messa
child_turn.as_ref(),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: child_turn.sub_id.clone(),
last_agent_message: Some("done".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("done".to_string()),
},
}),
)
.await;
@@ -1196,7 +1202,9 @@ async fn multi_agent_v2_assign_task_completion_notifies_parent_after_reuse() {
first_turn.as_ref(),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: first_turn.sub_id.clone(),
last_agent_message: Some("done once".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("done once".to_string()),
},
}),
)
.await;
@@ -1222,7 +1230,9 @@ async fn multi_agent_v2_assign_task_completion_notifies_parent_after_reuse() {
second_turn.as_ref(),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: second_turn.sub_id.clone(),
last_agent_message: Some("done twice".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("done twice".to_string()),
},
}),
)
.await;
@@ -1319,7 +1329,9 @@ async fn multi_agent_v2_failed_turn_forwards_only_error_status_after_reuse() {
first_turn.as_ref(),
EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: first_turn.sub_id.clone(),
last_agent_message: Some("done once".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("done once".to_string()),
},
}),
)
.await;
+2 -2
View File
@@ -134,7 +134,7 @@ async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> {
assert_eq!(assistant_message.message, "Completed first turn");
assert_eq!(completed.turn_id, started.turn_id);
assert_eq!(
completed.last_agent_message.as_deref(),
completed.last_agent_message().as_deref(),
Some("Completed first turn")
);
}
@@ -224,7 +224,7 @@ async fn resume_includes_initial_messages_from_reasoning_events() -> Result<()>
assert_eq!(assistant_message.message, "Completed reasoning turn");
assert_eq!(completed.turn_id, started.turn_id);
assert_eq!(
completed.last_agent_message.as_deref(),
completed.last_agent_message().as_deref(),
Some("Completed reasoning turn")
);
}
-30
View File
@@ -1872,36 +1872,6 @@ pub struct TurnCompleteEvent {
pub outcome: TurnOutcome,
}
impl TurnCompleteEvent {
pub fn succeeded(turn_id: String, last_agent_message: Option<String>) -> Self {
Self {
turn_id,
outcome: TurnOutcome::Succeeded { last_agent_message },
}
}
pub fn failed(turn_id: String, error: ErrorEvent) -> Self {
Self {
turn_id,
outcome: TurnOutcome::Failed { error },
}
}
pub fn last_agent_message(&self) -> Option<&str> {
match &self.outcome {
TurnOutcome::Succeeded { last_agent_message } => last_agent_message.as_deref(),
TurnOutcome::Failed { .. } => None,
}
}
pub fn error(&self) -> Option<&ErrorEvent> {
match &self.outcome {
TurnOutcome::Succeeded { .. } => None,
TurnOutcome::Failed { error } => Some(error),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
pub struct TurnStartedEvent {
pub turn_id: String,
+16 -10
View File
@@ -103,6 +103,8 @@ use codex_protocol::protocol::TurnAbortedEvent;
#[cfg(test)]
use codex_protocol::protocol::TurnCompleteEvent;
#[cfg(test)]
use codex_protocol::protocol::TurnOutcome;
#[cfg(test)]
use codex_protocol::protocol::TurnStartedEvent;
#[cfg(test)]
use std::time::Duration;
@@ -738,10 +740,12 @@ fn append_terminal_turn_events(events: &mut Vec<Event>, turn: &Turn, include_fai
match turn.status {
TurnStatus::Completed => events.push(Event {
id: String::new(),
msg: EventMsg::TurnComplete(TurnCompleteEvent::succeeded(
turn.id.clone(),
/*last_agent_message*/ None,
)),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: turn.id.clone(),
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
}),
TurnStatus::Interrupted => events.push(Event {
id: String::new(),
@@ -754,9 +758,10 @@ fn append_terminal_turn_events(events: &mut Vec<Event>, turn: &Turn, include_fai
let _ = include_failed_error;
events.push(Event {
id: String::new(),
msg: EventMsg::TurnComplete(TurnCompleteEvent::failed(
turn.id.clone(),
ErrorEvent {
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: turn.id.clone(),
outcome: TurnOutcome::Failed {
error: ErrorEvent {
message: turn
.error
.as_ref()
@@ -769,7 +774,8 @@ fn append_terminal_turn_events(events: &mut Vec<Event>, turn: &Turn, include_fai
.and_then(app_server_codex_error_info_to_core)
}),
},
)),
},
}),
});
}
TurnStatus::InProgress => {
@@ -1121,7 +1127,7 @@ mod tests {
panic!("expected turn complete event");
};
assert_eq!(completed.turn_id, turn_id);
assert_eq!(completed.last_agent_message, None);
assert_eq!(completed.last_agent_message(), None);
}
#[test]
@@ -1367,7 +1373,7 @@ mod tests {
panic!("expected turn complete event");
};
assert_eq!(completed.turn_id, turn_id);
assert_eq!(completed.last_agent_message, None);
assert_eq!(completed.last_agent_message(), None);
}
#[test]
+7 -7
View File
@@ -193,10 +193,8 @@ use codex_protocol::protocol::TerminalInteractionEvent;
use codex_protocol::protocol::TokenUsage;
use codex_protocol::protocol::TokenUsageInfo;
use codex_protocol::protocol::TurnAbortReason;
use codex_protocol::protocol::TurnCompleteEvent;
#[cfg(test)]
use codex_protocol::protocol::TurnDiffEvent;
use codex_protocol::protocol::TurnOutcome;
#[cfg(test)]
use codex_protocol::protocol::UndoCompletedEvent;
#[cfg(test)]
@@ -6927,14 +6925,16 @@ impl ChatWidget {
self.on_task_started();
}
}
EventMsg::TurnComplete(TurnCompleteEvent { outcome, .. }) => match outcome {
TurnOutcome::Succeeded { last_agent_message } => {
EventMsg::TurnComplete(codex_protocol::protocol::TurnCompleteEvent { outcome, .. }) => {
match outcome {
codex_protocol::protocol::TurnOutcome::Succeeded { last_agent_message } => {
self.on_task_complete(last_agent_message, from_replay);
}
TurnOutcome::Failed { error } => {
self.on_error(error.message);
codex_protocol::protocol::TurnOutcome::Failed { error } => {
self.on_error(error.message);
}
}
},
}
EventMsg::TokenCount(ev) => {
self.set_token_info(ev.info);
self.on_rate_limit_snapshot(ev.rate_limits);
+63 -21
View File
@@ -1741,7 +1741,9 @@ async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages
id: "turn-complete".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -1760,7 +1762,9 @@ async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages
id: "turn-complete-2".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-2".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -3275,7 +3279,9 @@ async fn plan_implementation_popup_skips_replayed_turn_complete() {
chat.replay_initial_messages(vec![EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Plan details".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Plan details".to_string()),
},
})]);
let popup = render_bottom_popup(&chat, /*width*/ 80);
@@ -3299,7 +3305,9 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com
chat.replay_initial_messages(vec![EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Plan details".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Plan details".to_string()),
},
})]);
let replay_popup = render_bottom_popup(&chat, /*width*/ 80);
assert!(
@@ -3311,7 +3319,9 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com
id: "live-turn-complete-1".to_string(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Plan details".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Plan details".to_string()),
},
}),
});
@@ -3332,7 +3342,9 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com
id: "live-turn-complete-2".to_string(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Plan details".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Plan details".to_string()),
},
}),
});
let duplicate_popup = render_bottom_popup(&chat, /*width*/ 80);
@@ -6463,7 +6475,9 @@ async fn unified_exec_wait_after_final_agent_message_snapshot() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Final response.".into()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Final response.".into()),
},
}),
});
@@ -6505,7 +6519,9 @@ async fn unified_exec_wait_before_streamed_agent_message_snapshot() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -6570,7 +6586,9 @@ async fn unified_exec_waiting_multiple_empty_snapshots() {
id: "turn-wait-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -6648,7 +6666,9 @@ async fn unified_exec_non_empty_then_empty_snapshots() {
id: "turn-wait-3".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -7150,7 +7170,9 @@ async fn slash_copy_state_tracks_turn_complete_final_reply() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Final reply **markdown**".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Final reply **markdown**".to_string()),
},
}),
});
@@ -7180,7 +7202,9 @@ async fn slash_copy_state_tracks_plan_item_completion() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -7213,7 +7237,9 @@ async fn slash_copy_state_is_preserved_during_running_task() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Previous completed reply".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Previous completed reply".to_string()),
},
}),
});
chat.on_task_started();
@@ -7232,7 +7258,9 @@ async fn slash_copy_state_clears_on_thread_rollback() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Reply that will be rolled back".to_string()),
outcome: TurnOutcome::Succeeded {
last_agent_message: Some("Reply that will be rolled back".to_string()),
},
}),
});
chat.handle_codex_event(Event {
@@ -7260,7 +7288,9 @@ async fn slash_copy_is_unavailable_when_legacy_agent_message_is_not_repeated_on_
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
let _ = drain_insert_history(&mut rx);
@@ -7301,7 +7331,9 @@ async fn slash_copy_uses_agent_message_item_when_turn_complete_omits_final_text(
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
let _ = drain_insert_history(&mut rx);
@@ -7346,7 +7378,9 @@ async fn slash_copy_does_not_return_stale_output_after_thread_rollback() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
let _ = drain_insert_history(&mut rx);
@@ -11230,7 +11264,9 @@ async fn turn_complete_keeps_unified_exec_processes() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -13172,7 +13208,9 @@ async fn status_line_branch_refreshes_after_turn_complete() {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -13474,7 +13512,9 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() {
id: "s1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
@@ -13945,7 +13985,9 @@ printf 'fenced within fenced\n'
id: "t1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: None,
outcome: TurnOutcome::Succeeded {
last_agent_message: None,
},
}),
});
for lines in drain_insert_history(&mut rx) {